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 <TGeoPcon.h> // ROOT_TGeoPcon
44 #include <TGeoTorus.h> // ROOT_TGeoTorus
45 #include <TGeoCompositeShape.h>
47 #include <TVector2.h> // ROOT_TVector2
48 #include <TVector3.h> // ROOT_TVector3
49 //#include <TGeoMaterial.h> // ROOT_TGeoMaterial
50 //#include <TGeoMedium.h> // ROOT_TGeoMedium
51 //#include <TGeoPcon.h> // ROOT_TGeoPcon
52 //#include <TGeoPolygon.h> // ROOT_TGeoPolygon
54 #include "AliFMDGeometryBuilder.h" // ALIFMDGEOSIMULATOR_H
55 #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
56 #include "AliFMDDetector.h" // ALIFMDDETECTOR_H
57 #include "AliFMDRing.h" // ALIFMDRING_H
58 #include "AliFMD1.h" // ALIFMD1_H
59 #include "AliFMD2.h" // ALIFMD2_H
60 #include "AliFMD3.h" // ALIFMD3_H
61 // #include "AliFMD.h" // ALIFMD_H
62 #include "AliFMDDebug.h" // ALILOG_H
65 //====================================================================
66 ClassImp(AliFMDGeometryBuilder)
68 ; // This is here to keep Emacs for indenting the next line
71 //____________________________________________________________________
72 const Char_t* AliFMDGeometryBuilder::fgkActiveName = "F%cAC";
73 const Char_t* AliFMDGeometryBuilder::fgkSectorName = "F%cSC";
74 const Char_t* AliFMDGeometryBuilder::fgkStripName = "F%cST";
75 const Char_t* AliFMDGeometryBuilder::fgkSensorName = "F%cSE";
76 const Char_t* AliFMDGeometryBuilder::fgkPCBName = "F%cPB";
77 const Char_t* AliFMDGeometryBuilder::fgkCuName = "F%cCU";
78 const Char_t* AliFMDGeometryBuilder::fgkChipName = "F%cCH";
79 const Char_t* AliFMDGeometryBuilder::fgkLongLegName = "F%cLL";
80 const Char_t* AliFMDGeometryBuilder::fgkShortLegName = "F%cSL";
81 const Char_t* AliFMDGeometryBuilder::fgkFrontVName = "F%cFH";
82 const Char_t* AliFMDGeometryBuilder::fgkBackVName = "F%cBH";
83 const Char_t* AliFMDGeometryBuilder::fgkRingTopName = "F%cTV";
84 const Char_t* AliFMDGeometryBuilder::fgkRingBotName = "F%cBV";
85 const Char_t* AliFMDGeometryBuilder::fgkHCName = "F%dH%c";
86 const Char_t* AliFMDGeometryBuilder::fgkIHCName = "F%dI%c";
87 const Char_t* AliFMDGeometryBuilder::fgkNoseName = "F3SN";
88 const Char_t* AliFMDGeometryBuilder::fgkBackName = "F%dSB";
89 const Char_t* AliFMDGeometryBuilder::fgkTopName = "F%dSU";
90 const Char_t* AliFMDGeometryBuilder::fgkBeamName = "F%dSL";
91 const Char_t* AliFMDGeometryBuilder::fgkFlangeName = "F%dSF";
92 const Char_t* AliFMDGeometryBuilder::fgkFMDDCuName = "F%cDC";
93 const Char_t* AliFMDGeometryBuilder::fgkFMDDPCBName = "F%cDP";
94 const Char_t* AliFMDGeometryBuilder::fgkFMDDChipName = "F%cDI";
95 const Char_t* AliFMDGeometryBuilder::fgkFMDDName = "F%cDD";
96 const Char_t* AliFMDGeometryBuilder::fgkFMDName = "F%dM%c";
98 //____________________________________________________________________
99 AliFMDGeometryBuilder::AliFMDGeometryBuilder()
100 : TTask("FMD", "Geomtry builder"),
118 // Default constructor
122 //____________________________________________________________________
123 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed)
124 : TTask("FMD", "Geometry builder"),
142 // Normal constructor
146 // fmd Pointer to AliFMD object
147 // detailed Whether to make a detailed simulation or not
152 //____________________________________________________________________
154 AliFMDGeometryBuilder::MakeXTRU(const TObjArray& verticies,
155 Double_t thick) const
159 for (Int_t i = 0; i < 3; i++) {
160 TVector2* v = static_cast<TVector2*>(verticies.At(i+1));
166 TGeoXtru* shape = new TGeoXtru(2);
167 shape->DefinePolygon(xs.fN, xs.fArray, ys.fArray);
168 shape->DefineSection(0, -thick/2);
169 shape->DefineSection(1, +thick/2);
174 //____________________________________________________________________
176 AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r)
178 // Setup the geometry of a ring. The defined TGeoVolume is
179 // returned, and should be used when setting up the rest of the
185 // r Pointer to ring geometry object
188 // pointer to ring volume
191 AliError("Didn't get a ring object");
194 Char_t id = r->GetId();
195 Char_t rng = toupper(id);
196 const Char_t* lName = (rng == 'I' ? "inner" : "outer");
197 Double_t siThick = r->GetSiThickness();
198 Double_t pcbThick = r->GetPrintboardThickness();
199 Double_t cuThick = r->GetCopperThickness();
200 Double_t chipThick= r->GetChipThickness();
201 Double_t modSpace = r->GetModuleSpacing();
202 Double_t theta = r->GetTheta();
204 //------------------------------------------------------------------
207 TGeoShape* sensorShape = MakeXTRU(r->GetSensorVerticies(), siThick);
208 sensorShape->SetName(Form("FMD%c_physical_sensor", id));
209 sensorShape->SetTitle(Form("FMD %s physical sensor", lName));
210 TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id),
212 sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
213 sensorVolume->VisibleDaughters(kFALSE);
214 Int_t sid = sensorVolume->GetNumber();
225 // Virtual volume shape to divide - This volume is only defined if
226 // the geometry is set to be detailed.
227 TGeoTubeSeg* activeShape = new TGeoTubeSeg(r->GetLowR(),
232 activeShape->SetName(Form(fgkActiveName, id));
233 activeShape->SetTitle(Form("FMD %s active area", lName));
234 TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
236 activeVolume->SetTitle(Form("FMD %s active area", lName));
237 TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id),
241 Int_t ns = r->GetNStrips();
242 Double_t stripoff = r->GetLowR(); // 0; // a->Mod();
243 Double_t dstrip = (r->GetHighR() - stripoff) / ns;
245 sectorVolume->SetTitle(Form("FMD %s sector", lName));
246 TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id),
247 1, ns, stripoff, dstrip,
249 stripVolume->SetTitle(Form("FMD %s strip", lName));
250 sid = stripVolume->GetNumber();
251 sensorVolume->AddNodeOverlap(activeVolume, 0);
255 case 'I': fActiveId[0] = sid; break;
256 case 'O': fActiveId[1] = sid; break;
259 //------------------------------------------------------------------
261 // PCB layer of hybrid
262 TGeoShape* pcbShape = MakeXTRU(r->GetHybridVerticies(), pcbThick);
263 pcbShape->SetName(Form("FMD%c_hybrid_pcb", id));
264 pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
265 TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id), pcbShape, fPCB);
266 pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
269 TGeoShape* cuShape = MakeXTRU(r->GetHybridVerticies(), cuThick);
270 cuShape->SetName(Form("FMD%c_hybrid_copper", id));
271 cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
272 TGeoVolume* cuVolume = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper);
273 cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
276 TGeoShape* chipShape = MakeXTRU(r->GetHybridVerticies(), chipThick);
277 chipShape->SetName(Form("FMD%c_hybrid_chip", id));
278 chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
279 TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id),chipShape,fChip);
280 chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
282 //------------------------------------------------------------------
284 Double_t legr = r->GetLegRadius();
285 Double_t legl = r->GetLegLength();
289 TGeoTube* shortLegShape = new TGeoTube(0, legr, (legl-lege) / 2);
290 shortLegShape->SetName(Form(fgkShortLegName, id));
291 shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
292 TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id),
293 shortLegShape, fCopper);
294 shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
296 TGeoTube* longLegShape = new TGeoTube(0, legr,
297 (legl - lege + modSpace) / 2);
298 longLegShape->SetName(Form(fgkLongLegName, id));
299 longLegShape->SetTitle(Form("FMD %s long support foot", lName));
300 TGeoVolume* longLegVolume = new TGeoVolume(Form(fgkLongLegName, id),
301 longLegShape, fCopper);
302 longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
306 //------------------------------------------------------------------
307 // Placement of module volumes in assemblies
310 for (Int_t i = 0; i < 3; i++) {
311 TVector2* vv = r->GetFootPosition(i);
312 // TVector2 uu = vv->Rotate(TMath::Pi()/2);
317 // Back container volume
318 TGeoVolume* backVolume = new TGeoVolumeAssembly(Form(fgkBackVName, id));
319 backVolume->SetTitle(Form("FMD %s back module", lName));
320 TGeoVolume* frontVolume = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
321 frontVolume->SetTitle(Form("FMD %s front module", lName));
323 Double_t space = r->GetSpacing();
326 Double_t zb = siThick / 2;
327 Double_t zf = siThick / 2;
328 backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zb));
329 frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zf));
330 zb += siThick / 2 + space + pcbThick / 2;
331 zf += siThick / 2 + space + pcbThick / 2;
332 backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zb));
333 frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zf));
334 zb += (pcbThick + cuThick) / 2;
335 zf += (pcbThick + cuThick) / 2;
336 backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zf));
337 frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zb));
338 zb += (cuThick + chipThick) / 2;
339 zf += (cuThick + chipThick) / 2;
340 backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zb));
341 frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zf));
342 zb += pcbThick / 2 + (legl)/ 2 - lege;
343 zf += pcbThick / 2 + (legl + modSpace)/ 2 - lege;
344 for (Int_t i = 0; i < 3; i++) {
345 x = xfs[i]; // a->X() + legoff + legr;
347 backVolume->AddNode(shortLegVolume, i, new TGeoTranslation(x,y,zb));
348 frontVolume->AddNode(longLegVolume, i, new TGeoTranslation(x,y,zf));
351 //------------------------------------------------------------------
353 Double_t ddlr = r->GetFMDDLowR();
354 Double_t ddhr = r->GetFMDDHighR();
355 Double_t ddpt = r->GetFMDDPrintboardThickness();
356 Double_t ddct = r->GetFMDDCopperThickness();
357 Double_t ddit = r->GetFMDDChipThickness();
358 Double_t ddt = ddpt + ddct + ddit;
360 TString pcbName(Form(fgkFMDDPCBName, id));
361 TString cuName(Form(fgkFMDDCuName, id));
362 TString chipName(Form(fgkFMDDChipName, id));
363 new TGeoTubeSeg(Form("%s_inner", pcbName.Data()), ddlr, ddhr, ddpt/2,0,180);
364 new TGeoTubeSeg(Form("%s_inner", cuName.Data()), ddlr, ddhr, ddct/2,0,180);
365 new TGeoTubeSeg(Form("%s_inner", chipName.Data()), ddlr, ddhr, ddit/2,0,180);
380 new TGeoBBox(Form("%s_clip", pcbName.Data()), clipWX, clipWY, ddpt);
381 new TGeoBBox(Form("%s_clip", cuName.Data()), clipWX, clipWY, ddct);
382 new TGeoBBox(Form("%s_clip", chipName.Data()),clipWX, clipWY, ddit);
383 TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
386 trans->RegisterYourself();
387 TGeoShape* fmddPcbShape =
388 new TGeoCompositeShape(pcbName.Data(),
389 Form("%s_inner*%s_clip:%s_trans",
393 TGeoShape* fmddCuShape =
394 new TGeoCompositeShape(cuName.Data(),
395 Form("%s_inner*%s_clip:%s_trans",
399 TGeoShape* fmddChipShape =
400 new TGeoCompositeShape(chipName.Data(),
401 Form("%s_inner*%s_clip:%s_trans",
405 fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
406 fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
407 fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
409 TGeoVolume* fmddPcbVolume = new TGeoVolume(Form(fgkFMDDPCBName, id),
411 TGeoVolume* fmddCuVolume = new TGeoVolume(Form(fgkFMDDCuName, id),
412 fmddCuShape, fCopper);
413 TGeoVolume* fmddChipVolume= new TGeoVolume(Form(fgkFMDDChipName, id),
414 fmddChipShape, fChip);
415 fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
416 fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
417 fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
419 //------------------------------------------------------------------
420 // Half ring mother volumes.
421 TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
422 TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
423 TGeoVolume* halfRing = ringTopVolume;
424 ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
425 ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
427 //------------------------------------------------------------------
428 // Adding modules to half-rings
429 Int_t nmod = r->GetNModules();
430 AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
431 for (Int_t i = 0; i < nmod; i++) {
432 if (i == nmod / 2) halfRing = ringBotVolume;
433 Bool_t front = (i % 2 == (rng == 'I' ? 1 : 0));
434 TGeoVolume* vol = (front ? frontVolume : backVolume);
435 // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
436 Double_t z1 = (front ? -1 : 1) * modSpace / 2;
437 // Double_t z1 = (front ? 0 : modSpace);
438 Double_t th = (2 * i + 1) * theta;
439 TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0);
441 mat1->SetName(Form("FMD%c_module_%02d", id, i));
442 mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
443 halfRing->AddNode(vol, i, mat1);
446 //------------------------------------------------------------------
448 Double_t zi = r->GetFullDepth() - ddt;
450 for (Int_t i = 0; i < n; i++) {
451 halfRing = (i == 0 ? ringTopVolume : ringBotVolume);
452 Double_t phi = 360. / n * i;
453 TGeoRotation* rot = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
455 rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
456 Double_t z = zi + ddpt / 2;
457 halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
458 z += (ddpt + ddct) / 2;
459 halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
460 z += (ddct + ddit) / 2;
461 halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
469 //____________________________________________________________________
471 AliFMDGeometryBuilder::HoneycombShape(Int_t id, Char_t ring,
472 double r1, double r2,
473 double w, double t, double c)
475 // Make a honey comb shape from passed parameters.
477 // id Detector identifier (1,2, or 3)
478 // ring Ring identifier ('I' or 'O')
482 // t Thickness of material
483 // c Clearing from horizontal.
485 // Pointer to newly allocated composite shape.
486 TString form = Form("FMD%d%c_%%c_%%c", id, ring);
487 double a1 = TMath::ATan2(c, r1) * 180 / TMath::Pi();
489 TString fn = Form(form.Data(),'F','1');
490 TString bn = Form(form.Data(),'B','1');
491 TString cn = Form(form.Data(),'C','O');
492 TString in = Form(form.Data(),'R','I');
493 TString on = Form(form.Data(),'R','O');
494 TString en = Form(form.Data(),'E','X');
496 double x = r1 * TMath::Cos(TMath::Pi()*a1/180);
497 new TGeoTubeSeg(fn.Data(),r1,r2,t/2,0,180);
498 new TGeoTubeSeg(bn.Data(),r1,r2,t/2,0,180);
499 new TGeoBBox(cn.Data(),(r2-r1)/2,t/2,w/2);
500 new TGeoTubeSeg(in.Data(),r1,r1+t,w/2,0,180);
501 new TGeoTubeSeg(on.Data(),r2-t,r2,w/2,0,180);
502 new TGeoBBox(en.Data(),r2+.005,c/2+.005,w/2+.005);
504 TString ftn = Form(form.Data(),'F','T');
505 TString btn = Form(form.Data(),'F','B');
506 TString ltn = Form(form.Data(),'C','L');
507 TString rtn = Form(form.Data(),'C','R');
508 TString etn = Form(form.Data(),'E','X');
509 (new TGeoTranslation(ftn.Data(),0,0,+w/2-t/2))->RegisterYourself();
510 (new TGeoTranslation(btn.Data(),0,0,-w/2+t/2))->RegisterYourself();
511 (new TGeoTranslation(ltn.Data(),-(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
512 (new TGeoTranslation(rtn.Data(),(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
513 (new TGeoTranslation(etn.Data(),0, c/2,0))->RegisterYourself();
515 TString comp(Form("(%s:%s+%s:%s+%s+%s+%s:%s+%s:%s)-%s:%s",
516 fn.Data(),ftn.Data(),
517 bn.Data(),btn.Data(),
519 cn.Data(),ltn.Data(),
520 cn.Data(),rtn.Data(),
521 en.Data(),etn.Data()));
522 TGeoCompositeShape* shape = new TGeoCompositeShape(comp.Data());
523 shape->SetName(Form(fgkHCName,id,ring));
524 shape->SetTitle(Form("FMD%d%c Honeycomb shape", id, ring));
528 //____________________________________________________________________
530 AliFMDGeometryBuilder::TensionBox()
532 static TGeoVolumeAssembly* tensionBox = 0;
533 if (tensionBox) return tensionBox;
535 TGeoBBox* tensionEndS = new TGeoBBox("FMD_tension_end", .6, 3, .25);
536 TGeoBBox* tensionTopS = new TGeoBBox("FMD_tension_top", .1, .5, 3.5);
537 TGeoVolume* tensionEndV = new TGeoVolume("FMD_tension_end", tensionEndS,fAl);
538 TGeoVolume* tensionTopV = new TGeoVolume("FMD_tension_top", tensionTopS,fAl);
539 tensionBox = new TGeoVolumeAssembly("FMD_tension_box");
540 tensionBox->AddNode(tensionEndV, 1, new TGeoTranslation(.6, 0, -3.75));
541 tensionBox->AddNode(tensionEndV, 2, new TGeoTranslation(.6, 0, +3.75));
542 tensionBox->AddNode(tensionTopV, 1, new TGeoTranslation(0.1, +2.5, 0));
543 tensionBox->AddNode(tensionTopV, 2, new TGeoTranslation(0.1, -2.5, 0));
544 tensionBox->AddNode(tensionTopV, 3, new TGeoTranslation(1.1, +2.5, 0));
545 tensionBox->AddNode(tensionTopV, 4, new TGeoTranslation(1.1, -2.5, 0));
550 //____________________________________________________________________
552 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d,
553 TGeoVolume* topMother,
554 TGeoVolume* botMother,
556 TGeoVolume* innerTop,
557 TGeoVolume* innerBot,
558 TGeoVolume* outerTop,
559 TGeoVolume* outerBot)
561 // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
562 // This includes putting the Honeycomb support plates and the rings
563 // into the mother volumes.
566 // d The detector geometry to use
567 // mother The mother volume of the detector
568 // zmother The midpoint in global coordinates of detector vol.
569 // inner Pointer to inner ring volume
570 // outer Pointer to outer ring volume
573 // Pointer to mother (detector volume)
576 // Loop over the defined rings
577 for (int i = 0; i < 2; i++) {
582 TGeoVolume* tvol = 0;
583 TGeoVolume* bvol = 0;
587 lowr = d->GetInnerHoneyLowR();
588 highr = d->GetInnerHoneyHighR();
595 lowr = d->GetOuterHoneyLowR();
596 highr = d->GetOuterHoneyHighR();
603 Char_t c = r->GetId();
604 Int_t id = d->GetId();
605 Double_t hcThick = r->GetHoneycombThickness();
606 Double_t alThick = r->GetAlThickness();
607 Double_t z = TMath::Abs(rz - zMother);
609 // Place ring in mother volume
610 // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
611 AliFMDDebug(2, ("Placing volumes %s and %s in %s and %s at z=%f",
612 tvol->GetName(), bvol->GetName(),
613 topMother->GetName(), botMother->GetName(), z));
614 topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
615 botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
618 TGeoShape* hcSha = HoneycombShape(id, c, lowr, highr, hcThick, alThick);
619 TGeoVolume* hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
620 hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
622 z += (r->GetModuleDepth()
623 + r->GetModuleSpacing() / 2
624 + r->GetHoneycombThickness() / 2);
626 AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f",
627 hcVol->GetName(), topMother->GetName(),
628 botMother->GetName(), z));
630 topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
633 TGeoMatrix* bhcMatrix = new TGeoCombiTrans(0,0,z,0);
634 bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
635 bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
636 bhcMatrix->RotateZ(180);
637 botMother->AddNode(hcVol, 1, bhcMatrix);
642 //____________________________________________________________________
644 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1,
645 TGeoVolume* innerTop,
646 TGeoVolume* innerBot)
648 // Setup the FMD1 geometry. The FMD1 only has one ring, and no
649 // special support as it is at the momement.
651 // See also AliFMDGeometryBuilder::DetectorGeometry
653 if (!fmd1 || !innerTop || !innerBot) return 0;
654 AliFMDRing* r = fmd1->GetInner();
655 Double_t z = fmd1->GetInnerZ();
657 // `Top' or `Outside' master volume
658 TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
659 fmd1->GetId(), 'T'));
660 fmd1TopVolume->SetTitle("FMD1 top half");
662 // `Bottom' or `Inside' master volume
663 TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
664 fmd1->GetId(), 'B'));
665 fmd1BotVolume->SetTitle("FMD1 bottom half");
667 // Basic detector geometry
668 DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z,
669 innerTop, innerBot, 0, 0);
671 Double_t lidP[][3] = { { 0.00, 4.20, 20.95 },
672 { 0.15, 4.20, 20.95 },
673 { 0.15, 20.80, 20.95 },
674 { 3.00, 20.80, 20.95 },
675 { 3.00, 20.80, 22.30 },
676 { 3.15, 20.80, 22.30 },
677 { 3.15, 20.95, 24.65 },
678 { 3.30, 20.95, 24.65 },
679 { 3.30, 24.50, 24.65 },
680 { 6.80, 24.50, 24.65 },
681 { 6.80, 24.50, 26.00 },
682 { 6.95, 24.50, 26.00 } };
683 TGeoPcon* lidBaseS = new TGeoPcon("FMD1_lid_base", 0, 180, 12);
684 for (size_t i = 0; i < 12; i++)
685 lidBaseS->DefineSection(i, lidP[i][0], lidP[i][1], lidP[i][2]);
688 Double_t lidH[][2] = { { 7.84903, 24.15680 },
689 { 20.54900, 14.92970 },
690 { 21.99700, 12.70000 },
691 { 25.26090, 2.65502 } };
692 Double_t lidHR = .53 / 2;
693 Double_t lidHL = 0.16;
695 new TGeoTube("FMD1_lid_hole", 0, lidHR, lidHL/2);
696 TString lidComp("FMD1_lid_base-(");
697 TGeoTranslation* trans = 0;
698 for (size_t i = 0; i < 4; i++) {
699 trans = new TGeoTranslation(-lidH[i][0], lidH[i][1], 6.95-lidHL/2);
700 trans->SetName(Form("FMD1_lid_hole_mat%d", 2*i+0));
701 trans->RegisterYourself();
702 trans = new TGeoTranslation(+lidH[i][0], lidH[i][1], 6.95-lidHL/2);
703 trans->SetName(Form("FMD1_lid_hole_mat%d", 2*i+1));
704 trans->RegisterYourself();
705 lidComp.Append(Form("FMD1_lid_hole:FMD1_lid_hole_mat%d+"
706 "FMD1_lid_hole:FMD1_lid_hole_mat%d%c",
707 2 * i, 2 * i + 1, i == 3 ? ')' : '+'));
709 TGeoCompositeShape* lidS = new TGeoCompositeShape(lidComp.Data());
710 lidS->SetName("FMD1_lid");
711 TGeoVolume* lidV = new TGeoVolume("FMD1_lid", lidS, fC);
712 lidV->SetTransparency(63);
715 Double_t lidZ = -(3.3 - r->GetModuleDepth() - r->GetModuleSpacing() / 2);
716 AliFMDDebug(1, ("FMD1 lid offset in Z=%f", lidZ));
718 for (Int_t i = 0; i < 2; i++) {
719 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
720 Double_t phi = 360. / 2 * i;
721 TGeoRotation* rot = new TGeoRotation(Form("FMD1_lid_rot%d",i));
723 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1_lid_mat%d", i),
725 mother->AddNode(lidV, i, matrix);
728 // Must add this after filling the assembly.
729 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
730 // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
731 TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
733 TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
735 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
736 fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
737 top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
738 top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
741 // Survey points on V0A (screw holes for the FMD)
742 const Double_t icb[] = { +12.700, -21.997, 324.670 };
743 const Double_t ict[] = { +12.700, +21.997, 324.670 };
744 const Double_t ocb[] = { -12.700, -21.997, 324.670 };
745 const Double_t oct[] = { -12.700, +21.997, 324.670 };
747 TGeoTube* surveyShape = new TGeoTube("FMD1_survey_marker",
750 TGeoMatrix* outMat = matrix;
752 if (gGeoManager->cd("/ALIC_1/F1MT_1"))
753 outMat = gGeoManager->GetCurrentMatrix();
755 AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
758 Double_t loct[3], locb[3];
759 outMat->MasterToLocal(oct, loct);
760 outMat->MasterToLocal(ocb, locb);
761 TGeoVolume* vOct = new TGeoVolume("V0L_OCT", surveyShape, fPlastic);
762 TGeoVolume* vOcb = new TGeoVolume("V0L_OCB", surveyShape, fPlastic);
764 fmd1TopVolume->AddNode(vOct, 1, new TGeoTranslation(loct[0],loct[1],loct[2]));
765 fmd1TopVolume->AddNode(vOcb, 1, new TGeoTranslation(locb[0],locb[1],locb[2]));
768 TGeoMatrix* inMat = matrix;
770 if (gGeoManager->cd("/ALIC_1/F1MT_1"))
771 inMat = gGeoManager->GetCurrentMatrix();
773 AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
776 Double_t lict[3], licb[3];
777 inMat->MasterToLocal(ict, lict);
778 inMat->MasterToLocal(icb, licb);
779 TGeoVolume* vIct = new TGeoVolume("V0L_ICT", surveyShape, fPlastic);
780 TGeoVolume* vIcb = new TGeoVolume("V0L_ICB", surveyShape, fPlastic);
782 fmd1BotVolume->AddNode(vIct, 1, new TGeoTranslation(lict[0],lict[1],lict[2]));
783 fmd1BotVolume->AddNode(vIcb, 1, new TGeoTranslation(licb[0],licb[1],licb[2]));
788 //____________________________________________________________________
790 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2,
791 TGeoVolume* innerTop,
792 TGeoVolume* innerBot,
793 TGeoVolume* outerTop,
794 TGeoVolume* outerBot)
796 // Setup the FMD2 geometry. The FMD2 has no
797 // special support as it is at the momement.
799 // See also AliFMDGeometryBuilder::DetectorGeometry
801 if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
802 AliFMDRing* r = fmd2->GetOuter();
803 Double_t z = fmd2->GetOuterZ();
804 Double_t framelr = 32.01; // fmd2->GetOuterHoneyHighR()+0.5;
805 Double_t framehr = 33.611; // fmd2->GetOuterHoneyHighR()+1.8;
806 Double_t framel = 14.8; // framehz - framelz;
807 // Double_t backth = 0.3;
808 Double_t backth = 0.03;
809 Double_t framelz = -(2.38
810 - r->GetModuleDepth()
811 - r->GetModuleSpacing() / 2);
812 // Double_t framelz = -0.8;
813 // Double_t framehz = framelz + backth + framel;
814 Double_t coverlr = 4.3; // fmd2->GetInner()->GetLowR()+1;
815 Double_t coverhr = framehr; // - 1;
817 TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
818 fmd2->GetId(), 'T'));
819 TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
820 fmd2->GetId(), 'B'));
821 fmd2TopVolume->SetTitle("FMD2 top half");
822 fmd2BotVolume->SetTitle("FMD2 bottom half");
824 DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z,
825 innerTop, innerBot, outerTop, outerBot);
827 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("FMD2_support");
828 TGeoShape* cylinderShape = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
829 TGeoVolume* cylinderVolume = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
831 TGeoShape* coverShape = new TGeoTubeSeg(coverlr,coverhr,backth/2,0,180);
832 TGeoVolume* coverVolume = new TGeoVolume(Form(fgkTopName, fmd2->GetId()),
834 cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
835 cylinderShape->SetTitle("FMD2 cylinder");
836 cylinderVolume->SetTitle("FMD2 cylinder");
837 cylinderVolume->SetTransparency(63);
838 coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
839 coverShape->SetTitle("FMD2 cover");
840 coverVolume->SetTitle("FMD2 cover");
841 coverVolume->SetTransparency(63);
843 TGeoTranslation* trans = 0;
844 support->AddNode(coverVolume,1, new TGeoTranslation(0,0,backth/2));
845 support->AddNode(cylinderVolume, 1, new TGeoTranslation(0,0,backth+framel/2));
848 Double_t f1l = 15.6085;
851 Int_t nFiducialHoles = 4;
852 Double_t precHoles[][2] = { { 32.4948, 29.6663 },
853 { 33.9104, 31.0819 },
854 { 34.8177, 33.4035 },
855 { 35.5028, 32.6744 } };
856 Double_t precRadius = .25;
857 Double_t flangeA = TMath::Pi()/4;
859 new TGeoBBox("FMD2_flange_base", f1l/2, f1w/2, f1d/2);
860 new TGeoTube("FMD2_fiducial_hole", 0, precRadius, f1d/2+.1);
861 Double_t flangeX = framehr + f1l/2;
862 TVector2 flangeC(flangeX * TMath::Cos(flangeA),
863 flangeX * TMath::Sin(flangeA));
864 TString flangeComb("FMD2_flange_base-(");
865 new TGeoBBox("FMD2_flange_slit", 7./2, 1.5/2, f1d/2+.1);
866 trans = new TGeoTranslation(-f1l/2+1+7./2, +.5+1.5/2, 0);
867 trans->SetName("FMD2_flange_slit_mat1");
868 trans->RegisterYourself();
869 trans = new TGeoTranslation(-f1l/2+1+7./2, -.5-1.5/2, 0);
870 trans->SetName("FMD2_flange_slit_mat2");
871 trans->RegisterYourself();
872 flangeComb.Append("FMD2_flange_slit:FMD2_flange_slit_mat1+"
873 "FMD2_flange_slit:FMD2_flange_slit_mat2+");
874 for (Int_t i = 0; i < nFiducialHoles; i++) {
875 TVector2 v(precHoles[i][0], precHoles[i][1]);
877 TVector2 r = v.Rotate(-flangeA);
878 TGeoTranslation* t1 = new TGeoTranslation(r.X(), r.Y(), 0);
879 TGeoTranslation* t2 = new TGeoTranslation(r.X(), -r.Y(), 0);
880 t1->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+0));
881 t2->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+1));
882 t1->RegisterYourself();
883 t2->RegisterYourself();
884 flangeComb.Append(Form("FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d+"
885 "FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d%c",
886 2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
888 // Final flange shape, and at to full shape
889 TGeoCompositeShape* flangeS = new TGeoCompositeShape(flangeComb.Data());
890 flangeS->SetName("FMD2_flange");
891 TGeoVolume* flangeV = new TGeoVolume("FMD2_flange", flangeS, fAl);
897 new TGeoBBox("FMD2_flange_spacer_base", f2l/2, f2w/2, f2d/2);
898 new TGeoTube("FMD2_flange_spacer_hole", 0, 2.5, f2w/2+.1);
899 TGeoRotation* holeRot = new TGeoRotation();
900 holeRot->RotateY(90);
901 holeRot->RotateZ(90);
902 TGeoCombiTrans* combo = 0;
903 combo = new TGeoCombiTrans(0, 0, f2d/2-.5-2.5, holeRot);
904 combo->SetName("FMD2_flange_spacer_hole_mat1");
905 combo->RegisterYourself();
906 combo = new TGeoCombiTrans(0, 0, -f2d/2+.5+2.5, holeRot);
907 combo->SetName("FMD2_flange_spacer_hole_mat2");
908 combo->RegisterYourself();
909 TString spacerComp("FMD2_flange_spacer_base-("
910 "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat1+"
911 "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat2)");
912 TGeoCompositeShape* spacerS = new TGeoCompositeShape(spacerComp.Data());
913 TGeoVolume* spacerV = new TGeoVolume("FMD2_flange_spacer",
916 Double_t extraL = framehr-framelr;
917 TGeoBBox* extraS = new TGeoBBox("FMD2_flange_extra",
918 extraL/2, f1w/2, f1d/2);
919 TGeoVolume* extraV = new TGeoVolume("FMD2_flange_extra", extraS,fAl);
920 TGeoVolumeAssembly* wingV = new TGeoVolumeAssembly("FMD2_wing");
921 TGeoVolume* tension = TensionBox();
922 TGeoTube* wireS = new TGeoTube(0, .05, (framehr-coverlr)/2);
923 TGeoVolume* wireV = new TGeoVolume("FMD2_tension_wire",
925 wingV->AddNode(flangeV, 1, new TGeoTranslation(f1l/2, 0, f1d/2));
926 wingV->AddNode(flangeV, 2, new TGeoTranslation(f1l/2, 0, -f2d-f1d/2));
927 wingV->AddNode(extraV, 1, new TGeoCombiTrans(-extraL/2, 0, f1d/2, 0));
928 wingV->AddNode(spacerV, 1, new TGeoTranslation(1+f2l/2,-f2w/2+f1w/2,
930 wingV->AddNode(spacerV, 2, new TGeoTranslation(1+f2l/2,+f2w/2-f1w/2,
932 TGeoRotation* tensionR = new TGeoRotation;
933 tensionR->RotateY(90);
934 wingV->AddNode(tension, 1, new TGeoCombiTrans(4, 0, f1d+1.2, tensionR));
935 TGeoRotation* wireR = new TGeoRotation;
937 wingV->AddNode(wireV, 1, new TGeoCombiTrans(-(framehr-coverlr)/2, 0, f1d+1,
940 TGeoCombiTrans* extraM1 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
941 extraM1->RotateZ(45);
942 extraM1->RegisterYourself();
943 extraM1->SetName("FMD2_back_cover_slit1");
944 TGeoCombiTrans* extraM2 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
945 extraM2->RotateZ(135);
946 extraM2->RegisterYourself();
947 extraM2->SetName("FMD2_back_cover_slit2");
948 TString coverComp(Form(fgkTopName, fmd2->GetId()));
949 coverComp.Append("-(FMD2_flange_extra:FMD2_back_cover_slit1"
950 "+FMD2_flange_extra:FMD2_back_cover_slit2)");
951 TGeoCompositeShape* cover2Shape = new TGeoCompositeShape(coverComp.Data());
952 cover2Shape->SetName("FMD2_back_cover");
953 TGeoVolume* cover2Volume = new TGeoVolume("FMD2_back_cover", cover2Shape,fC);
954 support->AddNode(cover2Volume,2,
955 new TGeoTranslation(0,0,backth+framel+backth/2));
957 TGeoCombiTrans* trans1 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
958 TGeoCombiTrans* trans2 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
960 trans2->RotateZ(135);
961 support->AddNode(wingV, 1, trans1);
962 support->AddNode(wingV, 2, trans2);
963 AliFMDDebug(1, ("FMD2 support offset is %f", framelz));
965 for (Int_t i = 0; i < 2; i++) {
966 TGeoVolume* mother = (i < 1 ? fmd2TopVolume : fmd2BotVolume);
968 Double_t phi = 360. / 2 * i;
969 TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i));
971 TGeoMatrix* matrix = new TGeoCombiTrans(0, 0, framelz, rot);
972 mother->AddNode(support, i, matrix);
975 // Must be done after filling the assemblies
976 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
977 TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
978 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
979 fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
980 top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
981 top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
987 //____________________________________________________________________
989 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3,
990 TGeoVolume* innerTop,
991 TGeoVolume* innerBot,
992 TGeoVolume* outerTop,
993 TGeoVolume* outerBot)
995 // Setup the FMD3 geometry. The FMD2 has a rather elaborate support
996 // structure, as the support will also support the vacuum
999 // See also AliFMDGeometryBuilder::DetectorGeometry
1001 if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
1003 //__________________________________________________________________
1004 // Basic detector set-up.
1005 TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
1006 fmd3->GetId(), 'T'));
1007 TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
1008 fmd3->GetId(), 'B'));
1009 fmd3TopVolume->SetTitle("FMD3 top half");
1010 fmd3BotVolume->SetTitle("FMD3 bottom half");
1011 DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, fmd3->GetInnerZ(),
1012 innerTop, innerBot, outerTop, outerBot);
1014 //__________________________________________________________________
1015 // Mother for all support material
1016 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
1017 support->SetTitle("FMD3 support");
1019 //__________________________________________________________________
1021 const TObjArray& radii = fmd3->ConeRadii();
1022 Int_t nRadii = radii.GetEntriesFast();
1023 TGeoPcon* coneBase = new TGeoPcon("FMD3_cone_base", 0., 180., nRadii);
1026 for (Int_t i = 0; i < nRadii; i++) {
1027 TVector3* v = static_cast<TVector3*>(radii.At(i));
1028 coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
1030 else if (i == 4) r4 = v;
1032 TString coneComb("(FMD3_cone_base");
1034 //__________________________________________________________________
1036 double flangeDepth = fmd3->GetFlangeDepth() / 2;
1037 double flangeLength = fmd3->GetFlangeLength() / 2;
1038 double flangeWidth = fmd3->GetFlangeWidth() / 2;
1039 new TGeoBBox("FMD3_flange_base", flangeLength, flangeWidth, flangeDepth);
1042 const TObjArray& fiducialHoles = fmd3->FiducialHoles();
1043 double fiducialRadius = fmd3->GetFiducialRadius();
1045 TGeoTube* fiducialShape =
1047 new TGeoTube("FMD3_fiducial_hole", 0, fiducialRadius, flangeDepth+.1);
1048 Int_t nFiducialHoles = fiducialHoles.GetEntriesFast();
1049 double flangeAngle = TMath::Pi() / 4;
1050 double flangeX = r5->Y()+flangeLength;
1051 TVector2 flangeC(flangeX * TMath::Cos(flangeAngle),
1052 flangeX * TMath::Sin(flangeAngle));
1053 TString flangeComb("FMD3_flange_base-(");
1054 #if 0// For debugging geometry
1055 TGeoVolume* fiducialVolume = new TGeoVolume("FMD3_fiducial", fiducialShape);
1056 fiducialVolume->SetLineColor(kGreen);
1058 for (Int_t i = 0; i < nFiducialHoles; i++) {
1059 TVector2& v = *(static_cast<TVector2*>(fiducialHoles.At(i)));
1061 TVector2 r = v.Rotate(-flangeAngle);
1062 TGeoTranslation* t1 = new TGeoTranslation(r.X(), r.Y(), 0);
1063 TGeoTranslation* t2 = new TGeoTranslation(r.X(), -r.Y(), 0);
1064 t1->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+0));
1065 t2->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+1));
1066 t1->RegisterYourself();
1067 t2->RegisterYourself();
1068 flangeComb.Append(Form("FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d+"
1069 "FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d%c",
1070 2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
1071 #if 0 // For debugging geometry
1072 support->AddNode(fiducialVolume, 2*i+0, t1);
1073 support->AddNode(fiducialVolume, 2*i+1, t2);
1077 // Final flange shape, and at to full shape
1078 TGeoCompositeShape* flangeShape = new TGeoCompositeShape(flangeComb.Data());
1079 flangeShape->SetName("FMD3_flange");
1080 for (Int_t i = 0; i < 2; i++) {
1081 TGeoRotation* rot = new TGeoRotation();
1082 rot->RotateZ((i+.5)*90);
1083 TVector2 v(flangeX, 0);
1084 TVector2 w = v.Rotate((i+.5) * 2 * flangeAngle);
1085 TGeoCombiTrans* trans = new TGeoCombiTrans(w.X(),w.Y(),
1086 r4->X()+flangeDepth, rot);
1087 trans->SetName(Form("FMD3_flange_matrix%d", i));
1088 trans->RegisterYourself();
1089 coneComb.Append(Form("+FMD3_flange:FMD3_flange_matrix%d", i));
1091 coneComb.Append(")-(");
1093 //__________________________________________________________________
1095 Double_t holeL = fmd3->GetHoleLength()/2;
1096 Double_t holeD = fmd3->GetHoleDepth()/2;
1097 Double_t holeLW = fmd3->GetHoleLowWidth()/2;
1098 Double_t holeHW = fmd3->GetHoleHighWidth()/2;
1099 Double_t holeA = fmd3->GetConeOuterAngle();
1100 Double_t holeA2 = TMath::Pi() - fmd3->GetConeOuterAngle();
1101 Double_t holeO = fmd3->GetHoleOffset();
1102 Double_t holeZ = (holeO
1103 + holeL * TMath::Cos(holeA)
1104 - holeD * TMath::Sin(holeA2));
1105 Double_t holeX = (fmd3->ConeR(-holeZ + fmd3->GetInnerZ() + fmd3->GetNoseZ())
1106 - holeD * TMath::Sin(holeA2));
1107 new TGeoTrd1("FMD3_cone_hole", holeLW, holeHW, holeD, holeL);
1108 TGeoTrd1* plateShape = new TGeoTrd1("FMD3_cooling_plate",
1109 holeLW, holeHW, .033, holeL);
1110 TGeoRotation* holeRot = new TGeoRotation();
1111 holeRot->SetName("FMD3_cone_hole_rotation");
1112 holeRot->RotateZ(90);
1113 holeRot->RotateY(holeA*180/TMath::Pi());
1114 TGeoCombiTrans* holeBaseTrans = new TGeoCombiTrans(holeX, 0, holeZ, holeRot);
1115 holeBaseTrans->SetName("FMD3_cone_hole_base_matrix");
1116 // TGeoRotation* plateRot = new TGeoRotation();
1117 // plateRot->SetName("FMD3_cone_plate_rotation");
1118 // plateRot->RotateZ(90);
1119 // plateRot->RotateY(plateA*180/TMath::Pi());
1120 // TGeoCombiTrans* plateBaseTrans = new
1121 // TGeoCombiTrans(plateX,0,plateZ,plateRot);
1122 TGeoVolume* plateVolume = new TGeoVolume("FMD3_cooling_plate",
1124 plateShape->SetTitle("FMD3 cooling plate");
1125 plateVolume->SetTitle("FMD3 cooling plate");
1126 for (Int_t i = 0; i < 4; i++) {
1127 Double_t ang = 360. / 8 * (i + .5);
1128 TGeoCombiTrans* trans = new TGeoCombiTrans(*holeBaseTrans);
1129 trans->RotateZ(ang);
1130 trans->SetName(Form("FMD3_cone_hole_matrix%d", i));
1131 trans->RegisterYourself();
1132 trans = new TGeoCombiTrans(*holeBaseTrans);
1133 trans->RotateZ(ang);
1134 trans->SetName(Form("FMD3_cooling_plate_matrix%d", i));
1135 coneComb.Append(Form("FMD3_cone_hole:FMD3_cone_hole_matrix%d+", i));
1136 support->AddNode(plateVolume, i, trans);
1139 //__________________________________________________________________
1141 Double_t boltRadius = fmd3->GetBoltRadius();
1142 Double_t boltLength = fmd3->GetBoltLength() / 2;
1143 Double_t boltZ1 = fmd3->GetInnerZ()+fmd3->GetNoseZ()-10;
1144 Double_t boltZ2 = fmd3->GetInnerZ()+fmd3->GetNoseZ()-20;
1145 Double_t boltXE = 2*boltLength*TMath::Cos(fmd3->GetConeOuterAngle());
1146 Double_t boltX1 = (fmd3->ConeR(boltZ1) - boltXE);
1147 Double_t boltX2 = (fmd3->ConeR(boltZ2) - boltXE);
1149 new TGeoTube("FMD3_bolt_hole", 0, boltRadius, boltLength+.2);
1150 TGeoTube* boltShape = new TGeoTube("FMD3_bolt", 0, boltRadius, boltLength);
1151 TGeoRotation* boltRot = new TGeoRotation();
1152 boltRot->RotateY(-fmd3->GetConeOuterAngle()*180/TMath::Pi());
1153 TGeoCombiTrans* boltTrans1 = new TGeoCombiTrans(boltX1, 0, 10, boltRot);
1154 TGeoCombiTrans* boltTrans2 = new TGeoCombiTrans(boltX2, 0, 20, boltRot);
1155 TGeoCombiTrans* boltTrans3 = new TGeoCombiTrans(*boltTrans1);
1156 TGeoCombiTrans* boltTrans4 = new TGeoCombiTrans(*boltTrans2);
1157 boltTrans3->RotateZ(180);
1158 boltTrans4->RotateZ(180);
1159 boltTrans1->SetName("FMD3_bolt_matrix1");
1160 boltTrans2->SetName("FMD3_bolt_matrix2");
1161 boltTrans3->SetName("FMD3_bolt_matrix3");
1162 boltTrans4->SetName("FMD3_bolt_matrix4");
1163 boltTrans1->RegisterYourself();
1164 boltTrans2->RegisterYourself();
1165 boltTrans3->RegisterYourself();
1166 boltTrans4->RegisterYourself();
1167 coneComb.Append("FMD3_bolt_hole:FMD3_bolt_matrix1"
1168 "+FMD3_bolt_hole:FMD3_bolt_matrix2"
1169 "+FMD3_bolt_hole:FMD3_bolt_matrix3"
1170 "+FMD3_bolt_hole:FMD3_bolt_matrix4");
1171 TGeoVolume* boltVolume = new TGeoVolume("FMD3_bolt", boltShape, fSteel);
1172 support->AddNode(boltVolume, 1, boltTrans1);
1173 support->AddNode(boltVolume, 2, boltTrans2);
1174 boltShape->SetTitle("FMD3 steering bolt");
1175 boltVolume->SetTitle("FMD3 steering bolt");
1177 //__________________________________________________________________
1178 // Cut-outs for tension wheel sheeve
1179 new TGeoBBox("FMD3_sheeve_hole", .55, .75, 1.16);
1180 Double_t sheeveHoleZ = fmd3->GetInnerZ() + fmd3->GetNoseZ() - .75;
1181 Double_t sheeveHoleR = fmd3->ConeR(sheeveHoleZ) - .55 + .2572222;
1182 TGeoCombiTrans* sheeveMat1 = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1183 TGeoCombiTrans* sheeveMat2 = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1184 sheeveMat1->RotateZ(45);
1185 sheeveMat2->RotateZ(135);
1186 sheeveMat1->SetName("FMD3_sheeve_hole_matrix1");
1187 sheeveMat2->SetName("FMD3_sheeve_hole_matrix2");
1188 sheeveMat1->RegisterYourself();
1189 sheeveMat2->RegisterYourself();
1190 coneComb.Append("+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix1"
1191 "+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix2)");
1193 //__________________________________________________________________
1195 Double_t sheeveL = 1.15;
1196 TGeoBBox* sheeveSideS = new TGeoBBox("FMD3_sheeve_side",
1198 TGeoBBox* sheeveBackS = new TGeoBBox("FMD3_sheeve_back",
1200 TGeoBBox* sheeveWingS = new TGeoBBox("FMD3_sheeve_wing",
1202 TGeoPcon* sheeveWheelS = new TGeoPcon("FMD3_sheeve_wheel", 0, 360, 9);
1203 Double_t sheeveInnerR = 0; // .2;
1204 Double_t sheeveR = .875;
1205 Double_t sheeveWheelZ = .95;
1206 sheeveWheelS->DefineSection(0, -.25, sheeveInnerR, 1);
1207 sheeveWheelS->DefineSection(1, -.125, sheeveInnerR, 1);
1208 sheeveWheelS->DefineSection(2, -.125, sheeveInnerR, sheeveWheelZ);
1209 sheeveWheelS->DefineSection(3, -.0625, sheeveInnerR, sheeveR+.02);
1210 sheeveWheelS->DefineSection(4, 0.000, sheeveInnerR, sheeveR);
1211 sheeveWheelS->DefineSection(5, +.0625, sheeveInnerR, sheeveR+.02);
1212 sheeveWheelS->DefineSection(6, +.125, sheeveInnerR, sheeveWheelZ);
1213 sheeveWheelS->DefineSection(7, +.125, sheeveInnerR, 1);
1214 sheeveWheelS->DefineSection(8, +.25, sheeveInnerR, 1);
1215 TGeoVolume* sheeveSideV = new TGeoVolume("FMD3_sheeve_side",
1216 sheeveSideS, fPlastic);
1217 TGeoVolume* sheeveBackV = new TGeoVolume("FMD3_sheeve_back",
1218 sheeveBackS, fPlastic);
1219 TGeoVolume* sheeveWingV = new TGeoVolume("FMD3_sheeve_wing",
1220 sheeveWingS, fPlastic);
1221 TGeoVolume* sheeveWheelV= new TGeoVolume("FMD3_sheeve_wheel",
1222 sheeveWheelS, fPlastic);
1223 TGeoVolumeAssembly* sheeveBox = new TGeoVolumeAssembly("FMD3_sheeve_box");
1224 sheeveBox->AddNode(sheeveSideV, 1, new TGeoTranslation(0, -.5, 0));
1225 sheeveBox->AddNode(sheeveSideV, 2, new TGeoTranslation(0, +.5, 0));
1226 sheeveBox->AddNode(sheeveBackV, 1, new TGeoTranslation(0, 0, 2.0+.15-1.15));
1227 sheeveBox->AddNode(sheeveWingV, 1, new TGeoTranslation(.55-.15, -.90, 0));
1228 sheeveBox->AddNode(sheeveWingV, 2, new TGeoTranslation(.55-.15, +.90, 0));
1229 TGeoRotation* sheeveWheelR = new TGeoRotation;
1230 sheeveWheelR->RotateX(90);
1231 TGeoCombiTrans* sheeveWheelM = new TGeoCombiTrans(0, 0, sheeveWheelZ-sheeveL,
1233 sheeveBox->AddNode(sheeveWheelV, 1, sheeveWheelM);
1234 support->AddNode(sheeveBox, 1, sheeveMat1);
1235 support->AddNode(sheeveBox, 2, sheeveMat2);
1239 //__________________________________________________________________
1241 TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneComb.Data());
1242 coneShape->SetName("FMD3_cone");
1243 coneShape->SetTitle("FMD3 cone");
1244 TGeoVolume* coneVolume = new TGeoVolume("FMD3_Cone", coneShape, fC);
1245 coneVolume->SetLineColor(kRed);
1246 support->AddNode(coneVolume, 0, new TGeoTranslation(0, 0, 0));
1248 //__________________________________________________________________
1250 TGeoVolume* tensionBox = TensionBox();
1251 Double_t tensionH = .6;
1252 Double_t tensionL = 4;
1253 Double_t tensionZ = 23.654;
1254 Double_t tensionR = fmd3->ConeR(fmd3->GetInnerZ() + fmd3->GetNoseZ()
1256 Double_t tensionAr = fmd3->GetConeOuterAngle();
1257 Double_t tensionA = tensionAr * 180 / TMath::Pi();
1258 TGeoRotation* tensionQ = new TGeoRotation;
1259 tensionQ->RotateY(tensionA);
1260 TGeoCombiTrans* tensionM1 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1261 TGeoCombiTrans* tensionM2 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1262 tensionM1->RotateZ(45);
1263 tensionM2->RotateZ(135);
1264 support->AddNode(tensionBox, 1, tensionM1);
1265 support->AddNode(tensionBox, 2, tensionM2);
1267 // Double_t tensionHR = 0.15;
1268 Double_t wireT = .1/2;
1269 Double_t wireZ1 = (tensionZ
1270 - tensionL * TMath::Cos(tensionAr)
1271 - tensionH * TMath::Sin(tensionAr));
1272 Double_t wireR1 = (tensionR
1273 - tensionL * TMath::Sin(tensionAr)
1274 + tensionH * TMath::Cos(tensionAr));
1275 AliFMDDebug(10, ("Wire Z1: %f=%f-%f*cos(%f)-%f*sin(%f)",
1276 wireZ1, tensionZ, tensionL, tensionAr, tensionH, tensionAr));
1277 AliFMDDebug(10, ("Wire R1: %f=%f-%f*sin(%f)-%f*cos(%f)",
1278 wireR1, tensionR, tensionL, tensionAr, tensionH, tensionAr));
1280 Double_t wireStartA = 42.3 * TMath::Pi() / 180;
1281 Double_t wireZ2 = (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1283 - wireT * TMath::Sin(wireStartA));
1284 /* (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1285 - wireT * TMath::Sin(wireStartA)
1287 AliFMDDebug(10, ("wireZ2=%f=%f*(1-%f)", wireZ2, sheeveWheelZ,
1288 TMath::Sin(wireStartA)));
1289 Double_t wireR2 = (sheeveHoleR +
1290 sheeveWheelZ * TMath::Cos(wireStartA) +
1291 wireT * TMath::Cos(wireStartA));
1292 Double_t wireDR = wireR1-wireR2;
1293 Double_t wireDZ = wireZ1-wireZ2;
1294 Double_t wireL = TMath::Sqrt(wireDR*wireDR+wireDZ*wireDZ)-.01;
1295 Double_t wireAngle = TMath::ATan2(wireDR,wireDZ);
1296 TGeoTube* wireShape = new TGeoTube("FMD3_wire", 0, wireT, wireL/2);
1297 TGeoVolume* wireVolume = new TGeoVolume("FMD3_wire", wireShape,fSteel);
1298 TGeoRotation* wireRot = new TGeoRotation();
1299 wireRot->RotateY(180/TMath::Pi()*wireAngle);
1300 Double_t wireR = wireR2 + wireDR / 2;
1301 Double_t wireZ = wireZ2 + wireDZ / 2;
1302 TGeoCombiTrans* wireM1 = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1303 TGeoCombiTrans* wireM2 = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1304 wireM1->RotateZ(45);
1305 wireM2->RotateZ(135);
1306 support->AddNode(wireVolume, 1, wireM1);
1307 support->AddNode(wireVolume, 2, wireM2);
1310 TGeoTorus* wireTS = new TGeoTorus(sheeveWheelZ+wireT, 0, wireT, 0,
1311 90-wireStartA*180/TMath::Pi());
1312 TGeoVolume* wireTV = new TGeoVolume("FMD3_bend_wire",wireTS,fSteel);
1313 TGeoRotation* wireTR = new TGeoRotation;
1314 wireTR->RotateY(90);
1315 wireTR->RotateZ(-90);
1316 Double_t wireTZ = sheeveWheelZ;
1317 TGeoCombiTrans* wireTM1 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1318 TGeoCombiTrans* wireTM2 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1319 wireTM1->RotateZ(45);
1320 wireTM2->RotateZ(135);
1321 support->AddNode(wireTV, 1, wireTM1);
1322 support->AddNode(wireTV, 2, wireTM2);
1324 Double_t colarR = 4.05;
1325 Double_t wireEL = sheeveHoleR - colarR;
1326 TGeoTube* wireES = new TGeoTube("FMD3_end_wire", 0, wireT, wireEL/2);
1327 TGeoVolume* wireEV = new TGeoVolume("FMD3_end_wire", wireES, fSteel);
1328 TGeoRotation* wireER = new TGeoRotation;
1329 wireER->RotateY(90);
1330 TGeoCombiTrans* wireEM1 = new TGeoCombiTrans(colarR+wireEL/2,0,
1332 TGeoCombiTrans* wireEM2 = new TGeoCombiTrans(colarR+wireEL/2,0,
1334 wireEM1->RotateZ(45);
1335 wireEM2->RotateZ(135);
1336 support->AddNode(wireEV, 1, wireEM1);
1337 support->AddNode(wireEV, 2, wireEM2);
1342 //__________________________________________________________________
1343 // Place support volumes in half-detector volumes
1344 Double_t z = fmd3->GetInnerZ();
1345 AliFMDDebug(1, ("FMD3 support at z=%f", -fmd3->GetNoseZ()));
1346 TGeoTranslation* t1 = new TGeoTranslation(0, 0, -fmd3->GetNoseZ());
1347 fmd3TopVolume->AddNode(support, 1, t1);
1348 TGeoCombiTrans* t2 = new TGeoCombiTrans(*t1);
1350 fmd3BotVolume->AddNode(support, 2, t2);
1352 TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
1354 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
1355 TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1356 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
1357 fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1358 top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1359 top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1365 //____________________________________________________________________
1367 AliFMDGeometryBuilder::Exec(Option_t*)
1369 // Setup up the FMD geometry.
1370 AliFMDDebug(1, ("\tGeometry options: %s",
1371 (fDetailed ? "divided into strips" : "one volume")));
1373 AliFatal("No TGeoManager defined");
1377 fSi = gGeoManager->GetMedium("FMD_Si$");
1378 fC = gGeoManager->GetMedium("FMD_Carbon$");
1379 fAl = gGeoManager->GetMedium("FMD_Aluminum$");
1380 fChip = gGeoManager->GetMedium("FMD_Si Chip$");
1381 fAir = gGeoManager->GetMedium("FMD_Air$");
1382 fPCB = gGeoManager->GetMedium("FMD_PCB$");
1383 fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1384 fCopper = gGeoManager->GetMedium("FMD_Copper$");
1385 fSteel = gGeoManager->GetMedium("FMD_Steel$");
1387 if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1388 AliError("Failed to get some or all tracking mediums");
1391 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1392 AliFMDRing* inner = fmd->GetInner();
1393 AliFMDRing* outer = fmd->GetOuter();
1394 RingGeometry(inner);
1395 RingGeometry(outer);
1396 TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1398 TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1400 TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1402 TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1405 FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1406 FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1407 FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1408 #ifndef USE_PRE_MOVE
1409 fmd->SetSectorOff(fSectorOff);
1410 fmd->SetModuleOff(fModuleOff);
1411 fmd->SetRingOff(fRingOff);
1412 fmd->SetDetectorOff(fDetectorOff);
1413 fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1415 // fmd->ExtractGeomInfo();
1420 //____________________________________________________________________