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 TString sensorName = TString::Format(fgkSensorName, id);
211 TGeoVolume* sensorVolume = new TGeoVolume(sensorName, sensorShape, fSi);
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 TString activeName = TString::Format(fgkActiveName, id);
235 TGeoVolume* activeVolume = new TGeoVolume(activeName,activeShape,fSi);
236 activeVolume->SetTitle(Form("FMD %s active area", lName));
237 TString sectorName = TString::Format(fgkSectorName,id);
238 TGeoVolume* sectorVolume = activeVolume->Divide(sectorName, 2, 2, -theta,
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 TString stripName = TString::Format(fgkStripName, id);
247 TGeoVolume* stripVolume = sectorVolume->Divide(stripName,
248 1, ns, stripoff, dstrip,
250 stripVolume->SetTitle(Form("FMD %s strip", lName));
251 sid = stripVolume->GetNumber();
252 sensorVolume->AddNodeOverlap(activeVolume, 0);
256 case 'I': fActiveId[0] = sid; break;
257 case 'O': fActiveId[1] = sid; break;
260 //------------------------------------------------------------------
262 // PCB layer of hybrid
263 TGeoShape* pcbShape = MakeXTRU(r->GetHybridVerticies(), pcbThick);
264 pcbShape->SetName(Form("FMD%c_hybrid_pcb", id));
265 pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
266 TString pcbName = TString::Format(fgkPCBName, id);
267 TGeoVolume* pcbVolume = new TGeoVolume(pcbName, pcbShape, fPCB);
268 pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
271 TGeoShape* cuShape = MakeXTRU(r->GetHybridVerticies(), cuThick);
272 cuShape->SetName(Form("FMD%c_hybrid_copper", id));
273 cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
274 TString cuName = TString::Format(fgkCuName,id);
275 TGeoVolume* cuVolume = new TGeoVolume(cuName,cuShape,fCopper);
276 cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
279 TGeoShape* chipShape = MakeXTRU(r->GetHybridVerticies(), chipThick);
280 chipShape->SetName(Form("FMD%c_hybrid_chip", id));
281 chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
282 TString chipName = TString::Format(fgkChipName,id);
283 TGeoVolume* chipVolume = new TGeoVolume(chipName,chipShape,fChip);
284 chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
286 //------------------------------------------------------------------
288 Double_t legr = r->GetLegRadius();
289 Double_t legl = r->GetLegLength();
293 TGeoTube* shortLegShape = new TGeoTube(0, legr, (legl-lege) / 2);
294 shortLegShape->SetName(Form(fgkShortLegName, id));
295 shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
296 TString shortLegName = TString::Format(fgkShortLegName, id);
297 TGeoVolume* shortLegVolume = new TGeoVolume(shortLegName,
298 shortLegShape, fCopper);
299 shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
301 TGeoTube* longLegShape = new TGeoTube(0, legr,
302 (legl - lege + modSpace) / 2);
303 longLegShape->SetName(Form(fgkLongLegName, id));
304 longLegShape->SetTitle(Form("FMD %s long support foot", lName));
305 TString longLegName = TString::Format(fgkLongLegName, id);
306 TGeoVolume* longLegVolume = new TGeoVolume(longLegName,
307 longLegShape, fCopper);
308 longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
312 //------------------------------------------------------------------
313 // Placement of module volumes in assemblies
316 for (Int_t i = 0; i < 3; i++) {
317 TVector2* vv = r->GetFootPosition(i);
318 // TVector2 uu = vv->Rotate(TMath::Pi()/2);
323 // Back container volume
324 TGeoVolume* backVolume = new TGeoVolumeAssembly(Form(fgkBackVName, id));
325 backVolume->SetTitle(Form("FMD %s back module", lName));
326 TGeoVolume* frontVolume = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
327 frontVolume->SetTitle(Form("FMD %s front module", lName));
329 Double_t space = r->GetSpacing();
332 Double_t zb = siThick / 2;
333 Double_t zf = siThick / 2;
334 backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zb));
335 frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zf));
336 zb += siThick / 2 + space + pcbThick / 2;
337 zf += siThick / 2 + space + pcbThick / 2;
338 backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zb));
339 frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zf));
340 zb += (pcbThick + cuThick) / 2;
341 zf += (pcbThick + cuThick) / 2;
342 backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zf));
343 frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zb));
344 zb += (cuThick + chipThick) / 2;
345 zf += (cuThick + chipThick) / 2;
346 backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zb));
347 frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zf));
348 zb += pcbThick / 2 + (legl)/ 2 - lege;
349 zf += pcbThick / 2 + (legl + modSpace)/ 2 - lege;
350 for (Int_t i = 0; i < 3; i++) {
351 x = xfs[i]; // a->X() + legoff + legr;
353 backVolume->AddNode(shortLegVolume, i, new TGeoTranslation(x,y,zb));
354 frontVolume->AddNode(longLegVolume, i, new TGeoTranslation(x,y,zf));
357 //------------------------------------------------------------------
359 Double_t ddlr = r->GetFMDDLowR();
360 Double_t ddhr = r->GetFMDDHighR();
361 Double_t ddpt = r->GetFMDDPrintboardThickness();
362 Double_t ddct = r->GetFMDDCopperThickness();
363 Double_t ddit = r->GetFMDDChipThickness();
364 Double_t ddt = ddpt + ddct + ddit;
366 TString pcbdName(Form(fgkFMDDPCBName, id));
367 TString cudName(Form(fgkFMDDCuName, id));
368 TString chipdName(Form(fgkFMDDChipName, id));
369 new TGeoTubeSeg(Form("%s_inner", pcbdName.Data()), ddlr, ddhr, ddpt/2,0,180);
370 new TGeoTubeSeg(Form("%s_inner", cudName.Data()), ddlr, ddhr, ddct/2,0,180);
371 new TGeoTubeSeg(Form("%s_inner", chipdName.Data()), ddlr, ddhr, ddit/2,0,180);
386 new TGeoBBox(Form("%s_clip", pcbdName.Data()), clipWX, clipWY, ddpt);
387 new TGeoBBox(Form("%s_clip", cudName.Data()), clipWX, clipWY, ddct);
388 new TGeoBBox(Form("%s_clip", chipdName.Data()),clipWX, clipWY, ddit);
389 TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
392 trans->RegisterYourself();
393 TGeoShape* fmddPcbShape =
394 new TGeoCompositeShape(pcbdName.Data(),
395 Form("%s_inner*%s_clip:%s_trans",
399 TGeoShape* fmddCuShape =
400 new TGeoCompositeShape(cudName.Data(),
401 Form("%s_inner*%s_clip:%s_trans",
405 TGeoShape* fmddChipShape =
406 new TGeoCompositeShape(chipdName.Data(),
407 Form("%s_inner*%s_clip:%s_trans",
411 fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
412 fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
413 fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
415 TString fmddPcbName = TString::Format(fgkFMDDPCBName, id);
416 TGeoVolume* fmddPcbVolume = new TGeoVolume(fmddPcbName,
418 TString fmddCuName = TString::Format(fgkFMDDCuName, id);
419 TGeoVolume* fmddCuVolume = new TGeoVolume(fmddCuName,
420 fmddCuShape, fCopper);
421 TString fmddChipName = TString::Format(fgkFMDDChipName, id);
422 TGeoVolume* fmddChipVolume = new TGeoVolume(fmddChipName,
423 fmddChipShape, fChip);
424 fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
425 fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
426 fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
428 //------------------------------------------------------------------
429 // Half ring mother volumes.
430 TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
431 TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
432 TGeoVolume* halfRing = ringTopVolume;
433 ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
434 ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
436 //------------------------------------------------------------------
437 // Adding modules to half-rings
438 Int_t nmod = r->GetNModules();
439 AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
440 for (Int_t i = 0; i < nmod; i++) {
441 if (i == nmod / 2) halfRing = ringBotVolume;
442 Bool_t front = (i % 2 == (rng == 'I' ? 1 : 0));
443 TGeoVolume* vol = (front ? frontVolume : backVolume);
444 // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
445 Double_t z1 = (front ? -1 : 1) * modSpace / 2;
446 // Double_t z1 = (front ? 0 : modSpace);
447 Double_t th = (2 * i + 1) * theta;
448 TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0);
450 mat1->SetName(Form("FMD%c_module_%02d", id, i));
451 mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
452 halfRing->AddNode(vol, i, mat1);
455 //------------------------------------------------------------------
457 Double_t zi = r->GetFullDepth() - ddt;
459 for (Int_t i = 0; i < n; i++) {
460 halfRing = (i == 0 ? ringTopVolume : ringBotVolume);
461 Double_t phi = 360. / n * i;
462 TGeoRotation* rot = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
464 rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
465 Double_t z = zi + ddpt / 2;
466 halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
467 z += (ddpt + ddct) / 2;
468 halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
469 z += (ddct + ddit) / 2;
470 halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
478 //____________________________________________________________________
480 AliFMDGeometryBuilder::HoneycombShape(Int_t id, Char_t ring,
481 double r1, double r2,
482 double w, double t, double c)
484 // Make a honey comb shape from passed parameters.
486 // id Detector identifier (1,2, or 3)
487 // ring Ring identifier ('I' or 'O')
491 // t Thickness of material
492 // c Clearing from horizontal.
494 // Pointer to newly allocated composite shape.
495 TString form = Form("FMD%d%c_%%c_%%c", id, ring);
496 double a1 = TMath::ATan2(c, r1) * 180 / TMath::Pi();
498 TString fn = Form(form.Data(),'F','1');
499 TString bn = Form(form.Data(),'B','1');
500 TString cn = Form(form.Data(),'C','O');
501 TString in = Form(form.Data(),'R','I');
502 TString on = Form(form.Data(),'R','O');
503 TString en = Form(form.Data(),'E','X');
505 double x = r1 * TMath::Cos(TMath::Pi()*a1/180);
506 new TGeoTubeSeg(fn.Data(),r1,r2,t/2,0,180);
507 new TGeoTubeSeg(bn.Data(),r1,r2,t/2,0,180);
508 new TGeoBBox(cn.Data(),(r2-r1)/2,t/2,w/2);
509 new TGeoTubeSeg(in.Data(),r1,r1+t,w/2,0,180);
510 new TGeoTubeSeg(on.Data(),r2-t,r2,w/2,0,180);
511 new TGeoBBox(en.Data(),r2+.005,c/2+.005,w/2+.005);
513 TString ftn = Form(form.Data(),'F','T');
514 TString btn = Form(form.Data(),'F','B');
515 TString ltn = Form(form.Data(),'C','L');
516 TString rtn = Form(form.Data(),'C','R');
517 TString etn = Form(form.Data(),'E','X');
518 (new TGeoTranslation(ftn.Data(),0,0,+w/2-t/2))->RegisterYourself();
519 (new TGeoTranslation(btn.Data(),0,0,-w/2+t/2))->RegisterYourself();
520 (new TGeoTranslation(ltn.Data(),-(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
521 (new TGeoTranslation(rtn.Data(),(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
522 (new TGeoTranslation(etn.Data(),0, c/2,0))->RegisterYourself();
524 TString comp(Form("(%s:%s+%s:%s+%s+%s+%s:%s+%s:%s)-%s:%s",
525 fn.Data(),ftn.Data(),
526 bn.Data(),btn.Data(),
528 cn.Data(),ltn.Data(),
529 cn.Data(),rtn.Data(),
530 en.Data(),etn.Data()));
531 TGeoCompositeShape* shape = new TGeoCompositeShape(comp.Data());
532 shape->SetName(Form(fgkHCName,id,ring));
533 shape->SetTitle(Form("FMD%d%c Honeycomb shape", id, ring));
537 //____________________________________________________________________
539 AliFMDGeometryBuilder::TensionBox()
541 static TGeoVolumeAssembly* tensionBox = 0;
542 if (tensionBox) return tensionBox;
544 TGeoBBox* tensionEndS = new TGeoBBox("FMD_tension_end", .6, 3, .25);
545 TGeoBBox* tensionTopS = new TGeoBBox("FMD_tension_top", .1, .5, 3.5);
546 TGeoVolume* tensionEndV = new TGeoVolume("FMD_tension_end", tensionEndS,fAl);
547 TGeoVolume* tensionTopV = new TGeoVolume("FMD_tension_top", tensionTopS,fAl);
548 tensionBox = new TGeoVolumeAssembly("FMD_tension_box");
549 tensionBox->AddNode(tensionEndV, 1, new TGeoTranslation(.6, 0, -3.75));
550 tensionBox->AddNode(tensionEndV, 2, new TGeoTranslation(.6, 0, +3.75));
551 tensionBox->AddNode(tensionTopV, 1, new TGeoTranslation(0.1, +2.5, 0));
552 tensionBox->AddNode(tensionTopV, 2, new TGeoTranslation(0.1, -2.5, 0));
553 tensionBox->AddNode(tensionTopV, 3, new TGeoTranslation(1.1, +2.5, 0));
554 tensionBox->AddNode(tensionTopV, 4, new TGeoTranslation(1.1, -2.5, 0));
559 //____________________________________________________________________
561 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d,
562 TGeoVolume* topMother,
563 TGeoVolume* botMother,
565 TGeoVolume* innerTop,
566 TGeoVolume* innerBot,
567 TGeoVolume* outerTop,
568 TGeoVolume* outerBot)
570 // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
571 // This includes putting the Honeycomb support plates and the rings
572 // into the mother volumes.
575 // d The detector geometry to use
576 // mother The mother volume of the detector
577 // zmother The midpoint in global coordinates of detector vol.
578 // inner Pointer to inner ring volume
579 // outer Pointer to outer ring volume
582 // Pointer to mother (detector volume)
585 // Loop over the defined rings
586 for (int i = 0; i < 2; i++) {
591 TGeoVolume* tvol = 0;
592 TGeoVolume* bvol = 0;
596 lowr = d->GetInnerHoneyLowR();
597 highr = d->GetInnerHoneyHighR();
604 lowr = d->GetOuterHoneyLowR();
605 highr = d->GetOuterHoneyHighR();
612 Char_t c = r->GetId();
613 Int_t id = d->GetId();
614 Double_t hcThick = r->GetHoneycombThickness();
615 Double_t alThick = r->GetAlThickness();
616 Double_t z = TMath::Abs(rz - zMother);
618 // Place ring in mother volume
619 // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
620 AliFMDDebug(2, ("Placing volumes %s and %s in %s and %s at z=%f",
621 tvol->GetName(), bvol->GetName(),
622 topMother->GetName(), botMother->GetName(), z));
623 topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
624 botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
627 TGeoShape* hcSha = HoneycombShape(id, c, lowr, highr, hcThick, alThick);
628 TGeoVolume* hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
629 hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
631 z += (r->GetModuleDepth()
632 + r->GetModuleSpacing() / 2
633 + r->GetHoneycombThickness() / 2);
635 AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f",
636 hcVol->GetName(), topMother->GetName(),
637 botMother->GetName(), z));
639 topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
642 TGeoMatrix* bhcMatrix = new TGeoCombiTrans(0,0,z,0);
643 bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
644 bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
645 bhcMatrix->RotateZ(180);
646 botMother->AddNode(hcVol, 1, bhcMatrix);
651 //____________________________________________________________________
653 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1,
654 TGeoVolume* innerTop,
655 TGeoVolume* innerBot)
657 // Setup the FMD1 geometry. The FMD1 only has one ring, and no
658 // special support as it is at the momement.
660 // See also AliFMDGeometryBuilder::DetectorGeometry
662 if (!fmd1 || !innerTop || !innerBot) return 0;
663 AliFMDRing* r = fmd1->GetInner();
664 Double_t z = fmd1->GetInnerZ();
666 // `Top' or `Outside' master volume
667 TString fmd1TopName = TString::Format(fgkFMDName, fmd1->GetId(), 'T');
668 TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(fmd1TopName);
669 fmd1TopVolume->SetTitle("FMD1 top half");
671 // `Bottom' or `Inside' master volume
672 TString fmd1BotName = TString::Format(fgkFMDName, fmd1->GetId(), 'B');
673 TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(fmd1BotName);
674 fmd1BotVolume->SetTitle("FMD1 bottom half");
676 // Basic detector geometry
677 DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z,
678 innerTop, innerBot, 0, 0);
680 Double_t lidP[][3] = { { 0.00, 4.20, 20.95 },
681 { 0.15, 4.20, 20.95 },
682 { 0.15, 20.80, 20.95 },
683 { 3.00, 20.80, 20.95 },
684 { 3.00, 20.80, 22.30 },
685 { 3.15, 20.80, 22.30 },
686 { 3.15, 20.95, 24.65 },
687 { 3.30, 20.95, 24.65 },
688 { 3.30, 24.50, 24.65 },
689 { 6.80, 24.50, 24.65 },
690 { 6.80, 24.50, 26.00 },
691 { 6.95, 24.50, 26.00 } };
692 Double_t lidZStart = lidP[11][0];
693 TGeoPcon* lidBaseS = new TGeoPcon("FMD1_lid_base", 0, 180, 12);
694 for (size_t i = 0; i < 12; i++)
695 lidBaseS->DefineSection(i, lidP[i][0] - lidZStart, lidP[i][1], lidP[i][2]);
698 Double_t lidH[][2] = { { 7.84903, 24.15680 },
699 { 20.54900, 14.92970 },
700 { 21.99700, 12.70000 },
701 { 25.26090, 2.65502 } };
702 Double_t lidHR = .53 / 2;
703 Double_t lidHL = 0.16;
705 new TGeoTube("FMD1_lid_hole", 0, lidHR, lidHL/2);
706 TString lidComp("FMD1_lid_base-(");
707 TGeoTranslation* trans = 0;
708 for (size_t i = 0; i < 4; i++) {
709 trans = new TGeoTranslation(-lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
710 trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+0)));
711 trans->RegisterYourself();
712 trans = new TGeoTranslation(+lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
713 trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+1)));
714 trans->RegisterYourself();
715 lidComp.Append(Form("FMD1_lid_hole:FMD1_lid_hole_mat%d+"
716 "FMD1_lid_hole:FMD1_lid_hole_mat%d%c",
717 int(2 * i), int(2 * i + 1), int(i == 3 ? ')' : '+')));
719 TGeoCompositeShape* lidS = new TGeoCompositeShape(lidComp.Data());
720 lidS->SetName("FMD1_lid");
721 TGeoVolume* lidV = new TGeoVolume("FMD1_lid", lidS, fC);
722 lidV->SetTransparency(63);
725 Double_t lidZ = (lidZStart -
726 (3.3 - r->GetModuleDepth() - r->GetModuleSpacing() / 2));
727 AliFMDDebug(1, ("FMD1 lid offset in Z=%f", lidZ));
729 for (Int_t i = 0; i < 2; i++) {
730 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
731 Double_t phi = 360. / 2 * i;
732 TGeoRotation* rot = new TGeoRotation(Form("FMD1_lid_rot%d",i));
734 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1_lid_mat%d", i),
736 mother->AddNode(lidV, i, matrix);
739 // Must add this after filling the assembly.
740 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
741 // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
742 TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
744 TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
746 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
747 fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
748 top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
749 top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
752 // Survey points on V0A (screw holes for the FMD)
753 const Double_t icb[] = { +12.700, -21.997, 324.670 };
754 const Double_t ict[] = { +12.700, +21.997, 324.670 };
755 const Double_t ocb[] = { -12.700, -21.997, 324.670 };
756 const Double_t oct[] = { -12.700, +21.997, 324.670 };
758 TGeoTube* surveyShape = new TGeoTube("FMD1_survey_marker",
761 TGeoMatrix* outMat = matrix;
763 if (gGeoManager->cd("/ALIC_1/F1MT_1"))
764 outMat = gGeoManager->GetCurrentMatrix();
766 AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
769 Double_t loct[3], locb[3];
770 outMat->MasterToLocal(oct, loct);
771 outMat->MasterToLocal(ocb, locb);
772 TGeoVolume* vOct = new TGeoVolume("V0L_OCT", surveyShape, fPlastic);
773 TGeoVolume* vOcb = new TGeoVolume("V0L_OCB", surveyShape, fPlastic);
775 fmd1TopVolume->AddNode(vOct, 1, new TGeoTranslation(loct[0],loct[1],loct[2]));
776 fmd1TopVolume->AddNode(vOcb, 1, new TGeoTranslation(locb[0],locb[1],locb[2]));
779 TGeoMatrix* inMat = matrix;
781 if (gGeoManager->cd("/ALIC_1/F1MT_1"))
782 inMat = gGeoManager->GetCurrentMatrix();
784 AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
787 Double_t lict[3], licb[3];
788 inMat->MasterToLocal(ict, lict);
789 inMat->MasterToLocal(icb, licb);
790 TGeoVolume* vIct = new TGeoVolume("V0L_ICT", surveyShape, fPlastic);
791 TGeoVolume* vIcb = new TGeoVolume("V0L_ICB", surveyShape, fPlastic);
793 fmd1BotVolume->AddNode(vIct, 1, new TGeoTranslation(lict[0],lict[1],lict[2]));
794 fmd1BotVolume->AddNode(vIcb, 1, new TGeoTranslation(licb[0],licb[1],licb[2]));
799 //____________________________________________________________________
801 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2,
802 TGeoVolume* innerTop,
803 TGeoVolume* innerBot,
804 TGeoVolume* outerTop,
805 TGeoVolume* outerBot)
807 // Setup the FMD2 geometry. The FMD2 has no
808 // special support as it is at the momement.
810 // See also AliFMDGeometryBuilder::DetectorGeometry
812 if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
813 AliFMDRing* ring = fmd2->GetOuter();
814 Double_t z = fmd2->GetOuterZ();
815 Double_t framelr = 32.01; // fmd2->GetOuterHoneyHighR()+0.5;
816 Double_t framehr = 33.611; // fmd2->GetOuterHoneyHighR()+1.8;
817 Double_t framel = 14.8; // framehz - framelz;
818 // Double_t backth = 0.3;
819 Double_t backth = 0.03;
820 Double_t framelz = -(2.38
821 - ring->GetModuleDepth()
822 - ring->GetModuleSpacing() / 2);
823 // Double_t framelz = -0.8;
824 // Double_t framehz = framelz + backth + framel;
825 Double_t coverlr = 4.3; // fmd2->GetInner()->GetLowR()+1;
826 Double_t coverhr = framehr; // - 1;
828 TString fmd2TopName = TString::Format(fgkFMDName, fmd2->GetId(), 'T');
829 TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(fmd2TopName);
830 TString fmd2BotName = TString::Format(fgkFMDName, fmd2->GetId(), 'B');
831 TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(fmd2BotName);
832 fmd2TopVolume->SetTitle("FMD2 top half");
833 fmd2BotVolume->SetTitle("FMD2 bottom half");
835 DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z,
836 innerTop, innerBot, outerTop, outerBot);
838 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("FMD2_support");
839 TGeoShape* cylinderShape = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
840 TGeoVolume* cylinderVolume = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
842 TGeoShape* coverShape = new TGeoTubeSeg(coverlr,coverhr,backth/2,0,180);
843 TGeoVolume* coverVolume = new TGeoVolume(Form(fgkTopName, fmd2->GetId()),
845 cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
846 cylinderShape->SetTitle("FMD2 cylinder");
847 cylinderVolume->SetTitle("FMD2 cylinder");
848 cylinderVolume->SetTransparency(63);
849 coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
850 coverShape->SetTitle("FMD2 cover");
851 coverVolume->SetTitle("FMD2 cover");
852 coverVolume->SetTransparency(63);
854 TGeoTranslation* trans = 0;
855 support->AddNode(coverVolume,1, new TGeoTranslation(0,0,backth/2));
856 support->AddNode(cylinderVolume, 1, new TGeoTranslation(0,0,backth+framel/2));
859 Double_t f1l = 15.6085;
862 Int_t nFiducialHoles = 4;
863 Double_t precHoles[][2] = { { 32.4948, 29.6663 },
864 { 33.9104, 31.0819 },
865 { 34.8177, 33.4035 },
866 { 35.5028, 32.6744 } };
867 Double_t precRadius = .25;
868 Double_t flangeA = TMath::Pi()/4;
870 new TGeoBBox("FMD2_flange_base", f1l/2, f1w/2, f1d/2);
871 new TGeoTube("FMD2_fiducial_hole", 0, precRadius, f1d/2+.1);
872 Double_t flangeX = framehr + f1l/2;
873 TVector2 flangeC(flangeX * TMath::Cos(flangeA),
874 flangeX * TMath::Sin(flangeA));
875 TString flangeComb("FMD2_flange_base-(");
876 new TGeoBBox("FMD2_flange_slit", 7./2, 1.5/2, f1d/2+.1);
877 trans = new TGeoTranslation(-f1l/2+1+7./2, +.5+1.5/2, 0);
878 trans->SetName("FMD2_flange_slit_mat1");
879 trans->RegisterYourself();
880 trans = new TGeoTranslation(-f1l/2+1+7./2, -.5-1.5/2, 0);
881 trans->SetName("FMD2_flange_slit_mat2");
882 trans->RegisterYourself();
883 flangeComb.Append("FMD2_flange_slit:FMD2_flange_slit_mat1+"
884 "FMD2_flange_slit:FMD2_flange_slit_mat2+");
885 for (Int_t i = 0; i < nFiducialHoles; i++) {
886 TVector2 v(precHoles[i][0], precHoles[i][1]);
888 TVector2 r = v.Rotate(-flangeA);
889 TGeoTranslation* t1 = new TGeoTranslation(r.X(), r.Y(), 0);
890 TGeoTranslation* t2 = new TGeoTranslation(r.X(), -r.Y(), 0);
891 t1->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+0));
892 t2->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+1));
893 t1->RegisterYourself();
894 t2->RegisterYourself();
895 flangeComb.Append(Form("FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d+"
896 "FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d%c",
897 2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
899 // Final flange shape, and at to full shape
900 TGeoCompositeShape* flangeS = new TGeoCompositeShape(flangeComb.Data());
901 flangeS->SetName("FMD2_flange");
902 TGeoVolume* flangeV = new TGeoVolume("FMD2_flange", flangeS, fAl);
908 new TGeoBBox("FMD2_flange_spacer_base", f2l/2, f2w/2, f2d/2);
909 new TGeoTube("FMD2_flange_spacer_hole", 0, 2.5, f2w/2+.1);
910 TGeoRotation* holeRot = new TGeoRotation();
911 holeRot->RotateY(90);
912 holeRot->RotateZ(90);
913 TGeoCombiTrans* combo = 0;
914 combo = new TGeoCombiTrans(0, 0, f2d/2-.5-2.5, holeRot);
915 combo->SetName("FMD2_flange_spacer_hole_mat1");
916 combo->RegisterYourself();
917 combo = new TGeoCombiTrans(0, 0, -f2d/2+.5+2.5, holeRot);
918 combo->SetName("FMD2_flange_spacer_hole_mat2");
919 combo->RegisterYourself();
920 TString spacerComp("FMD2_flange_spacer_base-("
921 "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat1+"
922 "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat2)");
923 TGeoCompositeShape* spacerS = new TGeoCompositeShape(spacerComp.Data());
924 TGeoVolume* spacerV = new TGeoVolume("FMD2_flange_spacer",
927 Double_t extraL = framehr-framelr;
928 TGeoBBox* extraS = new TGeoBBox("FMD2_flange_extra",
929 extraL/2, f1w/2, f1d/2);
930 TGeoVolume* extraV = new TGeoVolume("FMD2_flange_extra", extraS,fAl);
931 TGeoVolumeAssembly* wingV = new TGeoVolumeAssembly("FMD2_wing");
932 TGeoVolume* tension = TensionBox();
933 TGeoTube* wireS = new TGeoTube(0, .05, (framehr-coverlr)/2);
934 TGeoVolume* wireV = new TGeoVolume("FMD2_tension_wire",
936 wingV->AddNode(flangeV, 1, new TGeoTranslation(f1l/2, 0, f1d/2));
937 wingV->AddNode(flangeV, 2, new TGeoTranslation(f1l/2, 0, -f2d-f1d/2));
938 wingV->AddNode(extraV, 1, new TGeoCombiTrans(-extraL/2, 0, f1d/2, 0));
939 wingV->AddNode(spacerV, 1, new TGeoTranslation(1+f2l/2,-f2w/2+f1w/2,
941 wingV->AddNode(spacerV, 2, new TGeoTranslation(1+f2l/2,+f2w/2-f1w/2,
943 TGeoRotation* tensionR = new TGeoRotation;
944 tensionR->RotateY(90);
945 wingV->AddNode(tension, 1, new TGeoCombiTrans(4, 0, f1d+1.2, tensionR));
946 TGeoRotation* wireR = new TGeoRotation;
948 wingV->AddNode(wireV, 1, new TGeoCombiTrans(-(framehr-coverlr)/2, 0, f1d+1,
951 TGeoCombiTrans* extraM1 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
952 extraM1->RotateZ(45);
953 extraM1->RegisterYourself();
954 extraM1->SetName("FMD2_back_cover_slit1");
955 TGeoCombiTrans* extraM2 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
956 extraM2->RotateZ(135);
957 extraM2->RegisterYourself();
958 extraM2->SetName("FMD2_back_cover_slit2");
959 TString coverComp(Form(fgkTopName, fmd2->GetId()));
960 coverComp.Append("-(FMD2_flange_extra:FMD2_back_cover_slit1"
961 "+FMD2_flange_extra:FMD2_back_cover_slit2)");
962 TGeoCompositeShape* cover2Shape = new TGeoCompositeShape(coverComp.Data());
963 cover2Shape->SetName("FMD2_back_cover");
964 TGeoVolume* cover2Volume = new TGeoVolume("FMD2_back_cover", cover2Shape,fC);
965 support->AddNode(cover2Volume,2,
966 new TGeoTranslation(0,0,backth+framel+backth/2));
968 TGeoCombiTrans* trans1 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
969 TGeoCombiTrans* trans2 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
971 trans2->RotateZ(135);
972 support->AddNode(wingV, 1, trans1);
973 support->AddNode(wingV, 2, trans2);
974 AliFMDDebug(1, ("FMD2 support offset is %f", framelz));
976 for (Int_t i = 0; i < 2; i++) {
977 TGeoVolume* mother = (i < 1 ? fmd2TopVolume : fmd2BotVolume);
979 Double_t phi = 360. / 2 * i;
980 TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i));
982 TGeoMatrix* matrix = new TGeoCombiTrans(0, 0, framelz, rot);
983 mother->AddNode(support, i, matrix);
986 // Must be done after filling the assemblies
987 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
988 TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
989 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
990 fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
991 top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
992 top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
998 //____________________________________________________________________
1000 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3,
1001 TGeoVolume* innerTop,
1002 TGeoVolume* innerBot,
1003 TGeoVolume* outerTop,
1004 TGeoVolume* outerBot)
1006 // Setup the FMD3 geometry. The FMD2 has a rather elaborate support
1007 // structure, as the support will also support the vacuum
1010 // See also AliFMDGeometryBuilder::DetectorGeometry
1012 if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
1014 //__________________________________________________________________
1015 // Basic detector set-up.
1016 TString fmd3TopName = TString::Format(fgkFMDName, fmd3->GetId(), 'T');
1017 TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(fmd3TopName);
1018 TString fmd3BotName = TString::Format(fgkFMDName, fmd3->GetId(), 'B');
1019 TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(fmd3BotName);
1020 fmd3TopVolume->SetTitle("FMD3 top half");
1021 fmd3BotVolume->SetTitle("FMD3 bottom half");
1022 DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, fmd3->GetInnerZ(),
1023 innerTop, innerBot, outerTop, outerBot);
1025 //__________________________________________________________________
1026 // Mother for all support material
1027 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
1028 support->SetTitle("FMD3 support");
1030 //__________________________________________________________________
1032 const TObjArray& radii = fmd3->ConeRadii();
1033 Int_t nRadii = radii.GetEntriesFast();
1034 TGeoPcon* coneBase = new TGeoPcon("FMD3_cone_base", 0., 180., nRadii);
1037 for (Int_t i = 0; i < nRadii; i++) {
1038 TVector3* v = static_cast<TVector3*>(radii.At(i));
1039 coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
1041 else if (i == 4) r4 = v;
1043 TString coneComb("(FMD3_cone_base");
1045 //__________________________________________________________________
1047 double flangeDepth = fmd3->GetFlangeDepth() / 2;
1048 double flangeLength = fmd3->GetFlangeLength() / 2;
1049 double flangeWidth = fmd3->GetFlangeWidth() / 2;
1050 new TGeoBBox("FMD3_flange_base", flangeLength, flangeWidth, flangeDepth);
1053 const TObjArray& fiducialHoles = fmd3->FiducialHoles();
1054 double fiducialRadius = fmd3->GetFiducialRadius();
1056 TGeoTube* fiducialShape =
1058 new TGeoTube("FMD3_fiducial_hole", 0, fiducialRadius, flangeDepth+.1);
1059 Int_t nFiducialHoles = fiducialHoles.GetEntriesFast();
1060 double flangeAngle = TMath::Pi() / 4;
1061 double flangeX = r5->Y()+flangeLength;
1062 TVector2 flangeC(flangeX * TMath::Cos(flangeAngle),
1063 flangeX * TMath::Sin(flangeAngle));
1064 TString flangeComb("FMD3_flange_base-(");
1065 #if 0// For debugging geometry
1066 TGeoVolume* fiducialVolume = new TGeoVolume("FMD3_fiducial", fiducialShape);
1067 fiducialVolume->SetLineColor(kGreen);
1069 for (Int_t i = 0; i < nFiducialHoles; i++) {
1070 TVector2& v = *(static_cast<TVector2*>(fiducialHoles.At(i)));
1072 TVector2 r = v.Rotate(-flangeAngle);
1073 TGeoTranslation* t1 = new TGeoTranslation(r.X(), r.Y(), 0);
1074 TGeoTranslation* t2 = new TGeoTranslation(r.X(), -r.Y(), 0);
1075 t1->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+0));
1076 t2->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+1));
1077 t1->RegisterYourself();
1078 t2->RegisterYourself();
1079 flangeComb.Append(Form("FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d+"
1080 "FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d%c",
1081 2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
1082 #if 0 // For debugging geometry
1083 support->AddNode(fiducialVolume, 2*i+0, t1);
1084 support->AddNode(fiducialVolume, 2*i+1, t2);
1088 // Final flange shape, and at to full shape
1089 TGeoCompositeShape* flangeShape = new TGeoCompositeShape(flangeComb.Data());
1090 flangeShape->SetName("FMD3_flange");
1091 for (Int_t i = 0; i < 2; i++) {
1092 TGeoRotation* rot = new TGeoRotation();
1093 rot->RotateZ((i+.5)*90);
1094 TVector2 v(flangeX, 0);
1095 TVector2 w = v.Rotate((i+.5) * 2 * flangeAngle);
1096 TGeoCombiTrans* trans = new TGeoCombiTrans(w.X(),w.Y(),
1097 r4->X()+flangeDepth, rot);
1098 trans->SetName(Form("FMD3_flange_matrix%d", i));
1099 trans->RegisterYourself();
1100 coneComb.Append(Form("+FMD3_flange:FMD3_flange_matrix%d", i));
1102 coneComb.Append(")-(");
1104 //__________________________________________________________________
1106 Double_t holeL = fmd3->GetHoleLength()/2;
1107 Double_t holeD = fmd3->GetHoleDepth()/2;
1108 Double_t holeLW = fmd3->GetHoleLowWidth()/2;
1109 Double_t holeHW = fmd3->GetHoleHighWidth()/2;
1110 Double_t holeA = fmd3->GetConeOuterAngle();
1111 Double_t holeA2 = TMath::Pi() - fmd3->GetConeOuterAngle();
1112 Double_t holeO = fmd3->GetHoleOffset();
1113 Double_t holeZ = (holeO
1114 + holeL * TMath::Cos(holeA)
1115 - holeD * TMath::Sin(holeA2));
1116 Double_t holeX = (fmd3->ConeR(-holeZ + fmd3->GetInnerZ() + fmd3->GetNoseZ())
1117 - holeD * TMath::Sin(holeA2));
1118 new TGeoTrd1("FMD3_cone_hole", holeLW, holeHW, holeD, holeL);
1119 TGeoTrd1* plateShape = new TGeoTrd1("FMD3_cooling_plate",
1120 holeLW, holeHW, .033, holeL);
1121 TGeoRotation* holeRot = new TGeoRotation();
1122 holeRot->SetName("FMD3_cone_hole_rotation");
1123 holeRot->RotateZ(90);
1124 holeRot->RotateY(holeA*180/TMath::Pi());
1125 TGeoCombiTrans* holeBaseTrans = new TGeoCombiTrans(holeX, 0, holeZ, holeRot);
1126 holeBaseTrans->SetName("FMD3_cone_hole_base_matrix");
1127 // TGeoRotation* plateRot = new TGeoRotation();
1128 // plateRot->SetName("FMD3_cone_plate_rotation");
1129 // plateRot->RotateZ(90);
1130 // plateRot->RotateY(plateA*180/TMath::Pi());
1131 // TGeoCombiTrans* plateBaseTrans = new
1132 // TGeoCombiTrans(plateX,0,plateZ,plateRot);
1133 TGeoVolume* plateVolume = new TGeoVolume("FMD3_cooling_plate",
1135 plateShape->SetTitle("FMD3 cooling plate");
1136 plateVolume->SetTitle("FMD3 cooling plate");
1137 for (Int_t i = 0; i < 4; i++) {
1138 Double_t ang = 360. / 8 * (i + .5);
1139 TGeoCombiTrans* trans = new TGeoCombiTrans(*holeBaseTrans);
1140 trans->RotateZ(ang);
1141 trans->SetName(Form("FMD3_cone_hole_matrix%d", i));
1142 trans->RegisterYourself();
1143 trans = new TGeoCombiTrans(*holeBaseTrans);
1144 trans->RotateZ(ang);
1145 trans->SetName(Form("FMD3_cooling_plate_matrix%d", i));
1146 coneComb.Append(Form("FMD3_cone_hole:FMD3_cone_hole_matrix%d+", i));
1147 support->AddNode(plateVolume, i, trans);
1150 //__________________________________________________________________
1152 Double_t boltRadius = fmd3->GetBoltRadius();
1153 Double_t boltLength = fmd3->GetBoltLength() / 2;
1154 Double_t boltZ1 = fmd3->GetInnerZ()+fmd3->GetNoseZ()-10;
1155 Double_t boltZ2 = fmd3->GetInnerZ()+fmd3->GetNoseZ()-20;
1156 Double_t boltXE = 2*boltLength*TMath::Cos(fmd3->GetConeOuterAngle());
1157 Double_t boltX1 = (fmd3->ConeR(boltZ1) - boltXE);
1158 Double_t boltX2 = (fmd3->ConeR(boltZ2) - boltXE);
1160 new TGeoTube("FMD3_bolt_hole", 0, boltRadius, boltLength+.2);
1161 TGeoTube* boltShape = new TGeoTube("FMD3_bolt", 0, boltRadius, boltLength);
1162 TGeoRotation* boltRot = new TGeoRotation();
1163 boltRot->RotateY(-fmd3->GetConeOuterAngle()*180/TMath::Pi());
1164 TGeoCombiTrans* boltTrans1 = new TGeoCombiTrans(boltX1, 0, 10, boltRot);
1165 TGeoCombiTrans* boltTrans2 = new TGeoCombiTrans(boltX2, 0, 20, boltRot);
1166 TGeoCombiTrans* boltTrans3 = new TGeoCombiTrans(*boltTrans1);
1167 TGeoCombiTrans* boltTrans4 = new TGeoCombiTrans(*boltTrans2);
1168 boltTrans3->RotateZ(180);
1169 boltTrans4->RotateZ(180);
1170 boltTrans1->SetName("FMD3_bolt_matrix1");
1171 boltTrans2->SetName("FMD3_bolt_matrix2");
1172 boltTrans3->SetName("FMD3_bolt_matrix3");
1173 boltTrans4->SetName("FMD3_bolt_matrix4");
1174 boltTrans1->RegisterYourself();
1175 boltTrans2->RegisterYourself();
1176 boltTrans3->RegisterYourself();
1177 boltTrans4->RegisterYourself();
1178 coneComb.Append("FMD3_bolt_hole:FMD3_bolt_matrix1"
1179 "+FMD3_bolt_hole:FMD3_bolt_matrix2"
1180 "+FMD3_bolt_hole:FMD3_bolt_matrix3"
1181 "+FMD3_bolt_hole:FMD3_bolt_matrix4");
1182 TGeoVolume* boltVolume = new TGeoVolume("FMD3_bolt", boltShape, fSteel);
1183 support->AddNode(boltVolume, 1, boltTrans1);
1184 support->AddNode(boltVolume, 2, boltTrans2);
1185 boltShape->SetTitle("FMD3 steering bolt");
1186 boltVolume->SetTitle("FMD3 steering bolt");
1188 //__________________________________________________________________
1189 // Cut-outs for tension wheel sheeve
1190 new TGeoBBox("FMD3_sheeve_hole", .55, .75, 1.16);
1191 Double_t sheeveHoleZ = fmd3->GetInnerZ() + fmd3->GetNoseZ() - .75;
1192 Double_t sheeveHoleR = fmd3->ConeR(sheeveHoleZ) - .55 + .2572222;
1193 TGeoCombiTrans* sheeveMat1 = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1194 TGeoCombiTrans* sheeveMat2 = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1195 sheeveMat1->RotateZ(45);
1196 sheeveMat2->RotateZ(135);
1197 sheeveMat1->SetName("FMD3_sheeve_hole_matrix1");
1198 sheeveMat2->SetName("FMD3_sheeve_hole_matrix2");
1199 sheeveMat1->RegisterYourself();
1200 sheeveMat2->RegisterYourself();
1201 coneComb.Append("+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix1"
1202 "+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix2)");
1204 //__________________________________________________________________
1206 Double_t sheeveL = 1.15;
1207 TGeoBBox* sheeveSideS = new TGeoBBox("FMD3_sheeve_side",
1209 TGeoBBox* sheeveBackS = new TGeoBBox("FMD3_sheeve_back",
1211 TGeoBBox* sheeveWingS = new TGeoBBox("FMD3_sheeve_wing",
1213 TGeoPcon* sheeveWheelS = new TGeoPcon("FMD3_sheeve_wheel", 0, 360, 9);
1214 Double_t sheeveInnerR = 0; // .2;
1215 Double_t sheeveR = .875;
1216 Double_t sheeveWheelZ = .95;
1217 sheeveWheelS->DefineSection(0, -.25, sheeveInnerR, 1);
1218 sheeveWheelS->DefineSection(1, -.125, sheeveInnerR, 1);
1219 sheeveWheelS->DefineSection(2, -.125, sheeveInnerR, sheeveWheelZ);
1220 sheeveWheelS->DefineSection(3, -.0625, sheeveInnerR, sheeveR+.02);
1221 sheeveWheelS->DefineSection(4, 0.000, sheeveInnerR, sheeveR);
1222 sheeveWheelS->DefineSection(5, +.0625, sheeveInnerR, sheeveR+.02);
1223 sheeveWheelS->DefineSection(6, +.125, sheeveInnerR, sheeveWheelZ);
1224 sheeveWheelS->DefineSection(7, +.125, sheeveInnerR, 1);
1225 sheeveWheelS->DefineSection(8, +.25, sheeveInnerR, 1);
1226 TGeoVolume* sheeveSideV = new TGeoVolume("FMD3_sheeve_side",
1227 sheeveSideS, fPlastic);
1228 TGeoVolume* sheeveBackV = new TGeoVolume("FMD3_sheeve_back",
1229 sheeveBackS, fPlastic);
1230 TGeoVolume* sheeveWingV = new TGeoVolume("FMD3_sheeve_wing",
1231 sheeveWingS, fPlastic);
1232 TGeoVolume* sheeveWheelV= new TGeoVolume("FMD3_sheeve_wheel",
1233 sheeveWheelS, fPlastic);
1234 TGeoVolumeAssembly* sheeveBox = new TGeoVolumeAssembly("FMD3_sheeve_box");
1235 sheeveBox->AddNode(sheeveSideV, 1, new TGeoTranslation(0, -.5, 0));
1236 sheeveBox->AddNode(sheeveSideV, 2, new TGeoTranslation(0, +.5, 0));
1237 sheeveBox->AddNode(sheeveBackV, 1, new TGeoTranslation(0, 0, 2.0+.15-1.15));
1238 sheeveBox->AddNode(sheeveWingV, 1, new TGeoTranslation(.55-.15, -.90, 0));
1239 sheeveBox->AddNode(sheeveWingV, 2, new TGeoTranslation(.55-.15, +.90, 0));
1240 TGeoRotation* sheeveWheelR = new TGeoRotation;
1241 sheeveWheelR->RotateX(90);
1242 TGeoCombiTrans* sheeveWheelM = new TGeoCombiTrans(0, 0, sheeveWheelZ-sheeveL,
1244 sheeveBox->AddNode(sheeveWheelV, 1, sheeveWheelM);
1245 support->AddNode(sheeveBox, 1, sheeveMat1);
1246 support->AddNode(sheeveBox, 2, sheeveMat2);
1250 //__________________________________________________________________
1252 TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneComb.Data());
1253 coneShape->SetName("FMD3_cone");
1254 coneShape->SetTitle("FMD3 cone");
1255 TGeoVolume* coneVolume = new TGeoVolume("FMD3_Cone", coneShape, fC);
1256 coneVolume->SetLineColor(kRed);
1257 support->AddNode(coneVolume, 0, new TGeoTranslation(0, 0, 0));
1259 //__________________________________________________________________
1261 TGeoVolume* tensionBox = TensionBox();
1262 Double_t tensionH = .6;
1263 Double_t tensionL = 4;
1264 Double_t tensionZ = 23.654;
1265 Double_t tensionR = fmd3->ConeR(fmd3->GetInnerZ() + fmd3->GetNoseZ()
1267 Double_t tensionAr = fmd3->GetConeOuterAngle();
1268 Double_t tensionA = tensionAr * 180 / TMath::Pi();
1269 TGeoRotation* tensionQ = new TGeoRotation;
1270 tensionQ->RotateY(tensionA);
1271 TGeoCombiTrans* tensionM1 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1272 TGeoCombiTrans* tensionM2 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1273 tensionM1->RotateZ(45);
1274 tensionM2->RotateZ(135);
1275 support->AddNode(tensionBox, 1, tensionM1);
1276 support->AddNode(tensionBox, 2, tensionM2);
1278 // Double_t tensionHR = 0.15;
1279 Double_t wireT = .1/2;
1280 Double_t wireZ1 = (tensionZ
1281 - tensionL * TMath::Cos(tensionAr)
1282 - tensionH * TMath::Sin(tensionAr));
1283 Double_t wireR1 = (tensionR
1284 - tensionL * TMath::Sin(tensionAr)
1285 + tensionH * TMath::Cos(tensionAr));
1286 AliFMDDebug(10, ("Wire Z1: %f=%f-%f*cos(%f)-%f*sin(%f)",
1287 wireZ1, tensionZ, tensionL, tensionAr, tensionH, tensionAr));
1288 AliFMDDebug(10, ("Wire R1: %f=%f-%f*sin(%f)-%f*cos(%f)",
1289 wireR1, tensionR, tensionL, tensionAr, tensionH, tensionAr));
1291 Double_t wireStartA = 42.3 * TMath::Pi() / 180;
1292 Double_t wireZ2 = (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1294 - wireT * TMath::Sin(wireStartA));
1295 /* (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1296 - wireT * TMath::Sin(wireStartA)
1298 AliFMDDebug(10, ("wireZ2=%f=%f*(1-%f)", wireZ2, sheeveWheelZ,
1299 TMath::Sin(wireStartA)));
1300 Double_t wireR2 = (sheeveHoleR +
1301 sheeveWheelZ * TMath::Cos(wireStartA) +
1302 wireT * TMath::Cos(wireStartA));
1303 Double_t wireDR = wireR1-wireR2;
1304 Double_t wireDZ = wireZ1-wireZ2;
1305 Double_t wireL = TMath::Sqrt(wireDR*wireDR+wireDZ*wireDZ)-.01;
1306 Double_t wireAngle = TMath::ATan2(wireDR,wireDZ);
1307 TGeoTube* wireShape = new TGeoTube("FMD3_wire", 0, wireT, wireL/2);
1308 TGeoVolume* wireVolume = new TGeoVolume("FMD3_wire", wireShape,fSteel);
1309 TGeoRotation* wireRot = new TGeoRotation();
1310 wireRot->RotateY(180/TMath::Pi()*wireAngle);
1311 Double_t wireR = wireR2 + wireDR / 2;
1312 Double_t wireZ = wireZ2 + wireDZ / 2;
1313 TGeoCombiTrans* wireM1 = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1314 TGeoCombiTrans* wireM2 = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1315 wireM1->RotateZ(45);
1316 wireM2->RotateZ(135);
1317 support->AddNode(wireVolume, 1, wireM1);
1318 support->AddNode(wireVolume, 2, wireM2);
1321 TGeoTorus* wireTS = new TGeoTorus(sheeveWheelZ+wireT, 0, wireT, 0,
1322 90-wireStartA*180/TMath::Pi());
1323 TGeoVolume* wireTV = new TGeoVolume("FMD3_bend_wire",wireTS,fSteel);
1324 TGeoRotation* wireTR = new TGeoRotation;
1325 wireTR->RotateY(90);
1326 wireTR->RotateZ(-90);
1327 Double_t wireTZ = sheeveWheelZ;
1328 TGeoCombiTrans* wireTM1 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1329 TGeoCombiTrans* wireTM2 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1330 wireTM1->RotateZ(45);
1331 wireTM2->RotateZ(135);
1332 support->AddNode(wireTV, 1, wireTM1);
1333 support->AddNode(wireTV, 2, wireTM2);
1335 Double_t colarR = 4.05;
1336 Double_t wireEL = sheeveHoleR - colarR;
1337 TGeoTube* wireES = new TGeoTube("FMD3_end_wire", 0, wireT, wireEL/2);
1338 TGeoVolume* wireEV = new TGeoVolume("FMD3_end_wire", wireES, fSteel);
1339 TGeoRotation* wireER = new TGeoRotation;
1340 wireER->RotateY(90);
1341 TGeoCombiTrans* wireEM1 = new TGeoCombiTrans(colarR+wireEL/2,0,
1343 TGeoCombiTrans* wireEM2 = new TGeoCombiTrans(colarR+wireEL/2,0,
1345 wireEM1->RotateZ(45);
1346 wireEM2->RotateZ(135);
1347 support->AddNode(wireEV, 1, wireEM1);
1348 support->AddNode(wireEV, 2, wireEM2);
1353 //__________________________________________________________________
1354 // Place support volumes in half-detector volumes
1355 Double_t z = fmd3->GetInnerZ();
1356 AliFMDDebug(1, ("FMD3 support at z=%f", -fmd3->GetNoseZ()));
1357 TGeoTranslation* t1 = new TGeoTranslation(0, 0, -fmd3->GetNoseZ());
1358 fmd3TopVolume->AddNode(support, 1, t1);
1359 TGeoCombiTrans* t2 = new TGeoCombiTrans(*t1);
1361 fmd3BotVolume->AddNode(support, 2, t2);
1363 TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
1365 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
1366 TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1367 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
1368 fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1369 top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1370 top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1376 //____________________________________________________________________
1378 AliFMDGeometryBuilder::Exec(Option_t*)
1380 // Setup up the FMD geometry.
1381 AliFMDDebug(1, ("\tGeometry options: %s",
1382 (fDetailed ? "divided into strips" : "one volume")));
1384 AliFatal("No TGeoManager defined");
1388 fSi = gGeoManager->GetMedium("FMD_Si$");
1389 fC = gGeoManager->GetMedium("FMD_Carbon$");
1390 fAl = gGeoManager->GetMedium("FMD_Aluminum$");
1391 fChip = gGeoManager->GetMedium("FMD_Si Chip$");
1392 fAir = gGeoManager->GetMedium("FMD_Air$");
1393 fPCB = gGeoManager->GetMedium("FMD_PCB$");
1394 fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1395 fCopper = gGeoManager->GetMedium("FMD_Copper$");
1396 fSteel = gGeoManager->GetMedium("FMD_Steel$");
1398 if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1399 AliError("Failed to get some or all tracking mediums");
1402 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1403 AliFMDRing* inner = fmd->GetInner();
1404 AliFMDRing* outer = fmd->GetOuter();
1405 RingGeometry(inner);
1406 RingGeometry(outer);
1407 TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1409 TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1411 TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1413 TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1416 FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1417 FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1418 FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1419 #ifndef USE_PRE_MOVE
1420 fmd->SetSectorOff(fSectorOff);
1421 fmd->SetModuleOff(fModuleOff);
1422 fmd->SetRingOff(fRingOff);
1423 fmd->SetDetectorOff(fDetectorOff);
1424 fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1426 // fmd->ExtractGeomInfo();
1431 //____________________________________________________________________