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 <TGeoCompositeShape.h>
46 #include <TVector2.h> // ROOT_TVector2
47 #include <TVector3.h> // ROOT_TVector3
48 //#include <TGeoMaterial.h> // ROOT_TGeoMaterial
49 //#include <TGeoMedium.h> // ROOT_TGeoMedium
50 //#include <TGeoPcon.h> // ROOT_TGeoPcon
51 //#include <TGeoPolygon.h> // ROOT_TGeoPolygon
53 #include "AliFMDGeometryBuilder.h" // ALIFMDGEOSIMULATOR_H
54 #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
55 #include "AliFMDDetector.h" // ALIFMDDETECTOR_H
56 #include "AliFMDRing.h" // ALIFMDRING_H
57 #include "AliFMD1.h" // ALIFMD1_H
58 #include "AliFMD2.h" // ALIFMD2_H
59 #include "AliFMD3.h" // ALIFMD3_H
60 // #include "AliFMD.h" // ALIFMD_H
61 #include "AliFMDDebug.h" // ALILOG_H
64 //====================================================================
65 ClassImp(AliFMDGeometryBuilder)
67 ; // This is here to keep Emacs for indenting the next line
70 //____________________________________________________________________
71 const Char_t* AliFMDGeometryBuilder::fgkActiveName = "F%cAC";
72 const Char_t* AliFMDGeometryBuilder::fgkSectorName = "F%cSC";
73 const Char_t* AliFMDGeometryBuilder::fgkStripName = "F%cST";
74 const Char_t* AliFMDGeometryBuilder::fgkSensorName = "F%cSE";
75 const Char_t* AliFMDGeometryBuilder::fgkPCBName = "F%cPB";
76 const Char_t* AliFMDGeometryBuilder::fgkCuName = "F%cCU";
77 const Char_t* AliFMDGeometryBuilder::fgkChipName = "F%cCH";
78 const Char_t* AliFMDGeometryBuilder::fgkLongLegName = "F%cLL";
79 const Char_t* AliFMDGeometryBuilder::fgkShortLegName = "F%cSL";
80 const Char_t* AliFMDGeometryBuilder::fgkFrontVName = "F%cFH";
81 const Char_t* AliFMDGeometryBuilder::fgkBackVName = "F%cBH";
82 const Char_t* AliFMDGeometryBuilder::fgkRingTopName = "F%cTV";
83 const Char_t* AliFMDGeometryBuilder::fgkRingBotName = "F%cBV";
84 const Char_t* AliFMDGeometryBuilder::fgkHCName = "F%dH%c";
85 const Char_t* AliFMDGeometryBuilder::fgkIHCName = "F%dI%c";
86 const Char_t* AliFMDGeometryBuilder::fgkNoseName = "F3SN";
87 const Char_t* AliFMDGeometryBuilder::fgkBackName = "F%dSB";
88 const Char_t* AliFMDGeometryBuilder::fgkTopName = "F%dSU";
89 const Char_t* AliFMDGeometryBuilder::fgkBeamName = "F%dSL";
90 const Char_t* AliFMDGeometryBuilder::fgkFlangeName = "F%dSF";
91 const Char_t* AliFMDGeometryBuilder::fgkFMDDCuName = "F%cDC";
92 const Char_t* AliFMDGeometryBuilder::fgkFMDDPCBName = "F%cDP";
93 const Char_t* AliFMDGeometryBuilder::fgkFMDDChipName = "F%cDI";
94 const Char_t* AliFMDGeometryBuilder::fgkFMDDName = "F%cDD";
95 const Char_t* AliFMDGeometryBuilder::fgkFMDName = "F%dM%c";
97 //____________________________________________________________________
98 AliFMDGeometryBuilder::AliFMDGeometryBuilder()
99 : TTask("FMD", "Geomtry builder"),
117 // Default constructor
121 //____________________________________________________________________
122 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed)
123 : TTask("FMD", "Geometry builder"),
141 // Normal constructor
145 // fmd Pointer to AliFMD object
146 // detailed Whether to make a detailed simulation or not
152 //____________________________________________________________________
154 AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r)
156 // Setup the geometry of a ring. The defined TGeoVolume is
157 // returned, and should be used when setting up the rest of the
163 // r Pointer to ring geometry object
166 // pointer to ring volume
169 AliError("Didn't get a ring object");
172 Char_t id = r->GetId();
173 const Char_t* lName = (id == 'i' || id == 'I' ? "inner" : "outer");
174 Double_t siThick = r->GetSiThickness();
175 const Int_t knv = r->GetNVerticies();
176 TVector2* a = r->GetVertex(5);
177 TVector2* b = r->GetVertex(3);
178 TVector2* c = r->GetVertex(4);
179 Double_t theta = r->GetTheta();
180 Double_t off = (TMath::Tan(TMath::Pi() * theta / 180)
181 * r->GetBondingWidth());
182 Double_t rmax = b->Mod();
183 Double_t rmin = r->GetLowR();
184 Double_t pcbThick = r->GetPrintboardThickness();
185 Double_t cuThick = r->GetCopperThickness();
186 Double_t chipThick= r->GetChipThickness();
187 Double_t modSpace = r->GetModuleSpacing();
188 Double_t legr = r->GetLegRadius();
189 Double_t legl = r->GetLegLength();
190 Double_t legoff = r->GetLegOffset();
191 Int_t ns = r->GetNStrips();
192 Double_t stripoff = a->Mod();
193 Double_t dstrip = (rmax - stripoff) / ns;
194 Double_t space = r->GetSpacing();
197 for (Int_t i = 0; i < knv; i++) {
199 TVector2* vv = r->GetVertex(knv - 1 - i);
201 AliError(Form("Failed to get vertex # %d", knv - 1 - i));
208 // Shape of actual sensor
209 TGeoXtru* sensorShape = new TGeoXtru(2);
210 sensorShape->DefinePolygon(knv, xs.fArray, ys.fArray);
211 sensorShape->DefineSection(0, - siThick/2);
212 sensorShape->DefineSection(1, siThick/2);
213 sensorShape->SetName(Form(fgkSensorName, id));
214 sensorShape->SetTitle(Form("FMD %s Sensor", lName));
215 TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id),
217 sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
218 sensorVolume->VisibleDaughters(kFALSE);
219 Int_t sid = sensorVolume->GetNumber();
229 // Virtual volume shape to divide - This volume is only defined if
230 // the geometry is set to be detailed.
231 TGeoTubeSeg* activeShape = new TGeoTubeSeg(rmin, rmax, siThick/2,
233 activeShape->SetName(Form(fgkActiveName, id));
234 activeShape->SetTitle(Form("FMD %s active area", lName));
235 TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
237 activeVolume->SetTitle(Form("FMD %s active area", lName));
238 TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id),
239 2, 2, -theta,0,0,"N");
240 sectorVolume->SetTitle(Form("FMD %s sector", lName));
241 TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id),
242 1, ns, stripoff, dstrip,
244 stripVolume->SetTitle(Form("FMD %s strip", lName));
245 sid = stripVolume->GetNumber();
246 sensorVolume->AddNodeOverlap(activeVolume, 0);
250 case 'i': case 'I': fActiveId[0] = sid; break;
251 case 'o': case 'O': fActiveId[1] = sid; break;
254 // Shape of Printed circuit Board
255 for (Int_t i = 0; i < knv / 2; i++) ys[i] -= off;
256 for (Int_t i = knv / 2; i < knv; i++) ys[i] += off;
257 TGeoXtru* pcbShape = new TGeoXtru(2);
258 pcbShape->DefinePolygon(knv, xs.fArray, ys.fArray);
259 pcbShape->DefineSection(0, - pcbThick/2);
260 pcbShape->DefineSection(1, pcbThick/2);
261 pcbShape->SetName(Form(fgkPCBName, id));
262 pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
263 TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id),
265 pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
268 TGeoXtru* cuShape = new TGeoXtru(2);
269 cuShape->DefinePolygon(6, xs.fArray, ys.fArray);
270 cuShape->DefineSection(0, - cuThick/2);
271 cuShape->DefineSection(1, cuThick/2);
272 cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
273 TGeoVolume* cuVolume = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper);
274 cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
277 TGeoXtru* chipShape = new TGeoXtru(2);
278 chipShape->DefinePolygon(6, xs.fArray, ys.fArray);
279 chipShape->DefineSection(0, - chipThick/2);
280 chipShape->DefineSection(1, chipThick/2);
281 chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
282 TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id),
284 chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
287 TGeoTube* shortLegShape = new TGeoTube(0, legr, legl / 2);
288 shortLegShape->SetName(Form(fgkShortLegName, id));
289 shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
290 TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id),
291 shortLegShape, fCopper);
292 shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
294 TGeoTube* longLegShape = new TGeoTube(0, legr, (legl + modSpace) / 2);
295 longLegShape->SetName(Form(fgkLongLegName, id));
296 longLegShape->SetTitle(Form("FMD %s long support foot", lName));
297 TGeoVolume* longLegVolume = new TGeoVolume(Form(fgkLongLegName, id),
298 longLegShape, fCopper);
299 longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
302 // Back container volume
303 TGeoVolume* backVolume = new TGeoVolumeAssembly(Form(fgkBackVName, id));
304 backVolume->SetTitle(Form("FMD %s back module", lName));
307 Double_t z = siThick / 2;
308 backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z));
309 z += siThick / 2 + space + pcbThick / 2;
310 backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
311 z += (pcbThick + cuThick) / 2;
312 backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
313 z += (cuThick + chipThick) / 2;
314 backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
315 x = a->X() + legoff + legr;
317 z += pcbThick / 2 + legl / 2;
318 backVolume->AddNode(shortLegVolume, 0, new TGeoTranslation(x,y,z));
320 y = c->Y() - legoff - legr - off;
321 backVolume->AddNode(shortLegVolume, 1, new TGeoTranslation(x,y,z));
323 backVolume->AddNode(shortLegVolume, 2, new TGeoTranslation(x,y,z));
325 // Front container volume
326 TGeoVolume* frontVolume = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
327 frontVolume->SetTitle(Form("FMD %s front module", lName));
331 frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z));
332 z += siThick / 2 + space + pcbThick / 2;
333 frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
334 z += (pcbThick + cuThick) / 2;
335 frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
336 z += (cuThick + chipThick) / 2;
337 frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
338 x = a->X() + legoff + legr;
340 z += pcbThick / 2 + (legl + modSpace)/ 2;
341 frontVolume->AddNode(longLegVolume, 0, new TGeoTranslation(x,y,z));
343 y = c->Y() - legoff - legr - off;
344 frontVolume->AddNode(longLegVolume, 1, new TGeoTranslation(x,y,z));
346 frontVolume->AddNode(longLegVolume, 2, new TGeoTranslation(x,y,z));
350 Double_t ddlr = r->GetFMDDLowR();
351 Double_t ddhr = r->GetFMDDHighR();
352 Double_t ddpt = r->GetFMDDPrintboardThickness();
353 Double_t ddct = r->GetFMDDCopperThickness();
354 Double_t ddit = r->GetFMDDChipThickness();
355 Double_t ddt = ddpt + ddct + ddit;
357 TGeoShape* fmddPcbShape = new TGeoTubeSeg(ddlr, ddhr, ddpt/2,0,180);
358 TGeoShape* fmddCuShape = new TGeoTubeSeg(ddlr, ddhr, ddct/2,0,180);
359 TGeoShape* fmddChipShape = new TGeoTubeSeg(ddlr, ddhr, ddit/2,0,180);
360 fmddPcbShape->SetName(Form(fgkFMDDPCBName, id));
361 fmddCuShape->SetName(Form(fgkFMDDCuName, id));
362 fmddChipShape->SetName(Form(fgkFMDDChipName, id));
363 if (id == 'O' || id == 'o') {
364 TString pcbName(fmddPcbShape->GetName());
365 TString cuName(fmddCuShape->GetName());
366 TString chipName(fmddChipShape->GetName());
368 fmddPcbShape->SetName(Form("%s_inner", pcbName.Data()));
369 fmddCuShape->SetName(Form("%s_inner", cuName.Data()));
370 fmddChipShape->SetName(Form("%s_inner", chipName.Data()));
371 new TGeoBBox(Form("%s_clip", pcbName.Data()), ddlr+3, ddhr/2, ddpt);
372 new TGeoBBox(Form("%s_clip", cuName.Data()), ddlr+3, ddhr/2, ddpt);
373 new TGeoBBox(Form("%s_clip", chipName.Data()),ddlr+3, ddhr/2, ddpt);
374 TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
377 trans->RegisterYourself();
378 fmddPcbShape = new TGeoCompositeShape(pcbName.Data(),
379 Form("%s_inner*%s_clip:%s_trans",
383 fmddCuShape = new TGeoCompositeShape(cuName.Data(),
384 Form("%s_inner*%s_clip:%s_trans",
388 fmddChipShape = new TGeoCompositeShape(chipName.Data(),
389 Form("%s_inner*%s_clip:%s_trans",
394 fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
395 fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
396 fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
398 TGeoVolume* fmddPcbVolume = new TGeoVolume(Form(fgkFMDDPCBName, id),
400 TGeoVolume* fmddCuVolume = new TGeoVolume(Form(fgkFMDDCuName, id),
401 fmddCuShape, fCopper);
402 TGeoVolume* fmddChipVolume= new TGeoVolume(Form(fgkFMDDChipName, id),
403 fmddChipShape, fChip);
404 fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
405 fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
406 fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
408 // Half ring mother volumes.
409 TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
410 TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
411 TGeoVolume* halfRing = ringTopVolume;
412 ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
413 ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
415 // Adding modules to half-rings
416 Int_t nmod = r->GetNModules();
417 AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
418 for (Int_t i = 0; i < nmod; i++) {
419 if (i == nmod / 2) halfRing = ringBotVolume;
420 Bool_t front = (i % 2 == 0);
421 TGeoVolume* vol = (front ? frontVolume : backVolume);
422 // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
423 Double_t z1 = (i % 2) * modSpace;
424 Double_t th = (2 * i + 1) * theta;
425 TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0);
427 mat1->SetName(Form("FMD%c_module_%02d", id, i));
428 mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
429 halfRing->AddNode(vol, i, mat1);
431 Double_t z2 = z1 + siThick / 2 + space;
432 Double_t th = (2 * i + 1) * theta;
433 AliFMDDebug(20, ("Placing copy %d of %s and %s in %s at z=%f and %f, "
434 "and theta=%f", i, sensorVolume->GetName(),
435 vol->GetName(), halfRing->GetName(), z1, z2, th));
436 TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0);
438 halfRing->AddNode(sensorVolume, i, mat1);
439 TGeoMatrix* mat2 = new TGeoCombiTrans(0,0,z2,0);
441 halfRing->AddNode(vol, i, mat2);
446 Double_t zi = r->GetFullDepth() - ddt;
448 for (Int_t i = 0; i < n; i++) {
449 halfRing = (i == 0 ? ringTopVolume : ringBotVolume);
450 Double_t phi = 360. / n * i;
451 TGeoRotation* rot = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
453 rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
455 halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
456 z += (ddpt + ddct) / 2;
457 halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
458 z += (ddct + ddit) / 2;
459 halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
466 //____________________________________________________________________
468 AliFMDGeometryBuilder::HoneycombShape(Int_t id, Char_t ring,
469 double r1, double r2,
470 double w, double t, double c)
472 // Make a honey comb shape from passed parameters.
474 // id Detector identifier (1,2, or 3)
475 // ring Ring identifier ('I' or 'O')
479 // t Thickness of material
480 // c Clearing from horizontal.
482 // Pointer to newly allocated composite shape.
483 TString form = Form("FMD%d%c_%%c_%%c", id, ring);
484 double a1 = TMath::ATan2(c, r1) * 180 / TMath::Pi();
486 TString fn = Form(form.Data(),'F','1');
487 TString bn = Form(form.Data(),'B','1');
488 TString cn = Form(form.Data(),'C','O');
489 TString in = Form(form.Data(),'R','I');
490 TString on = Form(form.Data(),'R','O');
491 TString en = Form(form.Data(),'E','X');
493 double x = r1 * TMath::Cos(TMath::Pi()*a1/180);
494 new TGeoTubeSeg(fn.Data(),r1,r2,t/2,0,180);
495 new TGeoTubeSeg(bn.Data(),r1,r2,t/2,0,180);
496 new TGeoBBox(cn.Data(),(r2-r1)/2,t/2,w/2);
497 new TGeoTubeSeg(in.Data(),r1,r1+t,w/2,0,180);
498 new TGeoTubeSeg(on.Data(),r2-t,r2,w/2,0,180);
499 new TGeoBBox(en.Data(),r2+.005,c/2+.005,w/2+.005);
501 TString ftn = Form(form.Data(),'F','T');
502 TString btn = Form(form.Data(),'F','B');
503 TString ltn = Form(form.Data(),'C','L');
504 TString rtn = Form(form.Data(),'C','R');
505 TString etn = Form(form.Data(),'E','X');
506 (new TGeoTranslation(ftn.Data(),0,0,+w/2-t/2))->RegisterYourself();
507 (new TGeoTranslation(btn.Data(),0,0,-w/2+t/2))->RegisterYourself();
508 (new TGeoTranslation(ltn.Data(),-(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
509 (new TGeoTranslation(rtn.Data(),(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
510 (new TGeoTranslation(etn.Data(),0, c/2,0))->RegisterYourself();
512 TString comp(Form("(%s:%s+%s:%s+%s+%s+%s:%s+%s:%s)-%s:%s",
513 fn.Data(),ftn.Data(),
514 bn.Data(),btn.Data(),
516 cn.Data(),ltn.Data(),
517 cn.Data(),rtn.Data(),
518 en.Data(),etn.Data()));
519 TGeoCompositeShape* shape = new TGeoCompositeShape(comp.Data());
520 shape->SetName(Form(fgkHCName,id,ring));
521 shape->SetTitle(Form("FMD%d%c Honeycomb shape", id, ring));
526 //____________________________________________________________________
528 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d,
529 TGeoVolume* topMother,
530 TGeoVolume* botMother,
532 TGeoVolume* innerTop,
533 TGeoVolume* innerBot,
534 TGeoVolume* outerTop,
535 TGeoVolume* outerBot)
537 // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
538 // This includes putting the Honeycomb support plates and the rings
539 // into the mother volumes.
542 // d The detector geometry to use
543 // mother The mother volume of the detector
544 // zmother The midpoint in global coordinates of detector vol.
545 // inner Pointer to inner ring volume
546 // outer Pointer to outer ring volume
549 // Pointer to mother (detector volume)
552 // Loop over the defined rings
553 for (int i = 0; i < 2; i++) {
558 TGeoVolume* tvol = 0;
559 TGeoVolume* bvol = 0;
563 lowr = d->GetInnerHoneyLowR();
564 highr = d->GetInnerHoneyHighR();
571 lowr = d->GetOuterHoneyLowR();
572 highr = d->GetOuterHoneyHighR();
579 Char_t c = r->GetId();
580 Int_t id = d->GetId();
581 Double_t hcThick = r->GetHoneycombThickness();
582 Double_t alThick = r->GetAlThickness();
583 Double_t z = TMath::Abs(rz - zMother);
585 // Place ring in mother volume
586 // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
587 AliFMDDebug(1, ("Placing volumes %s and %s in %s and %s at z=%f",
588 tvol->GetName(), bvol->GetName(),
589 topMother->GetName(), botMother->GetName(), z));
590 topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
591 botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
594 TGeoShape* hcSha = HoneycombShape(id, c, lowr, highr, hcThick, alThick);
595 TGeoVolume* hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
596 hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
598 z += (r->GetSiThickness() +
600 r->GetPrintboardThickness() +
601 r->GetCopperThickness() +
602 r->GetChipThickness() +
603 r->GetModuleSpacing() +
605 r->GetHoneycombThickness() +
606 r->GetFMDDPrintboardThickness() -
609 AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f",
610 hcVol->GetName(), topMother->GetName(),
611 botMother->GetName(), z));
613 topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
616 TGeoMatrix* bhcMatrix = new TGeoCombiTrans(0,0,z,0);
617 bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
618 bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
619 bhcMatrix->RotateZ(180);
620 botMother->AddNode(hcVol, 1, bhcMatrix);
625 //____________________________________________________________________
627 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1,
628 TGeoVolume* innerTop,
629 TGeoVolume* innerBot)
631 // Setup the FMD1 geometry. The FMD1 only has one ring, and no
632 // special support as it is at the momement.
634 // See also AliFMDGeometryBuilder::DetectorGeometry
636 if (!fmd1 || !innerTop || !innerBot) return 0;
637 AliFMDRing* r = fmd1->GetInner();
638 Double_t z = fmd1->GetInnerZ();
640 Double_t backlr = fmd1->GetInnerHoneyHighR();
641 Double_t backhr = fmd1->GetInnerHoneyHighR()+5;
642 Double_t backth = 0.2;
643 Double_t toplr = r->GetLowR();
644 Double_t tophr = fmd1->GetInnerHoneyHighR()+disce;
645 Double_t wallbh = (r->GetFullDepth() + disce);
646 Double_t wallth = wallbh+0.1;
648 TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
649 fmd1->GetId(), 'T'));
650 fmd1TopVolume->SetTitle("FMD1 top half");
651 TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
652 fmd1->GetId(), 'B'));
653 fmd1BotVolume->SetTitle("FMD1 bottom half");
655 // Basic detector geometry
656 DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z,
657 innerTop, innerBot, 0, 0);
661 TGeoTubeSeg* backShape = new TGeoTubeSeg(backlr, backhr, backth / 2, 0, 180);
662 TGeoTubeSeg* wallbShape = new TGeoTubeSeg(backlr, backlr + backth,
664 TGeoTubeSeg* topShape = new TGeoTubeSeg(toplr, tophr, backth / 2, 0, 180);
665 TGeoTubeSeg* walltShape = new TGeoTubeSeg(tophr, tophr + backth,
667 TGeoVolume* backVolume = new TGeoVolume(Form(fgkBackName, fmd1->GetId()),
669 TGeoVolume* wallbVolume= new TGeoVolume(Form(fgkFlangeName, fmd1->GetId()),
671 TGeoVolume* topVolume = new TGeoVolume(Form(fgkTopName, fmd1->GetId()),
673 TGeoVolume* walltVolume= new TGeoVolume(Form(fgkBeamName, fmd1->GetId()),
675 backShape->SetName(Form(fgkBackName, fmd1->GetId()));
676 wallbShape->SetName(Form(fgkFlangeName, fmd1->GetId()));
677 topShape->SetName(Form(fgkTopName, fmd1->GetId()));
678 walltShape->SetName(Form(fgkBeamName, fmd1->GetId()));
679 backShape->SetTitle("FMD1 back saucer rim");
680 wallbShape->SetTitle("FMD1 back saucer wall");
681 topShape->SetTitle("FMD1 top lid");
682 walltShape->SetTitle("FMD1 top lid wall");
683 backVolume->SetFillColor(kGray);
684 topVolume->SetFillColor(kGray);
685 wallbVolume->SetFillColor(kGray);
686 walltVolume->SetFillColor(kGray);
687 backVolume->SetTitle("FMD1 back saucer rim");
688 wallbVolume->SetTitle("FMD1 back saucer wall");
689 topVolume->SetTitle("FMD1 top lid");
690 walltVolume->SetTitle("FMD1 top lid wall");
693 Double_t zb = TMath::Abs(fmd1->GetInnerZ() - z);
698 zi -= disce / 2 + backth / 2;
700 for (Int_t i = 0; i < 2; i++) {
701 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
702 Double_t phi = 360. / n * i;
703 TGeoRotation* rot = new TGeoRotation(Form("FMD1 top rotation %d",i));
705 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 top wall trans %d", i),
707 mother->AddNode(topVolume, i, matrix);
710 zi += wallth / 2 + backth / 2;
711 for (Int_t i = 0; i < 2; i++) {
712 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
713 Double_t phi = 360. / n * i;
714 TGeoRotation* rot = new TGeoRotation(Form("FMD1 outer wall rotation %d",
717 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 outer wall trans %d",
719 mother->AddNode(walltVolume, i, matrix);
722 zi += wallth / 2 + backth / 2; // + disce / 2;
723 for (Int_t i = 0; i < 2; i++) {
724 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
725 Double_t phi = 360. / n * i;
726 TGeoRotation* rot = new TGeoRotation(Form("FMD1 back rotation %d", i));
728 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 back trans %d", i),
730 mother->AddNode(backVolume, i, matrix);
733 zi -= wallbh / 2 + backth / 2; // + disce / 2;
734 for (Int_t i = 0; i < 2; i++) {
735 TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
736 Double_t phi = 360. / n * i;
737 TGeoRotation* rot = new TGeoRotation(Form("FMD1 inner wall rotation %d",
740 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 inner wall trans %d",
742 mother->AddNode(wallbVolume, i, matrix);
746 // Must add this after filling the assembly.
747 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
748 // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
749 TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
751 TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
752 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
753 fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
754 top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
755 top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
760 //____________________________________________________________________
762 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2,
763 TGeoVolume* innerTop,
764 TGeoVolume* innerBot,
765 TGeoVolume* outerTop,
766 TGeoVolume* outerBot)
768 // Setup the FMD2 geometry. The FMD2 has no
769 // special support as it is at the momement.
771 // See also AliFMDGeometryBuilder::DetectorGeometry
773 if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
774 AliFMDRing* r = fmd2->GetOuter();
775 Double_t z = fmd2->GetOuterZ();
776 Double_t framelr = fmd2->GetOuterHoneyHighR()+0.5;
777 Double_t framehr = fmd2->GetOuterHoneyHighR()+1.8;
778 Double_t framelz = -.5;
779 Double_t framehz = (fmd2->GetInnerZ()-z) + r->GetFullDepth() + .5;
780 Double_t framel = framehz - framelz;
781 Double_t coverlr = fmd2->GetInner()->GetLowR()+1;
782 Double_t backth = 0.05;
784 TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
785 fmd2->GetId(), 'T'));
786 TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
787 fmd2->GetId(), 'B'));
788 fmd2TopVolume->SetTitle("FMD2 top half");
789 fmd2BotVolume->SetTitle("FMD2 bottom half");
791 DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z,
792 innerTop, innerBot, outerTop, outerBot);
794 TGeoShape* cylinderShape = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
795 TGeoVolume* cylinderVolume = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
797 TGeoShape* coverShape = new TGeoTubeSeg(coverlr,framehr,backth/2,0,180);
798 TGeoVolume* coverVolume = new TGeoVolume(Form(fgkTopName, fmd2->GetId()),
800 cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
801 cylinderShape->SetTitle("FMD2 cylinder");
802 cylinderVolume->SetTitle("FMD2 cylinder");
803 cylinderVolume->SetTransparency(63);
804 coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
805 coverShape->SetTitle("FMD2 cover");
806 coverVolume->SetTitle("FMD2 cover");
807 coverVolume->SetTransparency(63);
809 for (Int_t i = 0; i < 2; i++) {
810 TGeoVolume* mother = (i == 0 ? fmd2TopVolume : fmd2BotVolume);
812 Double_t phi = 360. / 2 * i;
813 TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i));
815 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD2 cyl trans %d", i),
816 0, 0, framelz+framel/2, rot);
817 mother->AddNode(cylinderVolume, i, matrix);
818 matrix = new TGeoCombiTrans(Form("FMD2 fcov trans %d", i),
819 0, 0, framelz-backth/2, rot);
820 mother->AddNode(coverVolume, 2*i+0, matrix);
821 matrix = new TGeoCombiTrans(Form("FMD2 bcov trans %d", i),
822 0, 0, framelz+framel+backth/2,
824 mother->AddNode(coverVolume, 2*i+1, matrix);
832 TGeoBBox* flange1Shape = new TGeoBBox(f1l/2, f1w/2, f1d/2);
833 TGeoVolume* flange1Volume = new TGeoVolume(Form(fgkFlangeName, fmd2->GetId()),
835 TGeoBBox* flange2Shape = new TGeoBBox(f1w/2, f1d/2, (framel+backth)/2);
836 TGeoVolume* flange2Volume = new TGeoVolume(Form("F%dSG", fmd2->GetId()),
838 flange1Shape->SetName(Form(fgkFlangeName, fmd2->GetId()));
839 flange1Shape->SetTitle("FMD2 vertical flange");
840 flange1Volume->SetTitle("FMD2 vertical flange");
841 flange2Shape->SetName(Form("F%dSG", fmd2->GetId()));
842 flange2Shape->SetTitle("FMD2 horizontal flange");
843 flange2Volume->SetTitle("FMD2 horizontal flange ");
845 flange1Volume->SetTransparency(42);
846 for (Int_t i = 0; i < 4; i++) {
847 TGeoVolume* mother = (i < 2 ? fmd2TopVolume : fmd2BotVolume);
849 Double_t phi = 360. / 4 * i - 45;
850 Double_t rphi = TMath::Pi()*phi/180;
851 Double_t x = (framelr + f1l/2) * TMath::Sin(rphi);
852 Double_t y = (framelr + f1l/2) * TMath::Cos(rphi);
853 TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i));
855 TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD2 flange 1 trans %d", i),
856 x,y, framelz-backth-f1d/2, rot);
857 mother->AddNode(flange1Volume, 2*i+0, matrix);
858 matrix = new TGeoCombiTrans(Form("FMD2 flange 2 trans %d", i),
859 x,y,framelz+framel+backth+f1d/2,
861 mother->AddNode(flange1Volume, 2*i+1, matrix);
862 Double_t x1 = x - (f1w-f1d) / 2 * TMath::Cos(rphi);
863 Double_t y1 = y + (f1w-f1d) / 2 * TMath::Sin(rphi);
864 matrix = new TGeoCombiTrans(Form("FMD2 flange 3 trans %d", i),
865 x1,y1,framelz+framel/2, rot);
866 mother->AddNode(flange2Volume, 2*i+0, matrix);
867 Double_t x2 = x + (f1w-f1d) / 2 * TMath::Cos(rphi);
868 Double_t y2 = y - (f1w-f1d) / 2 * TMath::Sin(rphi);
869 matrix = new TGeoCombiTrans(Form("FMD2 flange 4 trans %d", i),
870 x2,y2,framelz+framel/2, rot);
871 mother->AddNode(flange2Volume, 2*i+1, matrix);
874 // Must be done after filling the assemblies
875 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
876 TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
877 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
878 fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
879 top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
880 top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
887 //____________________________________________________________________
889 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3,
890 TGeoVolume* innerTop,
891 TGeoVolume* innerBot,
892 TGeoVolume* outerTop,
893 TGeoVolume* outerBot)
895 // Setup the FMD3 geometry. The FMD2 has a rather elaborate support
896 // structure, as the support will also support the vacuum
899 // See also AliFMDGeometryBuilder::DetectorGeometry
901 if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
903 //__________________________________________________________________
904 // Basic detector set-up.
905 TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
906 fmd3->GetId(), 'T'));
907 TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
908 fmd3->GetId(), 'B'));
909 fmd3TopVolume->SetTitle("FMD3 top half");
910 fmd3BotVolume->SetTitle("FMD3 bottom half");
911 DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, fmd3->GetInnerZ(),
912 innerTop, innerBot, outerTop, outerBot);
914 //__________________________________________________________________
915 // Mother for all support material
916 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
917 support->SetTitle("FMD3 support");
919 //__________________________________________________________________
921 const TObjArray& radii = fmd3->ConeRadii();
922 Int_t nRadii = radii.GetEntriesFast();
923 TGeoPcon* coneBase = new TGeoPcon("FMD3_cone_base", 0., 180., nRadii);
926 for (Int_t i = 0; i < nRadii; i++) {
927 TVector3* v = static_cast<TVector3*>(radii.At(i));
928 coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
930 else if (i == 4) r4 = v;
932 TString coneComb("(FMD3_cone_base");
934 //__________________________________________________________________
936 double flangeDepth = fmd3->GetFlangeDepth() / 2;
937 double flangeLength = fmd3->GetFlangeLength() / 2;
938 double flangeWidth = fmd3->GetFlangeWidth() / 2;
939 new TGeoBBox("FMD3_flange_base", flangeLength, flangeWidth, flangeDepth);
942 const TObjArray& fiducialHoles = fmd3->FiducialHoles();
943 double fiducialRadius = fmd3->GetFiducialRadius();
944 TGeoTube* fiducialShape = new TGeoTube("FMD3_fiducial_hole", 0,
947 Int_t nFiducialHoles = fiducialHoles.GetEntriesFast();
948 double flangeAngle = TMath::Pi() / 4;
949 double flangeX = r5->Y()+flangeLength;
950 TVector2 flangeC(flangeX * TMath::Cos(flangeAngle),
951 flangeX * TMath::Sin(flangeAngle));
952 TString flangeComb("FMD3_flange_base-(");
953 #if 0// For debugging geometry
954 TGeoVolume* fiducialVolume = new TGeoVolume("FMD3_fiducial", fiducialShape);
955 fiducialVolume->SetLineColor(kGreen);
957 (void*)fiducialShape;
959 for (Int_t i = 0; i < nFiducialHoles; i++) {
960 TVector2& v = *(static_cast<TVector2*>(fiducialHoles.At(i)));
962 TVector2 r = v.Rotate(-flangeAngle);
963 TGeoTranslation* t1 = new TGeoTranslation(r.X(), r.Y(), 0);
964 TGeoTranslation* t2 = new TGeoTranslation(r.X(), -r.Y(), 0);
965 t1->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+0));
966 t2->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+1));
967 t1->RegisterYourself();
968 t2->RegisterYourself();
969 flangeComb.Append(Form("FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d+"
970 "FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d%c",
971 2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
972 #if 1 // For debugging geometry
973 // support->AddNode(fiducialVolume, 2*i+0, t1);
974 // support->AddNode(fiducialVolume, 2*i+1, t2);
978 // Final flange shape, and at to full shape
979 TGeoCompositeShape* flangeShape = new TGeoCompositeShape(flangeComb.Data());
980 flangeShape->SetName("FMD3_flange");
981 for (Int_t i = 0; i < 2; i++) {
982 TGeoRotation* rot = new TGeoRotation();
983 rot->RotateZ((i+.5)*90);
984 TVector2 v(flangeX, 0);
985 TVector2 w = v.Rotate((i+.5) * 2 * flangeAngle);
986 TGeoCombiTrans* trans = new TGeoCombiTrans(w.X(),w.Y(),
987 r4->X()+flangeDepth, rot);
988 trans->SetName(Form("FMD3_flange_matrix%d", i));
989 trans->RegisterYourself();
990 coneComb.Append(Form("+FMD3_flange:FMD3_flange_matrix%d", i));
992 coneComb.Append(")-(");
994 //__________________________________________________________________
996 Double_t holeL = (fmd3->GetHoleLength()-1)/2;
997 Double_t holeD = fmd3->GetHoleDepth()/2;
998 Double_t holeLW = fmd3->GetHoleLowWidth()/2;
999 Double_t holeHW = fmd3->GetHoleHighWidth()/2;
1000 Double_t holeA = fmd3->GetConeOuterAngle() - 1 * TMath::Pi() / 180;
1001 Double_t holeZ = (fmd3->GetHoleOffset()
1002 + holeL * TMath::Cos(holeA)
1003 - holeD * TMath::Sin(holeA));
1004 Double_t holeX = (fmd3->ConeR(-holeZ + fmd3->GetInnerZ() + fmd3->GetNoseZ())
1005 - holeD * TMath::Cos(holeA));
1006 Double_t plateZ = (fmd3->GetHoleOffset()
1007 + holeL * TMath::Cos(holeA)
1008 - 0.033 * TMath::Sin(holeA));
1009 Double_t plateX = (fmd3->ConeR(-plateZ + fmd3->GetInnerZ()+fmd3->GetNoseZ())
1010 - 0.033 * TMath::Cos(holeA));
1011 TGeoTrd1* holeShape = new TGeoTrd1("FMD3_cone_hole",
1012 holeLW, holeHW, holeD, holeL);
1013 TGeoTrd1* plateShape = new TGeoTrd1("FMD3_cooling_plate",
1014 holeLW, holeHW, .033, holeL);
1015 TGeoRotation* holeRot = new TGeoRotation();
1016 holeRot->SetName("FMD3_cone_hole_rotation");
1017 holeRot->RotateZ(90);
1018 holeRot->RotateY(holeA*180/TMath::Pi());
1019 TGeoCombiTrans* holeBaseTrans = new TGeoCombiTrans(holeX, 0, holeZ, holeRot);
1020 holeBaseTrans->SetName("FMD3_cone_hole_base_matrix");
1021 TGeoCombiTrans* plateBaseTrans = new TGeoCombiTrans(plateX, 0,plateZ,holeRot);
1023 TGeoVolume* plateVolume = new TGeoVolume("FMD3_cooling_plate",
1025 plateShape->SetTitle("FMD3 cooling plate");
1026 plateVolume->SetTitle("FMD3 cooling plate");
1027 for (Int_t i = 0; i < 4; i++) {
1028 Double_t ang = 360. / 8 * (i + .5);
1029 TGeoCombiTrans* trans = new TGeoCombiTrans(*holeBaseTrans);
1030 trans->RotateZ(ang);
1031 trans->SetName(Form("FMD3_cone_hole_matrix%d", i));
1032 trans->RegisterYourself();
1033 trans = new TGeoCombiTrans(*plateBaseTrans);
1034 trans->RotateZ(ang);
1035 trans->SetName(Form("FMD3_cooling_plate_matrix%d", i));
1036 coneComb.Append(Form("FMD3_cone_hole:FMD3_cone_hole_matrix%d+", i));
1037 support->AddNode(plateVolume, i, trans);
1040 //__________________________________________________________________
1042 Double_t boltRadius = fmd3->GetBoltRadius();
1043 Double_t boltLength = fmd3->GetBoltLength() / 2;
1044 Double_t boltZ1 = fmd3->GetInnerZ()+fmd3->GetNoseZ()-10;
1045 Double_t boltZ2 = fmd3->GetInnerZ()+fmd3->GetNoseZ()-20;
1046 Double_t boltXE = 2*boltLength*TMath::Cos(fmd3->GetConeOuterAngle());
1047 Double_t boltX1 = (fmd3->ConeR(boltZ1) - boltXE);
1048 Double_t boltX2 = (fmd3->ConeR(boltZ2) - boltXE);
1050 new TGeoTube("FMD3_bolt_hole", 0, boltRadius, boltLength+.2);
1051 TGeoTube* boltShape = new TGeoTube("FMD3_bolt", 0, boltRadius, boltLength);
1052 TGeoRotation* boltRot = new TGeoRotation();
1053 boltRot->RotateY(-fmd3->GetConeOuterAngle()*180/TMath::Pi());
1054 TGeoCombiTrans* boltTrans1 = new TGeoCombiTrans(boltX1, 0, 10, boltRot);
1055 TGeoCombiTrans* boltTrans2 = new TGeoCombiTrans(boltX2, 0, 20, boltRot);
1056 TGeoCombiTrans* boltTrans3 = new TGeoCombiTrans(*boltTrans1);
1057 TGeoCombiTrans* boltTrans4 = new TGeoCombiTrans(*boltTrans2);
1058 boltTrans3->RotateZ(180);
1059 boltTrans4->RotateZ(180);
1060 boltTrans1->SetName("FMD3_bolt_matrix1");
1061 boltTrans2->SetName("FMD3_bolt_matrix2");
1062 boltTrans3->SetName("FMD3_bolt_matrix3");
1063 boltTrans4->SetName("FMD3_bolt_matrix4");
1064 boltTrans1->RegisterYourself();
1065 boltTrans2->RegisterYourself();
1066 boltTrans3->RegisterYourself();
1067 boltTrans4->RegisterYourself();
1068 coneComb.Append("FMD3_bolt_hole:FMD3_bolt_matrix1"
1069 "+FMD3_bolt_hole:FMD3_bolt_matrix2"
1070 "+FMD3_bolt_hole:FMD3_bolt_matrix3"
1071 "+FMD3_bolt_hole:FMD3_bolt_matrix4)");
1072 TGeoVolume* boltVolume = new TGeoVolume("FMD3_bolt", boltShape, fSteel);
1073 support->AddNode(boltVolume, 1, boltTrans1);
1074 support->AddNode(boltVolume, 2, boltTrans2);
1075 boltShape->SetTitle("FMD3 steering bolt");
1076 boltVolume->SetTitle("FMD3 steering bolt");
1078 //__________________________________________________________________
1080 TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneComb.Data());
1081 coneShape->SetName("FMD3_cone");
1082 coneShape->SetTitle("FMD3 cone");
1083 TGeoVolume* coneVolume = new TGeoVolume("FMD3_Cone", coneShape, fC);
1084 coneVolume->SetLineColor(kRed);
1085 support->AddNode(coneVolume, 0, new TGeoTranslation(0, 0, 0));
1087 //__________________________________________________________________
1089 TGeoBBox* tensionOuter = new TGeoBBox("FMD3_tension_outer", .5, 3, 5);
1090 new TGeoBBox("FMD3_tension_inner", .51, 2.7, 4.3);
1091 TString tensionExpr("FMD3_tension_outer-FMD3_tension_inner");
1092 TGeoCompositeShape* tensionShape = new TGeoCompositeShape(tensionExpr.Data());
1093 tensionShape->SetName("FMD3_tension_box");
1094 tensionShape->SetTitle("FMD3 tension box");
1095 TGeoVolume* tensionFrame = new TGeoVolume("FMD3_tension_frame",
1097 TGeoTube* springShape = new TGeoTube("FMD3_tension_spring",
1099 TGeoVolume* springVolume = new TGeoVolume("FMD3_tension_spring",
1100 springShape, fSteel);
1101 TGeoVolume* tensionBox = new TGeoVolume("FMD3_tension_box",
1102 tensionOuter, fAir);
1103 tensionBox->AddNode(tensionFrame, 0);
1104 tensionBox->AddNode(springVolume, 0, new TGeoTranslation(0,0,4.2/2));
1106 Double_t tensionD = 5*TMath::Cos(fmd3->GetConeOuterAngle());
1107 Double_t tensionZ = (r4->Z() - 2 * tensionD -
1108 2*.5*TMath::Cos(fmd3->GetConeOuterAngle()));
1109 Double_t tensionX = (fmd3->ConeR(fmd3->GetInnerZ()
1112 2*.5*TMath::Cos(fmd3->GetConeOuterAngle()));
1113 TGeoRotation* tensionRot = new TGeoRotation();
1114 tensionRot->RotateY(180/TMath::Pi()*fmd3->GetConeOuterAngle());
1115 TGeoCombiTrans* tensionBase = new TGeoCombiTrans(tensionX, 0, tensionZ,
1118 Double_t wireR1 = fmd3->ConeR(fmd3->GetInnerZ()
1120 Double_t wireR2 = fmd3->ConeR(fmd3->GetInnerZ()
1123 Double_t wireL = TMath::Sqrt(TMath::Power(wireR1-wireR2,2)+
1124 TMath::Power(tensionZ-
1126 Double_t wireAngle = TMath::ATan2(wireR2-wireR1,tensionZ-tensionD);
1127 TGeoTube* wireShape = new TGeoTube("FMD3_wire", 0, .1, wireL/2);
1128 TGeoVolume* wireVolume = new TGeoVolume("FMD3_wire", wireShape,fSteel);
1129 TGeoRotation* wireRot = new TGeoRotation();
1130 wireRot->RotateY(180/TMath::Pi()*wireAngle);
1131 TGeoCombiTrans* wireBase = new TGeoCombiTrans((wireR2-wireR1)/2+wireR1
1132 +.1*TMath::Cos(wireAngle),
1133 0,(tensionZ-tensionD)/2,
1135 for (Int_t i = 0; i < 2; i++) {
1136 Double_t thisAngle = (i+.5) * 90;
1137 TGeoCombiTrans* thisTrans = new TGeoCombiTrans(*tensionBase);
1138 thisTrans->RotateZ(thisAngle);
1139 support->AddNode(tensionBox, i, thisTrans);
1140 thisTrans = new TGeoCombiTrans(*wireBase);
1141 thisTrans->RotateZ(thisAngle);
1142 support->AddNode(wireVolume, i, thisTrans);
1145 //__________________________________________________________________
1146 // Place support volumes in half-detector volumes
1147 Double_t z = fmd3->GetInnerZ();
1148 TGeoTranslation* t1 = new TGeoTranslation(0, 0, -fmd3->GetNoseZ());
1149 fmd3TopVolume->AddNode(support, 1, t1);
1150 TGeoCombiTrans* t2 = new TGeoCombiTrans(*t1);
1152 fmd3BotVolume->AddNode(support, 2, t2);
1154 TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
1156 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
1157 TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1158 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
1159 fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1160 top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1161 top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1167 //____________________________________________________________________
1169 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3,
1170 TGeoVolume* innerTop,
1171 TGeoVolume* innerBot,
1172 TGeoVolume* outerTop,
1173 TGeoVolume* outerBot)
1175 // Setup the FMD3 geometry. The FMD2 has a rather elaborate support
1176 // structure, as the support will also support the vacuum
1179 // See also AliFMDGeometryBuilder::DetectorGeometry
1181 if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
1182 Double_t nlen = fmd3->GetNoseLength();
1183 Double_t nz = fmd3->GetNoseZ();
1184 Double_t noser1 = fmd3->GetNoseLowR();
1185 Double_t noser2 = fmd3->GetNoseHighR();
1186 Double_t conet = fmd3->GetBeamThickness();
1187 Double_t conel = fmd3->GetConeLength();
1188 Double_t backl = fmd3->GetBackLength();
1189 // Double_t backr1 = fmd3->GetBackLowR();
1190 Double_t backr2 = fmd3->GetBackHighR();
1191 Double_t zdist = conel - backl - nlen;
1192 Double_t tdist = backr2 - noser2;
1193 // Double_t beaml = TMath::Sqrt(zdist * zdist + tdist * tdist);
1194 Double_t theta = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
1195 Double_t flanger = fmd3->GetFlangeR();
1196 Double_t z = fmd3->GetInnerZ(); // fmd3->GetZ();
1198 TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
1199 fmd3->GetId(), 'T'));
1200 TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName,
1201 fmd3->GetId(), 'B'));
1202 fmd3TopVolume->SetTitle("FMD3 top half");
1203 fmd3BotVolume->SetTitle("FMD3 bottom half");
1206 DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z,
1207 innerTop, innerBot, outerTop, outerBot);
1210 TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
1211 support->SetTitle("FMD3 support");
1214 TGeoPcon* coneBase = new TGeoPcon("FMD3 cone base", 0, 180, 6);
1215 const TObjArray& radii = fmd3.ConeRadii();
1218 for (Int_t i = 0; i < radii.GetEntriesFast(); i++) {
1219 TVector3* v = static_cast<TVector3*>(radii.At(i));
1220 coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
1225 Double_t holeL = TMath::Sqrt(TMath::Power(v4->Z()-v1->Z(),2) +
1226 TMath::Power(v4->X()-v1->X(),2));
1228 TGeoTrd1* coneHole = new TGeoTrd1("F3SC_hole",2,8,conet*3,
1234 TGeoTubeSeg* noseShape = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180);
1235 TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
1236 support->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, nlen/2));
1237 noseShape->SetName(fgkNoseName);
1238 noseShape->SetTitle("FMD3 nose");
1239 noseVolume->SetTitle("FMD3 nose");
1242 TGeoTube* boltShape = new TGeoTube("F3SB", 0, 0.3, conet / 2);
1243 TGeoVolume* boltVolume = new TGeoVolume("F3SB", boltShape, fSteel);
1245 Double_t x1 = (fmd3->ConeR(nz+z1));
1246 TGeoRotation* r1 = new TGeoRotation();
1248 TGeoCombiTrans* t = new TGeoCombiTrans("F3SB1",x1,0,-z1,r1);
1249 support->AddNode(boltVolume, 1, t);
1251 x1 = (fmd3->ConeR(nz+z1));
1252 t = new TGeoCombiTrans("F3SB2",x1,0,-z1,r1);
1253 support->AddNode(boltVolume, 2, t);
1254 boltShape->SetTitle("FMD3 steering bolt");
1255 boltVolume->SetTitle("FMD3 steering bolt");
1258 TGeoTrd1* plateShape = new TGeoTrd1(2, 8, 0.1, (conel-2-2)/2-.1);
1259 TGeoVolume* plateVolume = new TGeoVolume("F3CO", plateShape, fAl);
1260 plateShape->SetName("F3C0");
1261 plateShape->SetTitle("FMD3 cooling plate");
1262 plateVolume->SetTitle("FMD3 cooling plate");
1264 // Shape for carbon half-cone
1265 TGeoConeSeg* innerCone = new TGeoConeSeg("F3SC_inner", conel/2,
1266 noser2-conet, noser2,
1267 backr2-conet, backr2, 0., 180.);
1268 innerCone->SetTitle("FMD3 cone inner");
1269 TGeoTrd1* coneHole = new TGeoTrd1("F3SC_hole",2,8,conet*3,
1271 coneHole->SetTitle("FMD3 cone hole");
1272 Double_t holeAng = TMath::ATan2(backr2 - noser2, conel);
1273 Double_t holeX = ((conel-2) / 2 * TMath::Sin(holeAng) +
1274 conet * TMath::Cos(holeAng) +
1276 TGeoRotation* holeRot = new TGeoRotation();
1277 holeRot->SetName("FMD3 cone hole rotation");
1278 holeRot->RotateZ(90);
1279 holeRot->RotateY(holeAng*180./TMath::Pi());
1280 TGeoCombiTrans* holeTrans = new TGeoCombiTrans(holeX, 0, -2, holeRot);
1281 holeRot->SetName("FMD3 cone hole");
1283 // Build-up the composite shape for the cone, and add cooling plates
1284 // at the same time.
1285 TString coneExp("F3SC_inner-(");
1286 for (int i = 0; i < 4; i++) {
1287 Double_t thisAng = 360. / 8 * (i + .5);
1288 TGeoCombiTrans* thisTrans = new TGeoCombiTrans(*holeTrans);
1289 thisTrans->RotateZ(thisAng);
1290 thisTrans->SetName(Form("F3SC_rot%d", i));
1291 thisTrans->RegisterYourself();
1292 coneExp.Append(Form("F3SC_hole:F3SC_rot%d+", i));
1294 const Double_t* tt = thisTrans->GetTranslation();
1295 Double_t x = tt[0]+1*TMath::Cos(thisAng*TMath::Pi()/180);
1296 Double_t y = tt[1]+1*TMath::Sin(thisAng*TMath::Pi()/180);
1297 TGeoCombiTrans* plateTrans = new TGeoCombiTrans(x,y,tt[2]-1+nlen+conel/2,
1298 thisTrans->GetRotation());
1299 support->AddNode(plateVolume, i, plateTrans);
1301 // Remove bolt holes
1302 coneExp.Append("F3SB:F3SB1+F3SB:F3SB2)");
1304 // Finalize the half-cone shape and add volume
1305 TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneExp.Data());
1306 TGeoVolume* coneVolume = new TGeoVolume("F3SC", coneShape, fC);
1307 coneShape->SetName("F3SC");
1308 coneShape->SetTitle("FMD3 cone");
1309 coneVolume->SetTitle("FMD3 cone");
1310 support->AddNode(coneVolume,1,new TGeoTranslation(0,0,nlen+conel/2));
1313 TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2,
1314 fmd3->GetBeamWidth() / 2,
1316 TGeoVolume* flangeVolume = new TGeoVolume(Form(fgkFlangeName, fmd3->GetId()),
1318 flangeShape->SetName(Form(fgkFlangeName, fmd3->GetId()));
1319 flangeShape->SetTitle("FMD3 flange");
1320 flangeVolume->SetTitle("FMD3 flange");
1322 Int_t n = fmd3->GetNFlange();
1323 Double_t r = backr2 + (flanger - backr2) / 2;
1324 for (Int_t i = 0; i < n/2; i++) {
1325 Double_t phi = 360. / n * i + 180. / n;
1326 Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi);
1327 Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi);
1328 TGeoRotation* rot = new TGeoRotation;
1330 TGeoMatrix* matrix = new TGeoCombiTrans(x, y, nlen+conel-backl/2, rot);
1331 matrix->SetName(Form("FMD3_flange_%02d", i));
1332 matrix->SetTitle(Form("FMD3_flange_%2d", i));
1333 support->AddNode(flangeVolume, i, matrix);
1336 // Place support volumes in half-detector volumes
1337 z = fmd3->GetInnerZ();
1339 fmd3TopVolume->AddNode(support, 1, new TGeoTranslation(0,0,z1));
1340 r1 = new TGeoRotation();
1342 t = new TGeoCombiTrans(0,0,z1,r1);
1343 fmd3BotVolume->AddNode(support, 2, t);
1345 TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
1347 TGeoVolume* top = gGeoManager->GetVolume("ALIC");
1348 TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1349 AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f",
1350 fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1351 top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1352 top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1358 //____________________________________________________________________
1360 AliFMDGeometryBuilder::Exec(Option_t*)
1362 // Setup up the FMD geometry.
1363 AliFMDDebug(1, ("\tGeometry options: %s",
1364 (fDetailed ? "divided into strips" : "one volume")));
1366 AliFatal("No TGeoManager defined");
1370 fSi = gGeoManager->GetMedium("FMD_Si$");
1371 fC = gGeoManager->GetMedium("FMD_Carbon$");
1372 fAl = gGeoManager->GetMedium("FMD_Aluminum$");
1373 fChip = gGeoManager->GetMedium("FMD_Si Chip$");
1374 fAir = gGeoManager->GetMedium("FMD_Air$");
1375 fPCB = gGeoManager->GetMedium("FMD_PCB$");
1376 fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1377 fCopper = gGeoManager->GetMedium("FMD_Copper$");
1378 fSteel = gGeoManager->GetMedium("FMD_Steel$");
1380 if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1381 AliError("Failed to get some or all tracking mediums");
1384 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1385 AliFMDRing* inner = fmd->GetInner();
1386 AliFMDRing* outer = fmd->GetOuter();
1387 RingGeometry(inner);
1388 RingGeometry(outer);
1389 TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1391 TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1393 TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName,
1395 TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName,
1398 FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1399 FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1400 FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1401 #ifndef USE_PRE_MOVE
1402 fmd->SetSectorOff(fSectorOff);
1403 fmd->SetModuleOff(fModuleOff);
1404 fmd->SetRingOff(fRingOff);
1405 fmd->SetDetectorOff(fDetectorOff);
1406 fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1408 // fmd->ExtractGeomInfo();
1413 //____________________________________________________________________