]>
Commit | Line | Data |
---|---|---|
1 | /************************************************************************** | |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
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 | **************************************************************************/ | |
15 | /* $Id$ */ | |
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 | |
20 | */ | |
21 | //____________________________________________________________________ | |
22 | // | |
23 | // Builder of FMD geometry. | |
24 | // | |
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. | |
32 | // | |
33 | // | |
34 | ||
35 | #include <TArrayD.h> // ROOT_TArrayD | |
36 | #include <TGeoManager.h> // ROOT_TGeoManager | |
37 | #include <TGeoMatrix.h> // ROOT_TGeoMatrix | |
38 | #include <TGeoTube.h> // ROOT_TGeoTube | |
39 | #include <TGeoTrd1.h> // ROOT_TGeoTrd1 | |
40 | #include <TGeoCone.h> // ROOT_TGeoTrd1 | |
41 | #include <TGeoVolume.h> // ROOT_TGeoVolume | |
42 | #include <TGeoXtru.h> // ROOT_TGeoXtru | |
43 | #include <TGeoCompositeShape.h> | |
44 | #include <TMath.h> | |
45 | #include <TVector2.h> // ROOT_TVector2 | |
46 | //#include <TGeoMaterial.h> // ROOT_TGeoMaterial | |
47 | //#include <TGeoMedium.h> // ROOT_TGeoMedium | |
48 | //#include <TGeoPcon.h> // ROOT_TGeoPcon | |
49 | //#include <TGeoPolygon.h> // ROOT_TGeoPolygon | |
50 | ||
51 | #include "AliFMDGeometryBuilder.h" // ALIFMDGEOSIMULATOR_H | |
52 | #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H | |
53 | #include "AliFMDDetector.h" // ALIFMDDETECTOR_H | |
54 | #include "AliFMDRing.h" // ALIFMDRING_H | |
55 | #include "AliFMD1.h" // ALIFMD1_H | |
56 | #include "AliFMD2.h" // ALIFMD2_H | |
57 | #include "AliFMD3.h" // ALIFMD3_H | |
58 | // #include "AliFMD.h" // ALIFMD_H | |
59 | #include "AliFMDDebug.h" // ALILOG_H | |
60 | ||
61 | //==================================================================== | |
62 | ClassImp(AliFMDGeometryBuilder) | |
63 | #if 0 | |
64 | ; // This is here to keep Emacs for indenting the next line | |
65 | #endif | |
66 | ||
67 | //____________________________________________________________________ | |
68 | const Char_t* AliFMDGeometryBuilder::fgkActiveName = "F%cAC"; | |
69 | const Char_t* AliFMDGeometryBuilder::fgkSectorName = "F%cSC"; | |
70 | const Char_t* AliFMDGeometryBuilder::fgkStripName = "F%cST"; | |
71 | const Char_t* AliFMDGeometryBuilder::fgkSensorName = "F%cSE"; | |
72 | const Char_t* AliFMDGeometryBuilder::fgkPCBName = "F%cPB"; | |
73 | const Char_t* AliFMDGeometryBuilder::fgkCuName = "F%cCU"; | |
74 | const Char_t* AliFMDGeometryBuilder::fgkChipName = "F%cCH"; | |
75 | const Char_t* AliFMDGeometryBuilder::fgkLongLegName = "F%cLL"; | |
76 | const Char_t* AliFMDGeometryBuilder::fgkShortLegName = "F%cSL"; | |
77 | const Char_t* AliFMDGeometryBuilder::fgkFrontVName = "F%cFH"; | |
78 | const Char_t* AliFMDGeometryBuilder::fgkBackVName = "F%cBH"; | |
79 | const Char_t* AliFMDGeometryBuilder::fgkRingTopName = "F%cTV"; | |
80 | const Char_t* AliFMDGeometryBuilder::fgkRingBotName = "F%cBV"; | |
81 | const Char_t* AliFMDGeometryBuilder::fgkHCName = "F%dH%c"; | |
82 | const Char_t* AliFMDGeometryBuilder::fgkIHCName = "F%dI%c"; | |
83 | const Char_t* AliFMDGeometryBuilder::fgkNoseName = "F3SN"; | |
84 | const Char_t* AliFMDGeometryBuilder::fgkBackName = "F%dSB"; | |
85 | const Char_t* AliFMDGeometryBuilder::fgkTopName = "F%dSU"; | |
86 | const Char_t* AliFMDGeometryBuilder::fgkBeamName = "F%dSL"; | |
87 | const Char_t* AliFMDGeometryBuilder::fgkFlangeName = "F%dSF"; | |
88 | const Char_t* AliFMDGeometryBuilder::fgkFMDDCuName = "F%cDC"; | |
89 | const Char_t* AliFMDGeometryBuilder::fgkFMDDPCBName = "F%cDP"; | |
90 | const Char_t* AliFMDGeometryBuilder::fgkFMDDChipName = "F%cDI"; | |
91 | const Char_t* AliFMDGeometryBuilder::fgkFMDDName = "F%cDD"; | |
92 | const Char_t* AliFMDGeometryBuilder::fgkFMDName = "F%dM%c"; | |
93 | ||
94 | //____________________________________________________________________ | |
95 | AliFMDGeometryBuilder::AliFMDGeometryBuilder() | |
96 | : TTask("FMD", "Geomtry builder"), | |
97 | fActiveId(0), | |
98 | fDetailed(kTRUE), | |
99 | fUseAssembly(kTRUE), | |
100 | fSectorOff(0), | |
101 | fModuleOff(0), | |
102 | fRingOff(0), | |
103 | fDetectorOff(0), | |
104 | fSi(0), | |
105 | fC(0), | |
106 | fAl(0), | |
107 | fPCB(0), | |
108 | fChip(0), | |
109 | fAir(0), | |
110 | fPlastic(0), | |
111 | fCopper(0), | |
112 | fSteel(0) | |
113 | { | |
114 | // Default constructor | |
115 | fActiveId.Set(2); | |
116 | } | |
117 | ||
118 | //____________________________________________________________________ | |
119 | AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) | |
120 | : TTask("FMD", "Geometry builder"), | |
121 | fActiveId(0), | |
122 | fDetailed(detailed), | |
123 | fUseAssembly(kTRUE), | |
124 | fSectorOff(0), | |
125 | fModuleOff(0), | |
126 | fRingOff(0), | |
127 | fDetectorOff(0), | |
128 | fSi(0), | |
129 | fC(0), | |
130 | fAl(0), | |
131 | fPCB(0), | |
132 | fChip(0), | |
133 | fAir(0), | |
134 | fPlastic(0), | |
135 | fCopper(0), | |
136 | fSteel(0) | |
137 | { | |
138 | // Normal constructor | |
139 | // | |
140 | // Parameters: | |
141 | // | |
142 | // fmd Pointer to AliFMD object | |
143 | // detailed Whether to make a detailed simulation or not | |
144 | // | |
145 | fActiveId.Set(2); | |
146 | } | |
147 | ||
148 | ||
149 | //____________________________________________________________________ | |
150 | TGeoVolume* | |
151 | AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r) | |
152 | { | |
153 | // Setup the geometry of a ring. The defined TGeoVolume is | |
154 | // returned, and should be used when setting up the rest of the | |
155 | // volumes. | |
156 | // | |
157 | // | |
158 | // Parameters: | |
159 | // | |
160 | // r Pointer to ring geometry object | |
161 | // | |
162 | // Returns: | |
163 | // pointer to ring volume | |
164 | // | |
165 | if (!r) { | |
166 | AliError("Didn't get a ring object"); | |
167 | return 0; | |
168 | } | |
169 | Char_t id = r->GetId(); | |
170 | const Char_t* lName = (id == 'i' || id == 'I' ? "inner" : "outer"); | |
171 | Double_t siThick = r->GetSiThickness(); | |
172 | const Int_t knv = r->GetNVerticies(); | |
173 | TVector2* a = r->GetVertex(5); | |
174 | TVector2* b = r->GetVertex(3); | |
175 | TVector2* c = r->GetVertex(4); | |
176 | Double_t theta = r->GetTheta(); | |
177 | Double_t off = (TMath::Tan(TMath::Pi() * theta / 180) | |
178 | * r->GetBondingWidth()); | |
179 | Double_t rmax = b->Mod(); | |
180 | Double_t rmin = r->GetLowR(); | |
181 | Double_t pcbThick = r->GetPrintboardThickness(); | |
182 | Double_t cuThick = r->GetCopperThickness(); | |
183 | Double_t chipThick= r->GetChipThickness(); | |
184 | Double_t modSpace = r->GetModuleSpacing(); | |
185 | Double_t legr = r->GetLegRadius(); | |
186 | Double_t legl = r->GetLegLength(); | |
187 | Double_t legoff = r->GetLegOffset(); | |
188 | Int_t ns = r->GetNStrips(); | |
189 | Double_t stripoff = a->Mod(); | |
190 | Double_t dstrip = (rmax - stripoff) / ns; | |
191 | Double_t space = r->GetSpacing(); | |
192 | TArrayD xs(knv); | |
193 | TArrayD ys(knv); | |
194 | for (Int_t i = 0; i < knv; i++) { | |
195 | // Reverse the order | |
196 | TVector2* vv = r->GetVertex(knv - 1 - i); | |
197 | if (!vv) { | |
198 | AliError(Form("Failed to get vertex # %d", knv - 1 - i)); | |
199 | continue; | |
200 | } | |
201 | xs[i] = vv->X(); | |
202 | ys[i] = vv->Y(); | |
203 | } | |
204 | ||
205 | // Shape of actual sensor | |
206 | TGeoXtru* sensorShape = new TGeoXtru(2); | |
207 | sensorShape->DefinePolygon(knv, xs.fArray, ys.fArray); | |
208 | sensorShape->DefineSection(0, - siThick/2); | |
209 | sensorShape->DefineSection(1, siThick/2); | |
210 | sensorShape->SetName(Form(fgkSensorName, id)); | |
211 | sensorShape->SetTitle(Form("FMD %s Sensor", lName)); | |
212 | TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id), | |
213 | sensorShape, fSi); | |
214 | sensorVolume->SetTitle(Form("FMD %s Sensor", lName)); | |
215 | sensorVolume->VisibleDaughters(kFALSE); | |
216 | Int_t sid = sensorVolume->GetNumber(); | |
217 | fSectorOff = -1; | |
218 | fModuleOff = 1; | |
219 | fRingOff = 2; | |
220 | fDetectorOff = 3; | |
221 | if (fDetailed) { | |
222 | fSectorOff = 1; | |
223 | fModuleOff = 4; | |
224 | fRingOff = 5; | |
225 | fDetectorOff = 6; | |
226 | // Virtual volume shape to divide - This volume is only defined if | |
227 | // the geometry is set to be detailed. | |
228 | TGeoTubeSeg* activeShape = new TGeoTubeSeg(rmin, rmax, siThick/2, | |
229 | - theta, theta); | |
230 | activeShape->SetName(Form(fgkActiveName, id)); | |
231 | activeShape->SetTitle(Form("FMD %s active area", lName)); | |
232 | TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id), | |
233 | activeShape,fSi); | |
234 | activeVolume->SetTitle(Form("FMD %s active area", lName)); | |
235 | TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), | |
236 | 2, 2, -theta,0,0,"N"); | |
237 | sectorVolume->SetTitle(Form("FMD %s sector", lName)); | |
238 | TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id), | |
239 | 1, ns, stripoff, dstrip, | |
240 | 0, "SX"); | |
241 | stripVolume->SetTitle(Form("FMD %s strip", lName)); | |
242 | sid = stripVolume->GetNumber(); | |
243 | sensorVolume->AddNodeOverlap(activeVolume, 0); | |
244 | } | |
245 | ||
246 | switch (id) { | |
247 | case 'i': case 'I': fActiveId[0] = sid; break; | |
248 | case 'o': case 'O': fActiveId[1] = sid; break; | |
249 | } | |
250 | ||
251 | // Shape of Printed circuit Board | |
252 | for (Int_t i = 0; i < knv / 2; i++) ys[i] -= off; | |
253 | for (Int_t i = knv / 2; i < knv; i++) ys[i] += off; | |
254 | TGeoXtru* pcbShape = new TGeoXtru(2); | |
255 | pcbShape->DefinePolygon(knv, xs.fArray, ys.fArray); | |
256 | pcbShape->DefineSection(0, - pcbThick/2); | |
257 | pcbShape->DefineSection(1, pcbThick/2); | |
258 | pcbShape->SetName(Form(fgkPCBName, id)); | |
259 | pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName)); | |
260 | TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id), | |
261 | pcbShape, fPCB); | |
262 | pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName)); | |
263 | ||
264 | // Copper layer | |
265 | TGeoXtru* cuShape = new TGeoXtru(2); | |
266 | cuShape->DefinePolygon(6, xs.fArray, ys.fArray); | |
267 | cuShape->DefineSection(0, - cuThick/2); | |
268 | cuShape->DefineSection(1, cuThick/2); | |
269 | cuShape->SetTitle(Form("FMD %s hybrid copper", lName)); | |
270 | TGeoVolume* cuVolume = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper); | |
271 | cuVolume->SetTitle(Form("FMD %s hybrid copper", lName)); | |
272 | ||
273 | // Chip layer | |
274 | TGeoXtru* chipShape = new TGeoXtru(2); | |
275 | chipShape->DefinePolygon(6, xs.fArray, ys.fArray); | |
276 | chipShape->DefineSection(0, - chipThick/2); | |
277 | chipShape->DefineSection(1, chipThick/2); | |
278 | chipShape->SetTitle(Form("FMD %s hybrid chip", lName)); | |
279 | TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id), | |
280 | chipShape,fChip); | |
281 | chipVolume->SetTitle(Form("FMD %s hybrid chip", lName)); | |
282 | ||
283 | // Short leg shape | |
284 | TGeoTube* shortLegShape = new TGeoTube(0, legr, legl / 2); | |
285 | shortLegShape->SetName(Form(fgkShortLegName, id)); | |
286 | shortLegShape->SetTitle(Form("FMD %s short support foot", lName)); | |
287 | TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), | |
288 | shortLegShape, fCopper); | |
289 | shortLegVolume->SetTitle(Form("FMD %s short support foot", lName)); | |
290 | // Long leg shape | |
291 | TGeoTube* longLegShape = new TGeoTube(0, legr, (legl + modSpace) / 2); | |
292 | longLegShape->SetName(Form(fgkLongLegName, id)); | |
293 | longLegShape->SetTitle(Form("FMD %s long support foot", lName)); | |
294 | TGeoVolume* longLegVolume = new TGeoVolume(Form(fgkLongLegName, id), | |
295 | longLegShape, fCopper); | |
296 | longLegVolume->SetTitle(Form("FMD %s long support foot", lName)); | |
297 | ||
298 | ||
299 | // Back container volume | |
300 | TGeoVolume* backVolume = new TGeoVolumeAssembly(Form(fgkBackVName, id)); | |
301 | backVolume->SetTitle(Form("FMD %s back module", lName)); | |
302 | Double_t x = 0; | |
303 | Double_t y = 0; | |
304 | Double_t z = siThick / 2; | |
305 | backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z)); | |
306 | z += siThick / 2 + space + pcbThick / 2; | |
307 | backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z)); | |
308 | z += (pcbThick + cuThick) / 2; | |
309 | backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z)); | |
310 | z += (cuThick + chipThick) / 2; | |
311 | backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z)); | |
312 | x = a->X() + legoff + legr; | |
313 | y = 0; | |
314 | z += pcbThick / 2 + legl / 2; | |
315 | backVolume->AddNode(shortLegVolume, 0, new TGeoTranslation(x,y,z)); | |
316 | x = c->X(); | |
317 | y = c->Y() - legoff - legr - off; | |
318 | backVolume->AddNode(shortLegVolume, 1, new TGeoTranslation(x,y,z)); | |
319 | y = -y; | |
320 | backVolume->AddNode(shortLegVolume, 2, new TGeoTranslation(x,y,z)); | |
321 | ||
322 | // Front container volume | |
323 | TGeoVolume* frontVolume = new TGeoVolumeAssembly(Form(fgkFrontVName, id)); | |
324 | frontVolume->SetTitle(Form("FMD %s front module", lName)); | |
325 | x = 0; | |
326 | y = 0; | |
327 | z = siThick / 2; | |
328 | frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z)); | |
329 | z += siThick / 2 + space + pcbThick / 2; | |
330 | frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z)); | |
331 | z += (pcbThick + cuThick) / 2; | |
332 | frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z)); | |
333 | z += (cuThick + chipThick) / 2; | |
334 | frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z)); | |
335 | x = a->X() + legoff + legr; | |
336 | y = 0; | |
337 | z += pcbThick / 2 + (legl + modSpace)/ 2; | |
338 | frontVolume->AddNode(longLegVolume, 0, new TGeoTranslation(x,y,z)); | |
339 | x = c->X(); | |
340 | y = c->Y() - legoff - legr - off; | |
341 | frontVolume->AddNode(longLegVolume, 1, new TGeoTranslation(x,y,z)); | |
342 | y = -y; | |
343 | frontVolume->AddNode(longLegVolume, 2, new TGeoTranslation(x,y,z)); | |
344 | ||
345 | ||
346 | // FMDD | |
347 | Double_t ddlr = r->GetFMDDLowR(); | |
348 | Double_t ddhr = r->GetFMDDHighR(); | |
349 | Double_t ddpt = r->GetFMDDPrintboardThickness(); | |
350 | Double_t ddct = r->GetFMDDCopperThickness(); | |
351 | Double_t ddit = r->GetFMDDChipThickness(); | |
352 | Double_t ddt = ddpt + ddct + ddit; | |
353 | ||
354 | TGeoShape* fmddPcbShape = new TGeoTubeSeg(ddlr, ddhr, ddpt/2,0,180); | |
355 | TGeoShape* fmddCuShape = new TGeoTubeSeg(ddlr, ddhr, ddct/2,0,180); | |
356 | TGeoShape* fmddChipShape = new TGeoTubeSeg(ddlr, ddhr, ddit/2,0,180); | |
357 | fmddPcbShape->SetName(Form(fgkFMDDPCBName, id)); | |
358 | fmddCuShape->SetName(Form(fgkFMDDCuName, id)); | |
359 | fmddChipShape->SetName(Form(fgkFMDDChipName, id)); | |
360 | if (id == 'O' || id == 'o') { | |
361 | TString pcbName(fmddPcbShape->GetName()); | |
362 | TString cuName(fmddCuShape->GetName()); | |
363 | TString chipName(fmddChipShape->GetName()); | |
364 | ||
365 | fmddPcbShape->SetName(Form("%s_inner", pcbName.Data())); | |
366 | fmddCuShape->SetName(Form("%s_inner", cuName.Data())); | |
367 | fmddChipShape->SetName(Form("%s_inner", chipName.Data())); | |
368 | new TGeoBBox(Form("%s_clip", pcbName.Data()), ddlr+3, ddhr/2, ddpt); | |
369 | new TGeoBBox(Form("%s_clip", cuName.Data()), ddlr+3, ddhr/2, ddpt); | |
370 | new TGeoBBox(Form("%s_clip", chipName.Data()),ddlr+3, ddhr/2, ddpt); | |
371 | TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans", | |
372 | pcbName.Data()), | |
373 | 0, ddhr/2, 0); | |
374 | trans->RegisterYourself(); | |
375 | fmddPcbShape = new TGeoCompositeShape(pcbName.Data(), | |
376 | Form("%s_inner*%s_clip:%s_trans", | |
377 | pcbName.Data(), | |
378 | pcbName.Data(), | |
379 | pcbName.Data())); | |
380 | fmddCuShape = new TGeoCompositeShape(cuName.Data(), | |
381 | Form("%s_inner*%s_clip:%s_trans", | |
382 | cuName.Data(), | |
383 | cuName.Data(), | |
384 | pcbName.Data())); | |
385 | fmddChipShape = new TGeoCompositeShape(chipName.Data(), | |
386 | Form("%s_inner*%s_clip:%s_trans", | |
387 | chipName.Data(), | |
388 | chipName.Data(), | |
389 | pcbName.Data())); | |
390 | } | |
391 | fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName)); | |
392 | fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName)); | |
393 | fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName)); | |
394 | ||
395 | TGeoVolume* fmddPcbVolume = new TGeoVolume(Form(fgkFMDDPCBName, id), | |
396 | fmddPcbShape, fPCB); | |
397 | TGeoVolume* fmddCuVolume = new TGeoVolume(Form(fgkFMDDCuName, id), | |
398 | fmddCuShape, fCopper); | |
399 | TGeoVolume* fmddChipVolume= new TGeoVolume(Form(fgkFMDDChipName, id), | |
400 | fmddChipShape, fChip); | |
401 | fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName)); | |
402 | fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName)); | |
403 | fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName)); | |
404 | ||
405 | // Half ring mother volumes. | |
406 | TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id)); | |
407 | TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id)); | |
408 | TGeoVolume* halfRing = ringTopVolume; | |
409 | ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName)); | |
410 | ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName)); | |
411 | ||
412 | // Adding modules to half-rings | |
413 | Int_t nmod = r->GetNModules(); | |
414 | AliFMDDebug(10, ("making %d modules in ring %c", nmod, id)); | |
415 | for (Int_t i = 0; i < nmod; i++) { | |
416 | if (i == nmod / 2) halfRing = ringBotVolume; | |
417 | Bool_t front = (i % 2 == 0); | |
418 | TGeoVolume* vol = (front ? frontVolume : backVolume); | |
419 | // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2)); | |
420 | Double_t z1 = (i % 2) * modSpace; | |
421 | Double_t th = (2 * i + 1) * theta; | |
422 | TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0); | |
423 | mat1->RotateZ(th); | |
424 | mat1->SetName(Form("FMD%c_module_%02d", id, i)); | |
425 | mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i)); | |
426 | halfRing->AddNode(vol, i, mat1); | |
427 | #if 0 | |
428 | Double_t z2 = z1 + siThick / 2 + space; | |
429 | Double_t th = (2 * i + 1) * theta; | |
430 | AliFMDDebug(20, ("Placing copy %d of %s and %s in %s at z=%f and %f, " | |
431 | "and theta=%f", i, sensorVolume->GetName(), | |
432 | vol->GetName(), halfRing->GetName(), z1, z2, th)); | |
433 | TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0); | |
434 | mat1->RotateZ(th); | |
435 | halfRing->AddNode(sensorVolume, i, mat1); | |
436 | TGeoMatrix* mat2 = new TGeoCombiTrans(0,0,z2,0); | |
437 | mat2->RotateZ(th); | |
438 | halfRing->AddNode(vol, i, mat2); | |
439 | #endif | |
440 | } | |
441 | ||
442 | // Add the FMDD | |
443 | Double_t zi = r->GetFullDepth() - ddt; | |
444 | Int_t n = 2; | |
445 | for (Int_t i = 0; i < n; i++) { | |
446 | halfRing = (i == 0 ? ringTopVolume : ringBotVolume); | |
447 | Double_t phi = 360. / n * i; | |
448 | TGeoRotation* rot = new TGeoRotation(Form("FMDD%c rotation %d", id, i)); | |
449 | rot->RotateZ(phi); | |
450 | rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i)); | |
451 | z = zi + ddpt / 2; | |
452 | halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot)); | |
453 | z += (ddpt + ddct) / 2; | |
454 | halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot)); | |
455 | z += (ddct + ddit) / 2; | |
456 | halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot)); | |
457 | } | |
458 | ||
459 | ||
460 | return 0; | |
461 | } | |
462 | ||
463 | //____________________________________________________________________ | |
464 | TGeoVolume* | |
465 | AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d, | |
466 | TGeoVolume* topMother, | |
467 | TGeoVolume* botMother, | |
468 | Double_t zMother, | |
469 | TGeoVolume* innerTop, | |
470 | TGeoVolume* innerBot, | |
471 | TGeoVolume* outerTop, | |
472 | TGeoVolume* outerBot) | |
473 | { | |
474 | // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries. | |
475 | // This includes putting the Honeycomb support plates and the rings | |
476 | // into the mother volumes. | |
477 | // | |
478 | // Parameeters: | |
479 | // d The detector geometry to use | |
480 | // mother The mother volume of the detector | |
481 | // zmother The midpoint in global coordinates of detector vol. | |
482 | // inner Pointer to inner ring volume | |
483 | // outer Pointer to outer ring volume | |
484 | // | |
485 | // Returns: | |
486 | // Pointer to mother (detector volume) | |
487 | // | |
488 | if (!d) return 0; | |
489 | // Loop over the defined rings | |
490 | for (int i = 0; i < 2; i++) { | |
491 | AliFMDRing* r = 0; | |
492 | Double_t lowr = 0; | |
493 | Double_t highr = 0; | |
494 | Double_t rz = 0; | |
495 | TGeoVolume* tvol = 0; | |
496 | TGeoVolume* bvol = 0; | |
497 | switch (i) { | |
498 | case 0: | |
499 | r = d->GetInner(); | |
500 | lowr = d->GetInnerHoneyLowR(); | |
501 | highr = d->GetInnerHoneyHighR(); | |
502 | rz = d->GetInnerZ(); | |
503 | tvol = innerTop; | |
504 | bvol = innerBot; | |
505 | break; | |
506 | case 1: | |
507 | r = d->GetOuter(); | |
508 | lowr = d->GetOuterHoneyLowR(); | |
509 | highr = d->GetOuterHoneyHighR(); | |
510 | rz = d->GetOuterZ(); | |
511 | tvol = outerTop; | |
512 | bvol = outerBot; | |
513 | break; | |
514 | } | |
515 | if (!r) continue; | |
516 | Char_t c = r->GetId(); | |
517 | Int_t id = d->GetId(); | |
518 | Double_t hcThick = r->GetHoneycombThickness(); | |
519 | Double_t alThick = r->GetAlThickness(); | |
520 | Double_t z = TMath::Abs(rz - zMother); | |
521 | ||
522 | // Place ring in mother volume | |
523 | // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0); | |
524 | AliFMDDebug(1, ("Placing volumes %s and %s in %s and %s at z=%f", | |
525 | tvol->GetName(), bvol->GetName(), | |
526 | topMother->GetName(), botMother->GetName(), z)); | |
527 | topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z)); | |
528 | botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z)); | |
529 | ||
530 | // Top of Honeycomb | |
531 | TGeoTubeSeg* hcSha = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180); | |
532 | hcSha->SetName(Form(fgkHCName,id,c)); | |
533 | hcSha->SetTitle(Form("FMD%d%c honeycomb shell", id, c)); | |
534 | TGeoVolume* hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl); | |
535 | hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c)); | |
536 | // Air in top of honeycomb | |
537 | TGeoTubeSeg* ihcSha = new TGeoTubeSeg(lowr+alThick, highr - alThick, | |
538 | (hcThick-alThick)/2, 0, 180); | |
539 | ihcSha->SetName(Form(fgkIHCName,id,c)); | |
540 | ihcSha->SetTitle(Form("FMD%d%c honeycomb internal", id, c)); | |
541 | TGeoVolume* ihcVol = new TGeoVolume(Form(fgkIHCName,id,c),ihcSha,fAir); | |
542 | ihcVol->SetTitle(Form("FMD%d%c honeycomb internal", id, c)); | |
543 | hcVol->AddNode(ihcVol, 0); | |
544 | hcVol->VisibleDaughters(kFALSE); | |
545 | hcVol->SetVisibility(kTRUE); | |
546 | ||
547 | z += (r->GetSiThickness() + | |
548 | r->GetSpacing() + | |
549 | r->GetPrintboardThickness() + | |
550 | r->GetCopperThickness() + | |
551 | r->GetChipThickness() + | |
552 | r->GetModuleSpacing() + | |
553 | r->GetLegLength() + | |
554 | r->GetHoneycombThickness() + | |
555 | r->GetFMDDPrintboardThickness() - | |
556 | hcThick / 2); | |
557 | ||
558 | AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f", | |
559 | hcVol->GetName(), topMother->GetName(), | |
560 | botMother->GetName(), z)); | |
561 | // Add to top | |
562 | topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z)); | |
563 | ||
564 | // Add to bottom | |
565 | TGeoMatrix* bhcMatrix = new TGeoCombiTrans(0,0,z,0); | |
566 | bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c)); | |
567 | bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c)); | |
568 | bhcMatrix->RotateZ(180); | |
569 | botMother->AddNode(hcVol, 1, bhcMatrix); | |
570 | } | |
571 | return 0; | |
572 | } | |
573 | ||
574 | //____________________________________________________________________ | |
575 | TGeoVolume* | |
576 | AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1, | |
577 | TGeoVolume* innerTop, | |
578 | TGeoVolume* innerBot) | |
579 | { | |
580 | // Setup the FMD1 geometry. The FMD1 only has one ring, and no | |
581 | // special support as it is at the momement. | |
582 | // | |
583 | // See also AliFMDGeometryBuilder::DetectorGeometry | |
584 | // | |
585 | if (!fmd1 || !innerTop || !innerBot) return 0; | |
586 | AliFMDRing* r = fmd1->GetInner(); | |
587 | Double_t z = fmd1->GetInnerZ(); | |
588 | Double_t disce = 2; | |
589 | Double_t backlr = fmd1->GetInnerHoneyHighR(); | |
590 | Double_t backhr = fmd1->GetInnerHoneyHighR()+5; | |
591 | Double_t backth = 0.2; | |
592 | Double_t toplr = r->GetLowR(); | |
593 | Double_t tophr = fmd1->GetInnerHoneyHighR()+disce; | |
594 | Double_t wallbh = (r->GetFullDepth() + disce); | |
595 | Double_t wallth = wallbh+0.1; | |
596 | ||
597 | TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
598 | fmd1->GetId(), 'T')); | |
599 | fmd1TopVolume->SetTitle("FMD1 top half"); | |
600 | TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
601 | fmd1->GetId(), 'B')); | |
602 | fmd1BotVolume->SetTitle("FMD1 bottom half"); | |
603 | ||
604 | // Basic detector geometry | |
605 | DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z, | |
606 | innerTop, innerBot, 0, 0); | |
607 | ||
608 | ||
609 | // Back | |
610 | TGeoTubeSeg* backShape = new TGeoTubeSeg(backlr, backhr, backth / 2, 0, 180); | |
611 | TGeoTubeSeg* wallbShape = new TGeoTubeSeg(backlr, backlr + backth, | |
612 | wallbh/2, 0, 180); | |
613 | TGeoTubeSeg* topShape = new TGeoTubeSeg(toplr, tophr, backth / 2, 0, 180); | |
614 | TGeoTubeSeg* walltShape = new TGeoTubeSeg(tophr, tophr + backth, | |
615 | wallth/2, 0, 180); | |
616 | TGeoVolume* backVolume = new TGeoVolume(Form(fgkBackName, fmd1->GetId()), | |
617 | backShape, fC); | |
618 | TGeoVolume* wallbVolume= new TGeoVolume(Form(fgkFlangeName, fmd1->GetId()), | |
619 | wallbShape, fC); | |
620 | TGeoVolume* topVolume = new TGeoVolume(Form(fgkTopName, fmd1->GetId()), | |
621 | topShape, fC); | |
622 | TGeoVolume* walltVolume= new TGeoVolume(Form(fgkBeamName, fmd1->GetId()), | |
623 | walltShape, fC); | |
624 | backShape->SetName(Form(fgkBackName, fmd1->GetId())); | |
625 | wallbShape->SetName(Form(fgkFlangeName, fmd1->GetId())); | |
626 | topShape->SetName(Form(fgkTopName, fmd1->GetId())); | |
627 | walltShape->SetName(Form(fgkBeamName, fmd1->GetId())); | |
628 | backShape->SetTitle("FMD1 back saucer rim"); | |
629 | wallbShape->SetTitle("FMD1 back saucer wall"); | |
630 | topShape->SetTitle("FMD1 top lid"); | |
631 | walltShape->SetTitle("FMD1 top lid wall"); | |
632 | backVolume->SetFillColor(kGray); | |
633 | topVolume->SetFillColor(kGray); | |
634 | wallbVolume->SetFillColor(kGray); | |
635 | walltVolume->SetFillColor(kGray); | |
636 | backVolume->SetTitle("FMD1 back saucer rim"); | |
637 | wallbVolume->SetTitle("FMD1 back saucer wall"); | |
638 | topVolume->SetTitle("FMD1 top lid"); | |
639 | walltVolume->SetTitle("FMD1 top lid wall"); | |
640 | ||
641 | // Place volumes | |
642 | Double_t zb = TMath::Abs(fmd1->GetInnerZ() - z); | |
643 | Double_t zi = zb; | |
644 | Int_t n = 2; | |
645 | ||
646 | // Place top cover | |
647 | zi -= disce / 2 + backth / 2; | |
648 | zb = zi; | |
649 | for (Int_t i = 0; i < 2; i++) { | |
650 | TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume); | |
651 | Double_t phi = 360. / n * i; | |
652 | TGeoRotation* rot = new TGeoRotation(Form("FMD1 top rotation %d",i)); | |
653 | rot->RotateZ(phi); | |
654 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 top wall trans %d", i), | |
655 | 0, 0, zi, rot); | |
656 | mother->AddNode(topVolume, i, matrix); | |
657 | } | |
658 | // Place outer wall | |
659 | zi += wallth / 2 + backth / 2; | |
660 | for (Int_t i = 0; i < 2; i++) { | |
661 | TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume); | |
662 | Double_t phi = 360. / n * i; | |
663 | TGeoRotation* rot = new TGeoRotation(Form("FMD1 outer wall rotation %d", | |
664 | i)); | |
665 | rot->RotateZ(phi); | |
666 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 outer wall trans %d", | |
667 | i), 0, 0, zi, rot); | |
668 | mother->AddNode(walltVolume, i, matrix); | |
669 | } | |
670 | // Place back | |
671 | zi += wallth / 2 + backth / 2; // + disce / 2; | |
672 | for (Int_t i = 0; i < 2; i++) { | |
673 | TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume); | |
674 | Double_t phi = 360. / n * i; | |
675 | TGeoRotation* rot = new TGeoRotation(Form("FMD1 back rotation %d", i)); | |
676 | rot->RotateZ(phi); | |
677 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 back trans %d", i), | |
678 | 0, 0, zi, rot); | |
679 | mother->AddNode(backVolume, i, matrix); | |
680 | } | |
681 | // Place inner wall | |
682 | zi -= wallbh / 2 + backth / 2; // + disce / 2; | |
683 | for (Int_t i = 0; i < 2; i++) { | |
684 | TGeoVolume* mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume); | |
685 | Double_t phi = 360. / n * i; | |
686 | TGeoRotation* rot = new TGeoRotation(Form("FMD1 inner wall rotation %d", | |
687 | i)); | |
688 | rot->RotateZ(phi); | |
689 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD1 inner wall trans %d", | |
690 | i), 0, 0, zi, rot); | |
691 | mother->AddNode(wallbVolume, i, matrix); | |
692 | } | |
693 | ||
694 | ||
695 | // Must add this after filling the assembly. | |
696 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); | |
697 | // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z); | |
698 | TGeoRotation* rot = new TGeoRotation("FMD1 rotatation"); | |
699 | rot->RotateZ(-90); | |
700 | TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot); | |
701 | AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", | |
702 | fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z)); | |
703 | top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix); | |
704 | top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix); | |
705 | ||
706 | return 0; | |
707 | } | |
708 | ||
709 | //____________________________________________________________________ | |
710 | TGeoVolume* | |
711 | AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, | |
712 | TGeoVolume* innerTop, | |
713 | TGeoVolume* innerBot, | |
714 | TGeoVolume* outerTop, | |
715 | TGeoVolume* outerBot) | |
716 | { | |
717 | // Setup the FMD2 geometry. The FMD2 has no | |
718 | // special support as it is at the momement. | |
719 | // | |
720 | // See also AliFMDGeometryBuilder::DetectorGeometry | |
721 | // | |
722 | if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0; | |
723 | AliFMDRing* r = fmd2->GetOuter(); | |
724 | Double_t z = fmd2->GetOuterZ(); | |
725 | Double_t framelr = fmd2->GetOuterHoneyHighR()+0.5; | |
726 | Double_t framehr = fmd2->GetOuterHoneyHighR()+1.8; | |
727 | Double_t framelz = -1; | |
728 | Double_t framehz = (fmd2->GetInnerZ()-z) + r->GetFullDepth() + 1; | |
729 | Double_t framel = framehz - framelz; | |
730 | Double_t coverlr = fmd2->GetInner()->GetLowR()+1; | |
731 | Double_t backth = 0.05; | |
732 | ||
733 | TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
734 | fmd2->GetId(), 'T')); | |
735 | TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
736 | fmd2->GetId(), 'B')); | |
737 | fmd2TopVolume->SetTitle("FMD2 top half"); | |
738 | fmd2BotVolume->SetTitle("FMD2 bottom half"); | |
739 | ||
740 | DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, | |
741 | innerTop, innerBot, outerTop, outerBot); | |
742 | ||
743 | TGeoShape* cylinderShape = new TGeoTubeSeg(framelr,framehr,framel/2,0,180); | |
744 | TGeoVolume* cylinderVolume = new TGeoVolume(Form(fgkBackName, fmd2->GetId()), | |
745 | cylinderShape, fC); | |
746 | TGeoShape* coverShape = new TGeoTubeSeg(coverlr,framehr,backth/2,0,180); | |
747 | TGeoVolume* coverVolume = new TGeoVolume(Form(fgkTopName, fmd2->GetId()), | |
748 | coverShape, fC); | |
749 | cylinderShape->SetName(Form(fgkBackName, fmd2->GetId())); | |
750 | cylinderShape->SetTitle("FMD2 cylinder"); | |
751 | cylinderVolume->SetTitle("FMD2 cylinder"); | |
752 | cylinderVolume->SetTransparency(63); | |
753 | coverShape->SetName(Form(fgkTopName, fmd2->GetId())); | |
754 | coverShape->SetTitle("FMD2 cover"); | |
755 | coverVolume->SetTitle("FMD2 cover"); | |
756 | coverVolume->SetTransparency(63); | |
757 | ||
758 | for (Int_t i = 0; i < 2; i++) { | |
759 | TGeoVolume* mother = (i == 0 ? fmd2TopVolume : fmd2BotVolume); | |
760 | ||
761 | Double_t phi = 360. / 2 * i; | |
762 | TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i)); | |
763 | rot->RotateZ(phi); | |
764 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD2 cyl trans %d", i), | |
765 | 0, 0, framelz+framel/2, rot); | |
766 | mother->AddNode(cylinderVolume, i, matrix); | |
767 | matrix = new TGeoCombiTrans(Form("FMD2 fcov trans %d", i), | |
768 | 0, 0, framelz-backth/2, rot); | |
769 | mother->AddNode(coverVolume, 2*i+0, matrix); | |
770 | matrix = new TGeoCombiTrans(Form("FMD2 bcov trans %d", i), | |
771 | 0, 0, framelz+framel+backth/2, | |
772 | rot); | |
773 | mother->AddNode(coverVolume, 2*i+1, matrix); | |
774 | } | |
775 | ||
776 | ||
777 | Double_t f1l = 10; | |
778 | Double_t f1w = 6; | |
779 | Double_t f1d = 1.2; | |
780 | ||
781 | TGeoBBox* flange1Shape = new TGeoBBox(f1l/2, f1w/2, f1d/2); | |
782 | TGeoVolume* flange1Volume = new TGeoVolume(Form(fgkFlangeName, fmd2->GetId()), | |
783 | flange1Shape, fAl); | |
784 | TGeoBBox* flange2Shape = new TGeoBBox(f1w/2, f1d/2, (framel+backth)/2); | |
785 | TGeoVolume* flange2Volume = new TGeoVolume(Form("F%dSG", fmd2->GetId()), | |
786 | flange2Shape, fAl); | |
787 | flange1Shape->SetName(Form(fgkFlangeName, fmd2->GetId())); | |
788 | flange1Shape->SetTitle("FMD2 vertical flange"); | |
789 | flange1Volume->SetTitle("FMD2 vertical flange"); | |
790 | flange2Shape->SetName(Form("F%dSG", fmd2->GetId())); | |
791 | flange2Shape->SetTitle("FMD2 horizontal flange"); | |
792 | flange2Volume->SetTitle("FMD2 horizontal flange "); | |
793 | ||
794 | flange1Volume->SetTransparency(42); | |
795 | for (Int_t i = 0; i < 4; i++) { | |
796 | TGeoVolume* mother = (i < 2 ? fmd2TopVolume : fmd2BotVolume); | |
797 | ||
798 | Double_t phi = 360. / 4 * i - 45; | |
799 | Double_t rphi = TMath::Pi()*phi/180; | |
800 | Double_t x = (framelr + f1l/2) * TMath::Sin(rphi); | |
801 | Double_t y = (framelr + f1l/2) * TMath::Cos(rphi); | |
802 | TGeoRotation* rot = new TGeoRotation(Form("FMD2 support rot %d",i)); | |
803 | rot->RotateZ(phi); | |
804 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD2 flange 1 trans %d", i), | |
805 | x,y, framelz-backth-f1d/2, rot); | |
806 | mother->AddNode(flange1Volume, 2*i+0, matrix); | |
807 | matrix = new TGeoCombiTrans(Form("FMD2 flange 2 trans %d", i), | |
808 | x,y,framelz+framel+backth+f1d/2, | |
809 | rot); | |
810 | mother->AddNode(flange1Volume, 2*i+1, matrix); | |
811 | Double_t x1 = x - (f1w-f1d) / 2 * TMath::Cos(rphi); | |
812 | Double_t y1 = y + (f1w-f1d) / 2 * TMath::Sin(rphi); | |
813 | matrix = new TGeoCombiTrans(Form("FMD2 flange 3 trans %d", i), | |
814 | x1,y1,framelz+framel/2, rot); | |
815 | mother->AddNode(flange2Volume, 2*i+0, matrix); | |
816 | Double_t x2 = x + (f1w-f1d) / 2 * TMath::Cos(rphi); | |
817 | Double_t y2 = y - (f1w-f1d) / 2 * TMath::Sin(rphi); | |
818 | matrix = new TGeoCombiTrans(Form("FMD2 flange 4 trans %d", i), | |
819 | x2,y2,framelz+framel/2, rot); | |
820 | mother->AddNode(flange2Volume, 2*i+1, matrix); | |
821 | } | |
822 | ||
823 | // Must be done after filling the assemblies | |
824 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); | |
825 | TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z); | |
826 | AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", | |
827 | fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z)); | |
828 | top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix); | |
829 | top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix); | |
830 | ||
831 | ||
832 | return 0; | |
833 | } | |
834 | ||
835 | //____________________________________________________________________ | |
836 | TGeoVolume* | |
837 | AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, | |
838 | TGeoVolume* innerTop, | |
839 | TGeoVolume* innerBot, | |
840 | TGeoVolume* outerTop, | |
841 | TGeoVolume* outerBot) | |
842 | { | |
843 | // Setup the FMD3 geometry. The FMD2 has a rather elaborate support | |
844 | // structure, as the support will also support the vacuum | |
845 | // beam-pipe. | |
846 | // | |
847 | // See also AliFMDGeometryBuilder::DetectorGeometry | |
848 | // | |
849 | if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0; | |
850 | Double_t nlen = fmd3->GetNoseLength(); | |
851 | Double_t nz = fmd3->GetNoseZ(); | |
852 | Double_t noser1 = fmd3->GetNoseLowR(); | |
853 | Double_t noser2 = fmd3->GetNoseHighR(); | |
854 | Double_t conet = fmd3->GetBeamThickness(); | |
855 | Double_t conel = fmd3->GetConeLength(); | |
856 | Double_t backl = fmd3->GetBackLength(); | |
857 | // Double_t backr1 = fmd3->GetBackLowR(); | |
858 | Double_t backr2 = fmd3->GetBackHighR(); | |
859 | Double_t zdist = conel - backl - nlen; | |
860 | Double_t tdist = backr2 - noser2; | |
861 | // Double_t beaml = TMath::Sqrt(zdist * zdist + tdist * tdist); | |
862 | Double_t theta = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi(); | |
863 | Double_t flanger = fmd3->GetFlangeR(); | |
864 | Double_t z = fmd3->GetInnerZ(); // fmd3->GetZ(); | |
865 | ||
866 | TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
867 | fmd3->GetId(), 'T')); | |
868 | TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
869 | fmd3->GetId(), 'B')); | |
870 | fmd3TopVolume->SetTitle("FMD3 top half"); | |
871 | fmd3BotVolume->SetTitle("FMD3 bottom half"); | |
872 | ||
873 | ||
874 | DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z, | |
875 | innerTop, innerBot, outerTop, outerBot); | |
876 | ||
877 | ||
878 | TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU"); | |
879 | support->SetTitle("FMD3 support"); | |
880 | ||
881 | // Nose volume | |
882 | TGeoTubeSeg* noseShape = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180); | |
883 | TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC); | |
884 | support->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, nlen/2)); | |
885 | noseShape->SetName(fgkNoseName); | |
886 | noseShape->SetTitle("FMD3 nose"); | |
887 | noseVolume->SetTitle("FMD3 nose"); | |
888 | ||
889 | // Steel bolts | |
890 | TGeoTube* boltShape = new TGeoTube("F3SB", 0, 0.3, conet / 2); | |
891 | TGeoVolume* boltVolume = new TGeoVolume("F3SB", boltShape, fSteel); | |
892 | Double_t z1 = -10; | |
893 | Double_t x1 = (fmd3->ConeR(nz+z1)); | |
894 | TGeoRotation* r1 = new TGeoRotation(); | |
895 | r1->RotateY(theta); | |
896 | TGeoCombiTrans* t = new TGeoCombiTrans("F3SB1",x1,0,-z1,r1); | |
897 | support->AddNode(boltVolume, 1, t); | |
898 | z1 = -20; | |
899 | x1 = (fmd3->ConeR(nz+z1)); | |
900 | t = new TGeoCombiTrans("F3SB2",x1,0,-z1,r1); | |
901 | support->AddNode(boltVolume, 2, t); | |
902 | boltShape->SetTitle("FMD3 steering bolt"); | |
903 | boltVolume->SetTitle("FMD3 steering bolt"); | |
904 | ||
905 | // Cooling plates | |
906 | TGeoTrd1* plateShape = new TGeoTrd1(2, 8, 0.1, (conel-2-2)/2-.1); | |
907 | TGeoVolume* plateVolume = new TGeoVolume("F3CO", plateShape, fAl); | |
908 | plateShape->SetName("F3C0"); | |
909 | plateShape->SetTitle("FMD3 cooling plate"); | |
910 | plateVolume->SetTitle("FMD3 cooling plate"); | |
911 | ||
912 | // Shape for carbon half-cone | |
913 | TGeoConeSeg* innerCone = new TGeoConeSeg("F3SC_inner", conel/2, | |
914 | noser2-conet, noser2, | |
915 | backr2-conet, backr2, 0., 180.); | |
916 | innerCone->SetTitle("FMD3 cone inner"); | |
917 | TGeoTrd1* coneHole = new TGeoTrd1("F3SC_hole",2,8,conet*3, | |
918 | (conel-2-2)/2); | |
919 | coneHole->SetTitle("FMD3 cone hole"); | |
920 | Double_t holeAng = TMath::ATan2(backr2 - noser2, conel); | |
921 | Double_t holeX = ((conel-2) / 2 * TMath::Sin(holeAng) + | |
922 | conet * TMath::Cos(holeAng) + | |
923 | noser2); | |
924 | TGeoRotation* holeRot = new TGeoRotation(); | |
925 | holeRot->SetName("FMD3 cone hole rotation"); | |
926 | holeRot->RotateZ(90); | |
927 | holeRot->RotateY(holeAng*180./TMath::Pi()); | |
928 | TGeoCombiTrans* holeTrans = new TGeoCombiTrans(holeX, 0, -2, holeRot); | |
929 | holeRot->SetName("FMD3 cone hole"); | |
930 | ||
931 | // Build-up the composite shape for the cone, and add cooling plates | |
932 | // at the same time. | |
933 | TString coneExp("F3SC_inner-("); | |
934 | for (int i = 0; i < 4; i++) { | |
935 | Double_t thisAng = 360. / 8 * (i + .5); | |
936 | TGeoCombiTrans* thisTrans = new TGeoCombiTrans(*holeTrans); | |
937 | thisTrans->RotateZ(thisAng); | |
938 | thisTrans->SetName(Form("F3SC_rot%d", i)); | |
939 | thisTrans->RegisterYourself(); | |
940 | coneExp.Append(Form("F3SC_hole:F3SC_rot%d+", i)); | |
941 | ||
942 | const Double_t* tt = thisTrans->GetTranslation(); | |
943 | Double_t x = tt[0]+1*TMath::Cos(thisAng*TMath::Pi()/180); | |
944 | Double_t y = tt[1]+1*TMath::Sin(thisAng*TMath::Pi()/180); | |
945 | TGeoCombiTrans* plateTrans = new TGeoCombiTrans(x,y,tt[2]-1+nlen+conel/2, | |
946 | thisTrans->GetRotation()); | |
947 | support->AddNode(plateVolume, i, plateTrans); | |
948 | } | |
949 | // Remove bolt holes | |
950 | coneExp.Append("F3SB:F3SB1+F3SB:F3SB2)"); | |
951 | ||
952 | // Finalize the half-cone shape and add volume | |
953 | TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneExp.Data()); | |
954 | TGeoVolume* coneVolume = new TGeoVolume("F3SC", coneShape, fC); | |
955 | coneShape->SetName("F3SC"); | |
956 | coneShape->SetTitle("FMD3 cone"); | |
957 | coneVolume->SetTitle("FMD3 cone"); | |
958 | support->AddNode(coneVolume,1,new TGeoTranslation(0,0,nlen+conel/2)); | |
959 | ||
960 | // The flanges | |
961 | TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2, | |
962 | fmd3->GetBeamWidth() / 2, | |
963 | backl / 2); | |
964 | TGeoVolume* flangeVolume = new TGeoVolume(Form(fgkFlangeName, fmd3->GetId()), | |
965 | flangeShape, fC); | |
966 | flangeShape->SetName(Form(fgkFlangeName, fmd3->GetId())); | |
967 | flangeShape->SetTitle("FMD3 flange"); | |
968 | flangeVolume->SetTitle("FMD3 flange"); | |
969 | ||
970 | Int_t n = fmd3->GetNFlange(); | |
971 | Double_t r = backr2 + (flanger - backr2) / 2; | |
972 | for (Int_t i = 0; i < n/2; i++) { | |
973 | Double_t phi = 360. / n * i + 180. / n; | |
974 | Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi); | |
975 | Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi); | |
976 | TGeoRotation* rot = new TGeoRotation; | |
977 | rot->RotateZ(phi); | |
978 | TGeoMatrix* matrix = new TGeoCombiTrans(x, y, nlen+conel-backl/2, rot); | |
979 | matrix->SetName(Form("FMD3_flange_%02d", i)); | |
980 | matrix->SetTitle(Form("FMD3_flange_%2d", i)); | |
981 | support->AddNode(flangeVolume, i, matrix); | |
982 | } | |
983 | ||
984 | // Place support volumes in half-detector volumes | |
985 | z = fmd3->GetInnerZ(); | |
986 | z1 = z-nz; | |
987 | fmd3TopVolume->AddNode(support, 1, new TGeoTranslation(0,0,z1)); | |
988 | r1 = new TGeoRotation(); | |
989 | r1->RotateZ(180); | |
990 | t = new TGeoCombiTrans(0,0,z1,r1); | |
991 | fmd3BotVolume->AddNode(support, 2, t); | |
992 | ||
993 | TGeoRotation* rot = new TGeoRotation("FMD3 rotatation"); | |
994 | rot->RotateY(180); | |
995 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); | |
996 | TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot); | |
997 | AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", | |
998 | fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z)); | |
999 | top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix); | |
1000 | top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix); | |
1001 | ||
1002 | return 0; | |
1003 | } | |
1004 | ||
1005 | //____________________________________________________________________ | |
1006 | void | |
1007 | AliFMDGeometryBuilder::Exec(Option_t*) | |
1008 | { | |
1009 | // Setup up the FMD geometry. | |
1010 | AliFMDDebug(1, ("\tGeometry options: %s", | |
1011 | (fDetailed ? "divided into strips" : "one volume"))); | |
1012 | if (!gGeoManager) { | |
1013 | AliFatal("No TGeoManager defined"); | |
1014 | return; | |
1015 | } | |
1016 | ||
1017 | fSi = gGeoManager->GetMedium("FMD_Si$"); | |
1018 | fC = gGeoManager->GetMedium("FMD_Carbon$"); | |
1019 | fAl = gGeoManager->GetMedium("FMD_Aluminum$"); | |
1020 | fChip = gGeoManager->GetMedium("FMD_Si Chip$"); | |
1021 | fAir = gGeoManager->GetMedium("FMD_Air$"); | |
1022 | fPCB = gGeoManager->GetMedium("FMD_PCB$"); | |
1023 | fPlastic = gGeoManager->GetMedium("FMD_Plastic$"); | |
1024 | fCopper = gGeoManager->GetMedium("FMD_Copper$"); | |
1025 | fSteel = gGeoManager->GetMedium("FMD_Steel$"); | |
1026 | ||
1027 | if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) { | |
1028 | AliError("Failed to get some or all tracking mediums"); | |
1029 | return; | |
1030 | } | |
1031 | AliFMDGeometry* fmd = AliFMDGeometry::Instance(); | |
1032 | AliFMDRing* inner = fmd->GetInner(); | |
1033 | AliFMDRing* outer = fmd->GetOuter(); | |
1034 | RingGeometry(inner); | |
1035 | RingGeometry(outer); | |
1036 | TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, | |
1037 | inner->GetId())); | |
1038 | TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, | |
1039 | inner->GetId())); | |
1040 | TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, | |
1041 | outer->GetId())); | |
1042 | TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, | |
1043 | outer->GetId())); | |
1044 | ||
1045 | FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot); | |
1046 | FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot); | |
1047 | FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot); | |
1048 | #ifndef USE_PRE_MOVE | |
1049 | fmd->SetSectorOff(fSectorOff); | |
1050 | fmd->SetModuleOff(fModuleOff); | |
1051 | fmd->SetRingOff(fRingOff); | |
1052 | fmd->SetDetectorOff(fDetectorOff); | |
1053 | fmd->SetActive(fActiveId.fArray, fActiveId.fN); | |
1054 | #endif | |
1055 | // fmd->ExtractGeomInfo(); | |
1056 | ||
1057 | } | |
1058 | ||
1059 | ||
1060 | //____________________________________________________________________ | |
1061 | // | |
1062 | // EOF | |
1063 | // |