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
158 // Make a polygonic extrusion shape based on verticies passed in @a
162 // verticies List of verticies
166 // newly allocated polygonic extrusion shape
170 for (Int_t i = 0; i < 3; i++) {
171 TVector2* v = static_cast<TVector2*>(verticies.At(i+1));
177 TGeoXtru* shape = new TGeoXtru(2);
178 shape->DefinePolygon(xs.fN, xs.fArray, ys.fArray);
179 shape->DefineSection(0, -thick/2);
180 shape->DefineSection(1, +thick/2);
185 //____________________________________________________________________
187 AliFMDGeometryBuilder::RingGeometry(const AliFMDRing* r)
189 // Setup the geometry of a ring. The defined TGeoVolume is
190 // returned, and should be used when setting up the rest of the
196 // r Pointer to ring geometry object
199 // pointer to ring volume
202 AliError("Didn't get a ring object");
205 Char_t id = r->GetId();
206 Char_t rng = toupper(id);
207 const Char_t* lName = (rng == 'I' ? "inner" : "outer");
208 Double_t siThick = r->GetSiThickness();
209 Double_t pcbThick = r->GetPrintboardThickness();
210 Double_t cuThick = r->GetCopperThickness();
211 Double_t chipThick= r->GetChipThickness();
212 Double_t modSpace = r->GetModuleSpacing();
213 Double_t theta = r->GetTheta();
215 //------------------------------------------------------------------
218 TGeoShape* sensorShape = MakeXTRU(r->GetSensorVerticies(), siThick);
219 sensorShape->SetName(Form("FMD%c_physical_sensor", id));
220 sensorShape->SetTitle(Form("FMD %s physical sensor", lName));
221 TString sensorName = TString::Format(fgkSensorName, id);
222 TGeoVolume* sensorVolume = new TGeoVolume(sensorName, sensorShape, fSi);
223 sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
224 sensorVolume->VisibleDaughters(kFALSE);
225 Int_t sid = sensorVolume->GetNumber();
236 // Virtual volume shape to divide - This volume is only defined if
237 // the geometry is set to be detailed.
238 TGeoTubeSeg* activeShape = new TGeoTubeSeg(r->GetLowR(),
243 activeShape->SetName(Form(fgkActiveName, id));
244 activeShape->SetTitle(Form("FMD %s active area", lName));
245 TString activeName = TString::Format(fgkActiveName, id);
246 TGeoVolume* activeVolume = new TGeoVolume(activeName,activeShape,fSi);
247 activeVolume->SetTitle(Form("FMD %s active area", lName));
248 TString sectorName = TString::Format(fgkSectorName,id);
249 TGeoVolume* sectorVolume = activeVolume->Divide(sectorName, 2, 2, -theta,
252 Int_t ns = r->GetNStrips();
253 Double_t stripoff = r->GetLowR(); // 0; // a->Mod();
254 Double_t dstrip = (r->GetHighR() - stripoff) / ns;
256 sectorVolume->SetTitle(Form("FMD %s sector", lName));
257 TString stripName = TString::Format(fgkStripName, id);
258 TGeoVolume* stripVolume = sectorVolume->Divide(stripName,
259 1, ns, stripoff, dstrip,
261 stripVolume->SetTitle(Form("FMD %s strip", lName));
262 sid = stripVolume->GetNumber();
263 sensorVolume->AddNodeOverlap(activeVolume, 0);
267 case 'I': fActiveId[0] = sid; break;
268 case 'O': fActiveId[1] = sid; break;
271 //------------------------------------------------------------------
273 // PCB layer of hybrid
274 TGeoShape* pcbShape = MakeXTRU(r->GetHybridVerticies(), pcbThick);
275 pcbShape->SetName(Form("FMD%c_hybrid_pcb", id));
276 pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
277 TString pcbName = TString::Format(fgkPCBName, id);
278 TGeoVolume* pcbVolume = new TGeoVolume(pcbName, pcbShape, fPCB);
279 pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
282 TGeoShape* cuShape = MakeXTRU(r->GetHybridVerticies(), cuThick);
283 cuShape->SetName(Form("FMD%c_hybrid_copper", id));
284 cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
285 TString cuName = TString::Format(fgkCuName,id);
286 TGeoVolume* cuVolume = new TGeoVolume(cuName,cuShape,fCopper);
287 cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
290 TGeoShape* chipShape = MakeXTRU(r->GetHybridVerticies(), chipThick);
291 chipShape->SetName(Form("FMD%c_hybrid_chip", id));
292 chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
293 TString chipName = TString::Format(fgkChipName,id);
294 TGeoVolume* chipVolume = new TGeoVolume(chipName,chipShape,fChip);
295 chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
297 //------------------------------------------------------------------
299 Double_t legr = r->GetLegRadius();
300 Double_t legl = r->GetLegLength();
304 TGeoTube* shortLegShape = new TGeoTube(0, legr, (legl-lege) / 2);
305 shortLegShape->SetName(Form(fgkShortLegName, id));
306 shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
307 TString shortLegName = TString::Format(fgkShortLegName, id);
308 TGeoVolume* shortLegVolume = new TGeoVolume(shortLegName,
309 shortLegShape, fCopper);
310 shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
312 TGeoTube* longLegShape = new TGeoTube(0, legr,
313 (legl - lege + modSpace) / 2);
314 longLegShape->SetName(Form(fgkLongLegName, id));
315 longLegShape->SetTitle(Form("FMD %s long support foot", lName));
316 TString longLegName = TString::Format(fgkLongLegName, id);
317 TGeoVolume* longLegVolume = new TGeoVolume(longLegName,
318 longLegShape, fCopper);
319 longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
323 //------------------------------------------------------------------
324 // Placement of module volumes in assemblies
327 for (Int_t i = 0; i < 3; i++) {
328 TVector2* vv = r->GetFootPosition(i);
329 // TVector2 uu = vv->Rotate(TMath::Pi()/2);
334 // Back container volume
335 TGeoVolume* backVolume = new TGeoVolumeAssembly(Form(fgkBackVName, id));
336 backVolume->SetTitle(Form("FMD %s back module", lName));
337 TGeoVolume* frontVolume = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
338 frontVolume->SetTitle(Form("FMD %s front module", lName));
340 Double_t space = r->GetSpacing();
343 Double_t zb = siThick / 2;
344 Double_t zf = siThick / 2;
345 backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zb));
346 frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zf));
347 zb += siThick / 2 + space + pcbThick / 2;
348 zf += siThick / 2 + space + pcbThick / 2;
349 backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zb));
350 frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zf));
351 zb += (pcbThick + cuThick) / 2;
352 zf += (pcbThick + cuThick) / 2;
353 backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zf));
354 frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zb));
355 zb += (cuThick + chipThick) / 2;
356 zf += (cuThick + chipThick) / 2;
357 backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zb));
358 frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zf));
359 zb += pcbThick / 2 + (legl)/ 2 - lege;
360 zf += pcbThick / 2 + (legl + modSpace)/ 2 - lege;
361 for (Int_t i = 0; i < 3; i++) {
362 x = xfs[i]; // a->X() + legoff + legr;
364 backVolume->AddNode(shortLegVolume, i, new TGeoTranslation(x,y,zb));
365 frontVolume->AddNode(longLegVolume, i, new TGeoTranslation(x,y,zf));
368 //------------------------------------------------------------------
370 Double_t ddlr = r->GetFMDDLowR();
371 Double_t ddhr = r->GetFMDDHighR();
372 Double_t ddpt = r->GetFMDDPrintboardThickness();
373 Double_t ddct = r->GetFMDDCopperThickness();
374 Double_t ddit = r->GetFMDDChipThickness();
375 Double_t ddt = ddpt + ddct + ddit;
377 TString pcbdName(Form(fgkFMDDPCBName, id));
378 TString cudName(Form(fgkFMDDCuName, id));
379 TString chipdName(Form(fgkFMDDChipName, id));
380 new TGeoTubeSeg(Form("%s_inner", pcbdName.Data()), ddlr, ddhr, ddpt/2,0,180);
381 new TGeoTubeSeg(Form("%s_inner", cudName.Data()), ddlr, ddhr, ddct/2,0,180);
382 new TGeoTubeSeg(Form("%s_inner", chipdName.Data()), ddlr, ddhr, ddit/2,0,180);
397 new TGeoBBox(Form("%s_clip", pcbdName.Data()), clipWX, clipWY, ddpt);
398 new TGeoBBox(Form("%s_clip", cudName.Data()), clipWX, clipWY, ddct);
399 new TGeoBBox(Form("%s_clip", chipdName.Data()),clipWX, clipWY, ddit);
400 TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
403 trans->RegisterYourself();
404 TGeoShape* fmddPcbShape =
405 new TGeoCompositeShape(pcbdName.Data(),
406 Form("%s_inner*%s_clip:%s_trans",
410 TGeoShape* fmddCuShape =
411 new TGeoCompositeShape(cudName.Data(),
412 Form("%s_inner*%s_clip:%s_trans",
416 TGeoShape* fmddChipShape =
417 new TGeoCompositeShape(chipdName.Data(),
418 Form("%s_inner*%s_clip:%s_trans",
422 fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
423 fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
424 fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
426 TString fmddPcbName = TString::Format(fgkFMDDPCBName, id);
427 TGeoVolume* fmddPcbVolume = new TGeoVolume(fmddPcbName,
429 TString fmddCuName = TString::Format(fgkFMDDCuName, id);
430 TGeoVolume* fmddCuVolume = new TGeoVolume(fmddCuName,
431 fmddCuShape, fCopper);
432 TString fmddChipName = TString::Format(fgkFMDDChipName, id);
433 TGeoVolume* fmddChipVolume = new TGeoVolume(fmddChipName,
434 fmddChipShape, fChip);
435 fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
436 fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
437 fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
439 //------------------------------------------------------------------
440 // Half ring mother volumes.
441 TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
442 TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
443 TGeoVolume* halfRing = ringTopVolume;
444 ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
445 ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
447 //------------------------------------------------------------------
448 // Adding modules to half-rings
449 Int_t nmod = r->GetNModules();
450 AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
451 for (Int_t i = 0; i < nmod; i++) {
452 if (i == nmod / 2) halfRing = ringBotVolume;
453 Bool_t front = (i % 2 == (rng == 'I' ? 1 : 0));
454 TGeoVolume* vol = (front ? frontVolume : backVolume);
455 // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
456 Double_t z1 = (front ? -1 : 1) * modSpace / 2;
457 // Double_t z1 = (front ? 0 : modSpace);
458 Double_t th = (2 * i + 1) * theta;
459 TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0);
461 mat1->SetName(Form("FMD%c_module_%02d", id, i));
462 mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
463 halfRing->AddNode(vol, i, mat1);
466 //------------------------------------------------------------------
468 Double_t zi = r->GetFullDepth() - ddt;
470 for (Int_t i = 0; i < n; i++) {
471 halfRing = (i == 0 ? ringTopVolume : ringBotVolume);
472 Double_t phi = 360. / n * i;
473 TGeoRotation* rot = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
475 rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
476 Double_t z = zi + ddpt / 2;
477 halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
478 z += (ddpt + ddct) / 2;
479 halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
480 z += (ddct + ddit) / 2;
481 halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
489 //____________________________________________________________________
491 AliFMDGeometryBuilder::HoneycombShape(Int_t id, Char_t ring,
492 double r1, double r2,
493 double w, double t, double c)
495 // Make a honey comb shape from passed parameters.
497 // id Detector identifier (1,2, or 3)
498 // ring Ring identifier ('I' or 'O')
502 // t Thickness of material
503 // c Clearing from horizontal.
505 // Pointer to newly allocated composite shape.
506 TString form = Form("FMD%d%c_%%c_%%c", id, ring);
507 double a1 = TMath::ATan2(c, r1) * 180 / TMath::Pi();
509 TString fn = Form(form.Data(),'F','1');
510 TString bn = Form(form.Data(),'B','1');
511 TString cn = Form(form.Data(),'C','O');
512 TString in = Form(form.Data(),'R','I');
513 TString on = Form(form.Data(),'R','O');
514 TString en = Form(form.Data(),'E','X');
516 double x = r1 * TMath::Cos(TMath::Pi()*a1/180);
517 new TGeoTubeSeg(fn.Data(),r1,r2,t/2,0,180);
518 new TGeoTubeSeg(bn.Data(),r1,r2,t/2,0,180);
519 new TGeoBBox(cn.Data(),(r2-r1)/2,t/2,w/2);
520 new TGeoTubeSeg(in.Data(),r1,r1+t,w/2,0,180);
521 new TGeoTubeSeg(on.Data(),r2-t,r2,w/2,0,180);
522 new TGeoBBox(en.Data(),r2+.005,c/2+.005,w/2+.005);
524 TString ftn = Form(form.Data(),'F','T');
525 TString btn = Form(form.Data(),'F','B');
526 TString ltn = Form(form.Data(),'C','L');
527 TString rtn = Form(form.Data(),'C','R');
528 TString etn = Form(form.Data(),'E','X');
529 (new TGeoTranslation(ftn.Data(),0,0,+w/2-t/2))->RegisterYourself();
530 (new TGeoTranslation(btn.Data(),0,0,-w/2+t/2))->RegisterYourself();
531 (new TGeoTranslation(ltn.Data(),-(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
532 (new TGeoTranslation(rtn.Data(),(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
533 (new TGeoTranslation(etn.Data(),0, c/2,0))->RegisterYourself();
535 TString comp(Form("(%s:%s+%s:%s+%s+%s+%s:%s+%s:%s)-%s:%s",
536 fn.Data(),ftn.Data(),
537 bn.Data(),btn.Data(),
539 cn.Data(),ltn.Data(),
540 cn.Data(),rtn.Data(),
541 en.Data(),etn.Data()));
542 TGeoCompositeShape* shape = new TGeoCompositeShape(comp.Data());
543 shape->SetName(Form(fgkHCName,id,ring));
544 shape->SetTitle(Form("FMD%d%c Honeycomb shape", id, ring));
548 //____________________________________________________________________
550 AliFMDGeometryBuilder::TensionBox()
553 // Get the tension box volume
559 static TGeoVolumeAssembly* tensionBox = 0;
560 if (tensionBox) return tensionBox;
562 TGeoBBox* tensionEndS = new TGeoBBox("FMD_tension_end", .6, 3, .25);
563 TGeoBBox* tensionTopS = new TGeoBBox("FMD_tension_top", .1, .5, 3.5);
564 TGeoVolume* tensionEndV = new TGeoVolume("FMD_tension_end", tensionEndS,fAl);
565 TGeoVolume* tensionTopV = new TGeoVolume("FMD_tension_top", tensionTopS,fAl);
566 tensionBox = new TGeoVolumeAssembly("FMD_tension_box");
567 tensionBox->AddNode(tensionEndV, 1, new TGeoTranslation(.6, 0, -3.75));
568 tensionBox->AddNode(tensionEndV, 2, new TGeoTranslation(.6, 0, +3.75));
569 tensionBox->AddNode(tensionTopV, 1, new TGeoTranslation(0.1, +2.5, 0));
570 tensionBox->AddNode(tensionTopV, 2, new TGeoTranslation(0.1, -2.5, 0));
571 tensionBox->AddNode(tensionTopV, 3, new TGeoTranslation(1.1, +2.5, 0));
572 tensionBox->AddNode(tensionTopV, 4, new TGeoTranslation(1.1, -2.5, 0));
577 //____________________________________________________________________
579 AliFMDGeometryBuilder::DetectorGeometry(const AliFMDDetector* d,
580 TGeoVolume* topMother,
581 TGeoVolume* botMother,
583 TGeoVolume* innerTop,
584 TGeoVolume* innerBot,
585 TGeoVolume* outerTop,
586 TGeoVolume* outerBot)
588 // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
589 // This includes putting the Honeycomb support plates and the rings
590 // into the mother volumes.
593 // d The detector geometry to use
594 // mother The mother volume of the detector
595 // zmother The midpoint in global coordinates of detector vol.
596 // inner Pointer to inner ring volume
597 // outer Pointer to outer ring volume
600 // Pointer to mother (detector volume)
603 // Loop over the defined rings
604 for (int i = 0; i < 2; i++) {
609 TGeoVolume* tvol = 0;
610 TGeoVolume* bvol = 0;
614 lowr = d->GetInnerHoneyLowR();
615 highr = d->GetInnerHoneyHighR();
622 lowr = d->GetOuterHoneyLowR();
623 highr = d->GetOuterHoneyHighR();
630 Char_t c = r->GetId();
631 Int_t id = d->GetId();
632 Double_t hcThick = r->GetHoneycombThickness();
633 Double_t alThick = r->GetAlThickness();
634 Double_t z = TMath::Abs(rz - zMother);
636 // Place ring in mother volume
637 // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
638 AliFMDDebug(2, ("Placing volumes %s and %s in %s and %s at z=%f",
639 tvol->GetName(), bvol->GetName(),
640 topMother->GetName(), botMother->GetName(), z));
641 topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
642 botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
645 TGeoShape* hcSha = HoneycombShape(id, c, lowr, highr, hcThick, alThick);
646 TGeoVolume* hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
647 hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
649 z += (r->GetModuleDepth()
650 + r->GetModuleSpacing() / 2
651 + r->GetHoneycombThickness() / 2);
653 AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f",
654 hcVol->GetName(), topMother->GetName(),
655 botMother->GetName(), z));
657 topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
660 TGeoMatrix* bhcMatrix = new TGeoCombiTrans(0,0,z,0);
661 bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
662 bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
663 bhcMatrix->RotateZ(180);
664 botMother->AddNode(hcVol, 1, bhcMatrix);
669 //____________________________________________________________________
671 AliFMDGeometryBuilder::FMD1Geometry(const AliFMD1* fmd1,
672 TGeoVolume* innerTop,
673 TGeoVolume* innerBot)
675 // Setup the FMD1 geometry. The FMD1 only has one ring, and no
676 // special support as it is at the momement.
678 // See also AliFMDGeometryBuilder::DetectorGeometry
680 if (!fmd1 || !innerTop || !innerBot) return 0;
681 AliFMDRing* r = fmd1->GetInner();
682 Double_t z = fmd1->GetInnerZ();
684 // `Top' or `Outside' master volume
685 TString fmd1TopName = TString::Format(fgkFMDName, fmd1->GetId(), 'T');
686 TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(fmd1TopName);
687 fmd1TopVolume->SetTitle("FMD1 top half");
689 // `Bottom' or `Inside' master volume
690 TString fmd1BotName = TString::Format(fgkFMDName, fmd1->GetId(), 'B');
691 TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(fmd1BotName);
692 fmd1BotVolume->SetTitle("FMD1 bottom half");
694 // Basic detector geometry
695 DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z,
696 innerTop, innerBot, 0, 0);
698 Double_t lidP[][3] = { { 0.00, 4.20, 20.95 },
699 { 0.15, 4.20, 20.95 },
700 { 0.15, 20.80, 20.95 },
701 { 3.00, 20.80, 20.95 },
702 { 3.00, 20.80, 22.30 },
703 { 3.15, 20.80, 22.30 },
704 { 3.15, 20.95, 24.65 },
705 { 3.30, 20.95, 24.65 },
706 { 3.30, 24.50, 24.65 },
707 { 6.80, 24.50, 24.65 },
708 { 6.80, 24.50, 26.00 },
709 { 6.95, 24.50, 26.00 } };
710 Double_t lidZStart = lidP[11][0];
711 TGeoPcon* lidBaseS = new TGeoPcon("FMD1_lid_base", 0, 180, 12);
712 for (size_t i = 0; i < 12; i++)
713 lidBaseS->DefineSection(i, lidP[i][0] - lidZStart, lidP[i][1], lidP[i][2]);
716 Double_t lidH[][2] = { { 7.84903, 24.15680 },
717 { 20.54900, 14.92970 },
718 { 21.99700, 12.70000 },
719 { 25.26090, 2.65502 } };
720 Double_t lidHR = .53 / 2;
721 Double_t lidHL = 0.16;
723 new TGeoTube("FMD1_lid_hole", 0, lidHR, lidHL/2);
724 TString lidComp("FMD1_lid_base-(");
725 TGeoTranslation* trans = 0;
726 for (size_t i = 0; i < 4; i++) {
727 trans = new TGeoTranslation(-lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
728 trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+0)));
729 trans->RegisterYourself();
730 trans = new TGeoTranslation(+lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
731 trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+1)));
732 trans->RegisterYourself();
733 lidComp.Append(Form("FMD1_lid_hole:FMD1_lid_hole_mat%d+"
734 "FMD1_lid_hole:FMD1_lid_hole_mat%d%c",
735 int(2 * i), int(2 * i + 1), int(i == 3 ? ')' : '+')));
737 TGeoCompositeShape* lidS = new TGeoCompositeShape(lidComp.Data());
738 lidS->SetName("FMD1_lid");
739 TGeoVolume* lidV = new TGeoVolume("FMD1_lid", lidS, fC);
740 lidV->SetTransparency(63);
743 Double_t lidZ = (lidZStart -
744 (3.3 - r->GetModuleDepth() - r->GetModuleSpacing() / 2));
745 AliFMDDebug(1, ("FMD1 lid offset in Z=%f", lidZ));
747 for (Int_t i = 0; i < 2; i++) {
748 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
749 Double_t phi = 360. / 2 * i;
750 TGeoRotation* rot = new TGeoRotation(Form("FMD1_lid_rot%d",i));
752 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1_lid_mat%d", i),
754 mother->AddNode(lidV, i, matrix);
757 // Must add this after filling the assembly.
758 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
759 // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
760 TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
762 TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
764 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
765 fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
766 top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
767 top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
770 // Survey points on V0A (screw holes for the FMD)
771 const Double_t icb[] = { +12.700, -21.997, 324.670 };
772 const Double_t ict[] = { +12.700, +21.997, 324.670 };
773 const Double_t ocb[] = { -12.700, -21.997, 324.670 };
774 const Double_t oct[] = { -12.700, +21.997, 324.670 };
776 TGeoTube* surveyShape = new TGeoTube("FMD1_survey_marker",
779 TGeoMatrix* outMat = matrix;
781 if (gGeoManager->cd("/ALIC_1/F1MT_1"))
782 outMat = gGeoManager->GetCurrentMatrix();
784 AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
787 Double_t loct[3], locb[3];
788 outMat->MasterToLocal(oct, loct);
789 outMat->MasterToLocal(ocb, locb);
790 TGeoVolume* vOct = new TGeoVolume("V0L_OCT", surveyShape, fPlastic);
791 TGeoVolume* vOcb = new TGeoVolume("V0L_OCB", surveyShape, fPlastic);
793 fmd1TopVolume->AddNode(vOct, 1, new TGeoTranslation(loct[0],loct[1],loct[2]));
794 fmd1TopVolume->AddNode(vOcb, 1, new TGeoTranslation(locb[0],locb[1],locb[2]));
797 TGeoMatrix* inMat = matrix;
799 if (gGeoManager->cd("/ALIC_1/F1MT_1"))
800 inMat = gGeoManager->GetCurrentMatrix();
802 AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
805 Double_t lict[3], licb[3];
806 inMat->MasterToLocal(ict, lict);
807 inMat->MasterToLocal(icb, licb);
808 TGeoVolume* vIct = new TGeoVolume("V0L_ICT", surveyShape, fPlastic);
809 TGeoVolume* vIcb = new TGeoVolume("V0L_ICB", surveyShape, fPlastic);
811 fmd1BotVolume->AddNode(vIct, 1, new TGeoTranslation(lict[0],lict[1],lict[2]));
812 fmd1BotVolume->AddNode(vIcb, 1, new TGeoTranslation(licb[0],licb[1],licb[2]));
817 //____________________________________________________________________
819 AliFMDGeometryBuilder::FMD2Geometry(const AliFMD2* fmd2,
820 TGeoVolume* innerTop,
821 TGeoVolume* innerBot,
822 TGeoVolume* outerTop,
823 TGeoVolume* outerBot)
825 // Setup the FMD2 geometry. The FMD2 has no
826 // special support as it is at the momement.
828 // See also AliFMDGeometryBuilder::DetectorGeometry
830 if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
831 AliFMDRing* ring = fmd2->GetOuter();
832 Double_t z = fmd2->GetOuterZ();
833 Double_t framelr = 32.01; // fmd2->GetOuterHoneyHighR()+0.5;
834 Double_t framehr = 33.611; // fmd2->GetOuterHoneyHighR()+1.8;
835 Double_t framel = 14.8; // framehz - framelz;
836 // Double_t backth = 0.3;
837 Double_t backth = 0.03;
838 Double_t framelz = -(2.38
839 - ring->GetModuleDepth()
840 - ring->GetModuleSpacing() / 2);
841 // Double_t framelz = -0.8;
842 // Double_t framehz = framelz + backth + framel;
843 Double_t coverlr = 4.3; // fmd2->GetInner()->GetLowR()+1;
844 Double_t coverhr = framehr; // - 1;
846 TString fmd2TopName = TString::Format(fgkFMDName, fmd2->GetId(), 'T');
847 TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(fmd2TopName);
848 TString fmd2BotName = TString::Format(fgkFMDName, fmd2->GetId(), 'B');
849 TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(fmd2BotName);
850 fmd2TopVolume->SetTitle("FMD2 top half");
851 fmd2BotVolume->SetTitle("FMD2 bottom half");
853 DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z,
854 innerTop, innerBot, outerTop, outerBot);
856 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("FMD2_support");
857 TGeoShape* cylinderShape = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
858 TGeoVolume* cylinderVolume = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
860 TGeoShape* coverShape = new TGeoTubeSeg(coverlr,coverhr,backth/2,0,180);
861 TGeoVolume* coverVolume = new TGeoVolume(Form(fgkTopName, fmd2->GetId()),
863 cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
864 cylinderShape->SetTitle("FMD2 cylinder");
865 cylinderVolume->SetTitle("FMD2 cylinder");
866 cylinderVolume->SetTransparency(63);
867 coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
868 coverShape->SetTitle("FMD2 cover");
869 coverVolume->SetTitle("FMD2 cover");
870 coverVolume->SetTransparency(63);
872 TGeoTranslation* trans = 0;
873 support->AddNode(coverVolume,1, new TGeoTranslation(0,0,backth/2));
874 support->AddNode(cylinderVolume, 1, new TGeoTranslation(0,0,backth+framel/2));
877 Double_t f1l = 15.6085;
880 Int_t nFiducialHoles = 4;
881 Double_t precHoles[][2] = { { 32.4948, 29.6663 },
882 { 33.9104, 31.0819 },
883 { 34.8177, 33.4035 },
884 { 35.5028, 32.6744 } };
885 Double_t precRadius = .25;
886 Double_t flangeA = TMath::Pi()/4;
888 new TGeoBBox("FMD2_flange_base", f1l/2, f1w/2, f1d/2);
889 new TGeoTube("FMD2_fiducial_hole", 0, precRadius, f1d/2+.1);
890 Double_t flangeX = framehr + f1l/2;
891 TVector2 flangeC(flangeX * TMath::Cos(flangeA),
892 flangeX * TMath::Sin(flangeA));
893 TString flangeComb("FMD2_flange_base-(");
894 new TGeoBBox("FMD2_flange_slit", 7./2, 1.5/2, f1d/2+.1);
895 trans = new TGeoTranslation(-f1l/2+1+7./2, +.5+1.5/2, 0);
896 trans->SetName("FMD2_flange_slit_mat1");
897 trans->RegisterYourself();
898 trans = new TGeoTranslation(-f1l/2+1+7./2, -.5-1.5/2, 0);
899 trans->SetName("FMD2_flange_slit_mat2");
900 trans->RegisterYourself();
901 flangeComb.Append("FMD2_flange_slit:FMD2_flange_slit_mat1+"
902 "FMD2_flange_slit:FMD2_flange_slit_mat2+");
903 for (Int_t i = 0; i < nFiducialHoles; i++) {
904 TVector2 v(precHoles[i][0], precHoles[i][1]);
906 TVector2 r = v.Rotate(-flangeA);
907 TGeoTranslation* t1 = new TGeoTranslation(r.X(), r.Y(), 0);
908 TGeoTranslation* t2 = new TGeoTranslation(r.X(), -r.Y(), 0);
909 t1->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+0));
910 t2->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+1));
911 t1->RegisterYourself();
912 t2->RegisterYourself();
913 flangeComb.Append(Form("FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d+"
914 "FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d%c",
915 2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
917 // Final flange shape, and at to full shape
918 TGeoCompositeShape* flangeS = new TGeoCompositeShape(flangeComb.Data());
919 flangeS->SetName("FMD2_flange");
920 TGeoVolume* flangeV = new TGeoVolume("FMD2_flange", flangeS, fAl);
926 new TGeoBBox("FMD2_flange_spacer_base", f2l/2, f2w/2, f2d/2);
927 new TGeoTube("FMD2_flange_spacer_hole", 0, 2.5, f2w/2+.1);
928 TGeoRotation* holeRot = new TGeoRotation();
929 holeRot->RotateY(90);
930 holeRot->RotateZ(90);
931 TGeoCombiTrans* combo = 0;
932 combo = new TGeoCombiTrans(0, 0, f2d/2-.5-2.5, holeRot);
933 combo->SetName("FMD2_flange_spacer_hole_mat1");
934 combo->RegisterYourself();
935 combo = new TGeoCombiTrans(0, 0, -f2d/2+.5+2.5, holeRot);
936 combo->SetName("FMD2_flange_spacer_hole_mat2");
937 combo->RegisterYourself();
938 TString spacerComp("FMD2_flange_spacer_base-("
939 "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat1+"
940 "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat2)");
941 TGeoCompositeShape* spacerS = new TGeoCompositeShape(spacerComp.Data());
942 TGeoVolume* spacerV = new TGeoVolume("FMD2_flange_spacer",
945 Double_t extraL = framehr-framelr;
946 TGeoBBox* extraS = new TGeoBBox("FMD2_flange_extra",
947 extraL/2, f1w/2, f1d/2);
948 TGeoVolume* extraV = new TGeoVolume("FMD2_flange_extra", extraS,fAl);
949 TGeoVolumeAssembly* wingV = new TGeoVolumeAssembly("FMD2_wing");
950 TGeoVolume* tension = TensionBox();
951 TGeoTube* wireS = new TGeoTube(0, .05, (framehr-coverlr)/2);
952 TGeoVolume* wireV = new TGeoVolume("FMD2_tension_wire",
954 wingV->AddNode(flangeV, 1, new TGeoTranslation(f1l/2, 0, f1d/2));
955 wingV->AddNode(flangeV, 2, new TGeoTranslation(f1l/2, 0, -f2d-f1d/2));
956 wingV->AddNode(extraV, 1, new TGeoCombiTrans(-extraL/2, 0, f1d/2, 0));
957 wingV->AddNode(spacerV, 1, new TGeoTranslation(1+f2l/2,-f2w/2+f1w/2,
959 wingV->AddNode(spacerV, 2, new TGeoTranslation(1+f2l/2,+f2w/2-f1w/2,
961 TGeoRotation* tensionR = new TGeoRotation;
962 tensionR->RotateY(90);
963 wingV->AddNode(tension, 1, new TGeoCombiTrans(4, 0, f1d+1.2, tensionR));
964 TGeoRotation* wireR = new TGeoRotation;
966 wingV->AddNode(wireV, 1, new TGeoCombiTrans(-(framehr-coverlr)/2, 0, f1d+1,
969 TGeoCombiTrans* extraM1 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
970 extraM1->RotateZ(45);
971 extraM1->RegisterYourself();
972 extraM1->SetName("FMD2_back_cover_slit1");
973 TGeoCombiTrans* extraM2 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
974 extraM2->RotateZ(135);
975 extraM2->RegisterYourself();
976 extraM2->SetName("FMD2_back_cover_slit2");
977 TString coverComp(Form(fgkTopName, fmd2->GetId()));
978 coverComp.Append("-(FMD2_flange_extra:FMD2_back_cover_slit1"
979 "+FMD2_flange_extra:FMD2_back_cover_slit2)");
980 TGeoCompositeShape* cover2Shape = new TGeoCompositeShape(coverComp.Data());
981 cover2Shape->SetName("FMD2_back_cover");
982 TGeoVolume* cover2Volume = new TGeoVolume("FMD2_back_cover", cover2Shape,fC);
983 support->AddNode(cover2Volume,2,
984 new TGeoTranslation(0,0,backth+framel+backth/2));
986 TGeoCombiTrans* trans1 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
987 TGeoCombiTrans* trans2 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
989 trans2->RotateZ(135);
990 support->AddNode(wingV, 1, trans1);
991 support->AddNode(wingV, 2, trans2);
992 AliFMDDebug(1, ("FMD2 support offset is %f", framelz));
994 for (Int_t i = 0; i < 2; i++) {
995 TGeoVolume* mother = (i < 1 ? fmd2TopVolume : fmd2BotVolume);
997 Double_t phi = 360. / 2 * i;
998 TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i));
1000 TGeoMatrix* matrix = new TGeoCombiTrans(0, 0, framelz, rot);
1001 mother->AddNode(support, i, matrix);
1004 // Must be done after filling the assemblies
1005 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
1006 TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
1007 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
1008 fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
1009 top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
1010 top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
1016 //____________________________________________________________________
1018 AliFMDGeometryBuilder::FMD3Geometry(const AliFMD3* fmd3,
1019 TGeoVolume* innerTop,
1020 TGeoVolume* innerBot,
1021 TGeoVolume* outerTop,
1022 TGeoVolume* outerBot)
1024 // Setup the FMD3 geometry. The FMD2 has a rather elaborate support
1025 // structure, as the support will also support the vacuum
1028 // See also AliFMDGeometryBuilder::DetectorGeometry
1030 if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
1032 //__________________________________________________________________
1033 // Basic detector set-up.
1034 TString fmd3TopName = TString::Format(fgkFMDName, fmd3->GetId(), 'T');
1035 TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(fmd3TopName);
1036 TString fmd3BotName = TString::Format(fgkFMDName, fmd3->GetId(), 'B');
1037 TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(fmd3BotName);
1038 fmd3TopVolume->SetTitle("FMD3 top half");
1039 fmd3BotVolume->SetTitle("FMD3 bottom half");
1040 DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, fmd3->GetInnerZ(),
1041 innerTop, innerBot, outerTop, outerBot);
1043 //__________________________________________________________________
1044 // Mother for all support material
1045 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
1046 support->SetTitle("FMD3 support");
1048 //__________________________________________________________________
1050 const TObjArray& radii = fmd3->ConeRadii();
1051 Int_t nRadii = radii.GetEntriesFast();
1052 TGeoPcon* coneBase = new TGeoPcon("FMD3_cone_base", 0., 180., nRadii);
1055 for (Int_t i = 0; i < nRadii; i++) {
1056 TVector3* v = static_cast<TVector3*>(radii.At(i));
1057 coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
1059 else if (i == 4) r4 = v;
1061 TString coneComb("(FMD3_cone_base");
1063 //__________________________________________________________________
1065 double flangeDepth = fmd3->GetFlangeDepth() / 2;
1066 double flangeLength = fmd3->GetFlangeLength() / 2;
1067 double flangeWidth = fmd3->GetFlangeWidth() / 2;
1068 new TGeoBBox("FMD3_flange_base", flangeLength, flangeWidth, flangeDepth);
1071 const TObjArray& fiducialHoles = fmd3->FiducialHoles();
1072 double fiducialRadius = fmd3->GetFiducialRadius();
1074 TGeoTube* fiducialShape =
1076 new TGeoTube("FMD3_fiducial_hole", 0, fiducialRadius, flangeDepth+.1);
1077 Int_t nFiducialHoles = fiducialHoles.GetEntriesFast();
1078 double flangeAngle = TMath::Pi() / 4;
1079 double flangeX = r5->Y()+flangeLength;
1080 TVector2 flangeC(flangeX * TMath::Cos(flangeAngle),
1081 flangeX * TMath::Sin(flangeAngle));
1082 TString flangeComb("FMD3_flange_base-(");
1083 #if 0// For debugging geometry
1084 TGeoVolume* fiducialVolume = new TGeoVolume("FMD3_fiducial", fiducialShape);
1085 fiducialVolume->SetLineColor(kGreen);
1087 for (Int_t i = 0; i < nFiducialHoles; i++) {
1088 TVector2& v = *(static_cast<TVector2*>(fiducialHoles.At(i)));
1090 TVector2 r = v.Rotate(-flangeAngle);
1091 TGeoTranslation* t1 = new TGeoTranslation(r.X(), r.Y(), 0);
1092 TGeoTranslation* t2 = new TGeoTranslation(r.X(), -r.Y(), 0);
1093 t1->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+0));
1094 t2->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+1));
1095 t1->RegisterYourself();
1096 t2->RegisterYourself();
1097 flangeComb.Append(Form("FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d+"
1098 "FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d%c",
1099 2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
1100 #if 0 // For debugging geometry
1101 support->AddNode(fiducialVolume, 2*i+0, t1);
1102 support->AddNode(fiducialVolume, 2*i+1, t2);
1106 // Final flange shape, and at to full shape
1107 TGeoCompositeShape* flangeShape = new TGeoCompositeShape(flangeComb.Data());
1108 flangeShape->SetName("FMD3_flange");
1109 for (Int_t i = 0; i < 2; i++) {
1110 TGeoRotation* rot = new TGeoRotation();
1111 rot->RotateZ((i+.5)*90);
1112 TVector2 v(flangeX, 0);
1113 TVector2 w = v.Rotate((i+.5) * 2 * flangeAngle);
1114 TGeoCombiTrans* trans = new TGeoCombiTrans(w.X(),w.Y(),
1115 r4->X()+flangeDepth, rot);
1116 trans->SetName(Form("FMD3_flange_matrix%d", i));
1117 trans->RegisterYourself();
1118 coneComb.Append(Form("+FMD3_flange:FMD3_flange_matrix%d", i));
1120 coneComb.Append(")-(");
1122 //__________________________________________________________________
1124 Double_t holeL = fmd3->GetHoleLength()/2;
1125 Double_t holeD = fmd3->GetHoleDepth()/2;
1126 Double_t holeLW = fmd3->GetHoleLowWidth()/2;
1127 Double_t holeHW = fmd3->GetHoleHighWidth()/2;
1128 Double_t holeA = fmd3->GetConeOuterAngle();
1129 Double_t holeA2 = TMath::Pi() - fmd3->GetConeOuterAngle();
1130 Double_t holeO = fmd3->GetHoleOffset();
1131 Double_t holeZ = (holeO
1132 + holeL * TMath::Cos(holeA)
1133 - holeD * TMath::Sin(holeA2));
1134 Double_t holeX = (fmd3->ConeR(-holeZ + fmd3->GetInnerZ() + fmd3->GetNoseZ())
1135 - holeD * TMath::Sin(holeA2));
1136 new TGeoTrd1("FMD3_cone_hole", holeLW, holeHW, holeD, holeL);
1137 TGeoTrd1* plateShape = new TGeoTrd1("FMD3_cooling_plate",
1138 holeLW, holeHW, .033, holeL);
1139 TGeoRotation* holeRot = new TGeoRotation();
1140 holeRot->SetName("FMD3_cone_hole_rotation");
1141 holeRot->RotateZ(90);
1142 holeRot->RotateY(holeA*180/TMath::Pi());
1143 TGeoCombiTrans* holeBaseTrans = new TGeoCombiTrans(holeX, 0, holeZ, holeRot);
1144 holeBaseTrans->SetName("FMD3_cone_hole_base_matrix");
1145 // TGeoRotation* plateRot = new TGeoRotation();
1146 // plateRot->SetName("FMD3_cone_plate_rotation");
1147 // plateRot->RotateZ(90);
1148 // plateRot->RotateY(plateA*180/TMath::Pi());
1149 // TGeoCombiTrans* plateBaseTrans = new
1150 // TGeoCombiTrans(plateX,0,plateZ,plateRot);
1151 TGeoVolume* plateVolume = new TGeoVolume("FMD3_cooling_plate",
1153 plateShape->SetTitle("FMD3 cooling plate");
1154 plateVolume->SetTitle("FMD3 cooling plate");
1155 for (Int_t i = 0; i < 4; i++) {
1156 Double_t ang = 360. / 8 * (i + .5);
1157 TGeoCombiTrans* trans = new TGeoCombiTrans(*holeBaseTrans);
1158 trans->RotateZ(ang);
1159 trans->SetName(Form("FMD3_cone_hole_matrix%d", i));
1160 trans->RegisterYourself();
1161 trans = new TGeoCombiTrans(*holeBaseTrans);
1162 trans->RotateZ(ang);
1163 trans->SetName(Form("FMD3_cooling_plate_matrix%d", i));
1164 coneComb.Append(Form("FMD3_cone_hole:FMD3_cone_hole_matrix%d+", i));
1165 support->AddNode(plateVolume, i, trans);
1168 //__________________________________________________________________
1170 Double_t boltRadius = fmd3->GetBoltRadius();
1171 Double_t boltLength = fmd3->GetBoltLength() / 2;
1172 Double_t boltZ1 = fmd3->GetInnerZ()+fmd3->GetNoseZ()-10;
1173 Double_t boltZ2 = fmd3->GetInnerZ()+fmd3->GetNoseZ()-20;
1174 Double_t boltXE = 2*boltLength*TMath::Cos(fmd3->GetConeOuterAngle());
1175 Double_t boltX1 = (fmd3->ConeR(boltZ1) - boltXE);
1176 Double_t boltX2 = (fmd3->ConeR(boltZ2) - boltXE);
1178 new TGeoTube("FMD3_bolt_hole", 0, boltRadius, boltLength+.2);
1179 TGeoTube* boltShape = new TGeoTube("FMD3_bolt", 0, boltRadius, boltLength);
1180 TGeoRotation* boltRot = new TGeoRotation();
1181 boltRot->RotateY(-fmd3->GetConeOuterAngle()*180/TMath::Pi());
1182 TGeoCombiTrans* boltTrans1 = new TGeoCombiTrans(boltX1, 0, 10, boltRot);
1183 TGeoCombiTrans* boltTrans2 = new TGeoCombiTrans(boltX2, 0, 20, boltRot);
1184 TGeoCombiTrans* boltTrans3 = new TGeoCombiTrans(*boltTrans1);
1185 TGeoCombiTrans* boltTrans4 = new TGeoCombiTrans(*boltTrans2);
1186 boltTrans3->RotateZ(180);
1187 boltTrans4->RotateZ(180);
1188 boltTrans1->SetName("FMD3_bolt_matrix1");
1189 boltTrans2->SetName("FMD3_bolt_matrix2");
1190 boltTrans3->SetName("FMD3_bolt_matrix3");
1191 boltTrans4->SetName("FMD3_bolt_matrix4");
1192 boltTrans1->RegisterYourself();
1193 boltTrans2->RegisterYourself();
1194 boltTrans3->RegisterYourself();
1195 boltTrans4->RegisterYourself();
1196 coneComb.Append("FMD3_bolt_hole:FMD3_bolt_matrix1"
1197 "+FMD3_bolt_hole:FMD3_bolt_matrix2"
1198 "+FMD3_bolt_hole:FMD3_bolt_matrix3"
1199 "+FMD3_bolt_hole:FMD3_bolt_matrix4");
1200 TGeoVolume* boltVolume = new TGeoVolume("FMD3_bolt", boltShape, fSteel);
1201 support->AddNode(boltVolume, 1, boltTrans1);
1202 support->AddNode(boltVolume, 2, boltTrans2);
1203 boltShape->SetTitle("FMD3 steering bolt");
1204 boltVolume->SetTitle("FMD3 steering bolt");
1206 //__________________________________________________________________
1207 // Cut-outs for tension wheel sheeve
1208 new TGeoBBox("FMD3_sheeve_hole", .55, .75, 1.16);
1209 Double_t sheeveHoleZ = fmd3->GetInnerZ() + fmd3->GetNoseZ() - .75;
1210 Double_t sheeveHoleR = fmd3->ConeR(sheeveHoleZ) - .55 + .2572222;
1211 TGeoCombiTrans* sheeveMat1 = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1212 TGeoCombiTrans* sheeveMat2 = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1213 sheeveMat1->RotateZ(45);
1214 sheeveMat2->RotateZ(135);
1215 sheeveMat1->SetName("FMD3_sheeve_hole_matrix1");
1216 sheeveMat2->SetName("FMD3_sheeve_hole_matrix2");
1217 sheeveMat1->RegisterYourself();
1218 sheeveMat2->RegisterYourself();
1219 coneComb.Append("+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix1"
1220 "+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix2)");
1222 //__________________________________________________________________
1224 Double_t sheeveL = 1.15;
1225 TGeoBBox* sheeveSideS = new TGeoBBox("FMD3_sheeve_side",
1227 TGeoBBox* sheeveBackS = new TGeoBBox("FMD3_sheeve_back",
1229 TGeoBBox* sheeveWingS = new TGeoBBox("FMD3_sheeve_wing",
1231 TGeoPcon* sheeveWheelS = new TGeoPcon("FMD3_sheeve_wheel", 0, 360, 9);
1232 Double_t sheeveInnerR = 0; // .2;
1233 Double_t sheeveR = .875;
1234 Double_t sheeveWheelZ = .95;
1235 sheeveWheelS->DefineSection(0, -.25, sheeveInnerR, 1);
1236 sheeveWheelS->DefineSection(1, -.125, sheeveInnerR, 1);
1237 sheeveWheelS->DefineSection(2, -.125, sheeveInnerR, sheeveWheelZ);
1238 sheeveWheelS->DefineSection(3, -.0625, sheeveInnerR, sheeveR+.02);
1239 sheeveWheelS->DefineSection(4, 0.000, sheeveInnerR, sheeveR);
1240 sheeveWheelS->DefineSection(5, +.0625, sheeveInnerR, sheeveR+.02);
1241 sheeveWheelS->DefineSection(6, +.125, sheeveInnerR, sheeveWheelZ);
1242 sheeveWheelS->DefineSection(7, +.125, sheeveInnerR, 1);
1243 sheeveWheelS->DefineSection(8, +.25, sheeveInnerR, 1);
1244 TGeoVolume* sheeveSideV = new TGeoVolume("FMD3_sheeve_side",
1245 sheeveSideS, fPlastic);
1246 TGeoVolume* sheeveBackV = new TGeoVolume("FMD3_sheeve_back",
1247 sheeveBackS, fPlastic);
1248 TGeoVolume* sheeveWingV = new TGeoVolume("FMD3_sheeve_wing",
1249 sheeveWingS, fPlastic);
1250 TGeoVolume* sheeveWheelV= new TGeoVolume("FMD3_sheeve_wheel",
1251 sheeveWheelS, fPlastic);
1252 TGeoVolumeAssembly* sheeveBox = new TGeoVolumeAssembly("FMD3_sheeve_box");
1253 sheeveBox->AddNode(sheeveSideV, 1, new TGeoTranslation(0, -.5, 0));
1254 sheeveBox->AddNode(sheeveSideV, 2, new TGeoTranslation(0, +.5, 0));
1255 sheeveBox->AddNode(sheeveBackV, 1, new TGeoTranslation(0, 0, 2.0+.15-1.15));
1256 sheeveBox->AddNode(sheeveWingV, 1, new TGeoTranslation(.55-.15, -.90, 0));
1257 sheeveBox->AddNode(sheeveWingV, 2, new TGeoTranslation(.55-.15, +.90, 0));
1258 TGeoRotation* sheeveWheelR = new TGeoRotation;
1259 sheeveWheelR->RotateX(90);
1260 TGeoCombiTrans* sheeveWheelM = new TGeoCombiTrans(0, 0, sheeveWheelZ-sheeveL,
1262 sheeveBox->AddNode(sheeveWheelV, 1, sheeveWheelM);
1263 support->AddNode(sheeveBox, 1, sheeveMat1);
1264 support->AddNode(sheeveBox, 2, sheeveMat2);
1268 //__________________________________________________________________
1270 TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneComb.Data());
1271 coneShape->SetName("FMD3_cone");
1272 coneShape->SetTitle("FMD3 cone");
1273 TGeoVolume* coneVolume = new TGeoVolume("FMD3_Cone", coneShape, fC);
1274 coneVolume->SetLineColor(kRed);
1275 support->AddNode(coneVolume, 0, new TGeoTranslation(0, 0, 0));
1277 //__________________________________________________________________
1279 TGeoVolume* tensionBox = TensionBox();
1280 Double_t tensionH = .6;
1281 Double_t tensionL = 4;
1282 Double_t tensionZ = 23.654;
1283 Double_t tensionR = fmd3->ConeR(fmd3->GetInnerZ() + fmd3->GetNoseZ()
1285 Double_t tensionAr = fmd3->GetConeOuterAngle();
1286 Double_t tensionA = tensionAr * 180 / TMath::Pi();
1287 TGeoRotation* tensionQ = new TGeoRotation;
1288 tensionQ->RotateY(tensionA);
1289 TGeoCombiTrans* tensionM1 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1290 TGeoCombiTrans* tensionM2 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1291 tensionM1->RotateZ(45);
1292 tensionM2->RotateZ(135);
1293 support->AddNode(tensionBox, 1, tensionM1);
1294 support->AddNode(tensionBox, 2, tensionM2);
1296 // Double_t tensionHR = 0.15;
1297 Double_t wireT = .1/2;
1298 Double_t wireZ1 = (tensionZ
1299 - tensionL * TMath::Cos(tensionAr)
1300 - tensionH * TMath::Sin(tensionAr));
1301 Double_t wireR1 = (tensionR
1302 - tensionL * TMath::Sin(tensionAr)
1303 + tensionH * TMath::Cos(tensionAr));
1304 AliFMDDebug(10, ("Wire Z1: %f=%f-%f*cos(%f)-%f*sin(%f)",
1305 wireZ1, tensionZ, tensionL, tensionAr, tensionH, tensionAr));
1306 AliFMDDebug(10, ("Wire R1: %f=%f-%f*sin(%f)-%f*cos(%f)",
1307 wireR1, tensionR, tensionL, tensionAr, tensionH, tensionAr));
1309 Double_t wireStartA = 42.3 * TMath::Pi() / 180;
1310 Double_t wireZ2 = (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1312 - wireT * TMath::Sin(wireStartA));
1313 /* (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1314 - wireT * TMath::Sin(wireStartA)
1316 AliFMDDebug(10, ("wireZ2=%f=%f*(1-%f)", wireZ2, sheeveWheelZ,
1317 TMath::Sin(wireStartA)));
1318 Double_t wireR2 = (sheeveHoleR +
1319 sheeveWheelZ * TMath::Cos(wireStartA) +
1320 wireT * TMath::Cos(wireStartA));
1321 Double_t wireDR = wireR1-wireR2;
1322 Double_t wireDZ = wireZ1-wireZ2;
1323 Double_t wireL = TMath::Sqrt(wireDR*wireDR+wireDZ*wireDZ)-.01;
1324 Double_t wireAngle = TMath::ATan2(wireDR,wireDZ);
1325 TGeoTube* wireShape = new TGeoTube("FMD3_wire", 0, wireT, wireL/2);
1326 TGeoVolume* wireVolume = new TGeoVolume("FMD3_wire", wireShape,fSteel);
1327 TGeoRotation* wireRot = new TGeoRotation();
1328 wireRot->RotateY(180/TMath::Pi()*wireAngle);
1329 Double_t wireR = wireR2 + wireDR / 2;
1330 Double_t wireZ = wireZ2 + wireDZ / 2;
1331 TGeoCombiTrans* wireM1 = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1332 TGeoCombiTrans* wireM2 = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1333 wireM1->RotateZ(45);
1334 wireM2->RotateZ(135);
1335 support->AddNode(wireVolume, 1, wireM1);
1336 support->AddNode(wireVolume, 2, wireM2);
1339 TGeoTorus* wireTS = new TGeoTorus(sheeveWheelZ+wireT, 0, wireT, 0,
1340 90-wireStartA*180/TMath::Pi());
1341 TGeoVolume* wireTV = new TGeoVolume("FMD3_bend_wire",wireTS,fSteel);
1342 TGeoRotation* wireTR = new TGeoRotation;
1343 wireTR->RotateY(90);
1344 wireTR->RotateZ(-90);
1345 Double_t wireTZ = sheeveWheelZ;
1346 TGeoCombiTrans* wireTM1 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1347 TGeoCombiTrans* wireTM2 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1348 wireTM1->RotateZ(45);
1349 wireTM2->RotateZ(135);
1350 support->AddNode(wireTV, 1, wireTM1);
1351 support->AddNode(wireTV, 2, wireTM2);
1353 Double_t colarR = 4.05;
1354 Double_t wireEL = sheeveHoleR - colarR;
1355 TGeoTube* wireES = new TGeoTube("FMD3_end_wire", 0, wireT, wireEL/2);
1356 TGeoVolume* wireEV = new TGeoVolume("FMD3_end_wire", wireES, fSteel);
1357 TGeoRotation* wireER = new TGeoRotation;
1358 wireER->RotateY(90);
1359 TGeoCombiTrans* wireEM1 = new TGeoCombiTrans(colarR+wireEL/2,0,
1361 TGeoCombiTrans* wireEM2 = new TGeoCombiTrans(colarR+wireEL/2,0,
1363 wireEM1->RotateZ(45);
1364 wireEM2->RotateZ(135);
1365 support->AddNode(wireEV, 1, wireEM1);
1366 support->AddNode(wireEV, 2, wireEM2);
1371 //__________________________________________________________________
1372 // Place support volumes in half-detector volumes
1373 Double_t z = fmd3->GetInnerZ();
1374 AliFMDDebug(1, ("FMD3 support at z=%f", -fmd3->GetNoseZ()));
1375 TGeoTranslation* t1 = new TGeoTranslation(0, 0, -fmd3->GetNoseZ());
1376 fmd3TopVolume->AddNode(support, 1, t1);
1377 TGeoCombiTrans* t2 = new TGeoCombiTrans(*t1);
1379 fmd3BotVolume->AddNode(support, 2, t2);
1381 TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
1383 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
1384 TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1385 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
1386 fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1387 top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1388 top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1394 //____________________________________________________________________
1396 AliFMDGeometryBuilder::Exec(Option_t*)
1398 // Setup up the FMD geometry.
1399 AliFMDDebug(1, ("\tGeometry options: %s",
1400 (fDetailed ? "divided into strips" : "one volume")));
1402 AliFatal("No TGeoManager defined");
1406 fSi = gGeoManager->GetMedium("FMD_Si$");
1407 fC = gGeoManager->GetMedium("FMD_Carbon$");
1408 fAl = gGeoManager->GetMedium("FMD_Aluminum$");
1409 fChip = gGeoManager->GetMedium("FMD_Si Chip$");
1410 fAir = gGeoManager->GetMedium("FMD_Air$");
1411 fPCB = gGeoManager->GetMedium("FMD_PCB$");
1412 fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1413 fCopper = gGeoManager->GetMedium("FMD_Copper$");
1414 fSteel = gGeoManager->GetMedium("FMD_Steel$");
1416 if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1417 AliError("Failed to get some or all tracking mediums");
1420 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1421 AliFMDRing* inner = fmd->GetInner();
1422 AliFMDRing* outer = fmd->GetOuter();
1423 RingGeometry(inner);
1424 RingGeometry(outer);
1425 TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1427 TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1429 TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1431 TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1434 FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1435 FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1436 FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1437 #ifndef USE_PRE_MOVE
1438 fmd->SetSectorOff(fSectorOff);
1439 fmd->SetModuleOff(fModuleOff);
1440 fmd->SetRingOff(fRingOff);
1441 fmd->SetDetectorOff(fDetectorOff);
1442 fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1444 // fmd->ExtractGeomInfo();
1449 //____________________________________________________________________