]>
Commit | Line | Data |
---|---|---|
1a1fdef7 | 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 | ||
16 | /* $Id$ */ | |
17 | ||
18 | //____________________________________________________________________ | |
19 | // | |
20 | // Forward Multiplicity Detector based on Silicon wafers. This class | |
21 | // contains the base procedures for the Forward Multiplicity detector | |
22 | // Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of | |
23 | // which has 1 or 2 rings of silicon sensors. | |
24 | // | |
25 | // This is the base class for all FMD manager classes. | |
26 | // | |
27 | // The actual code is done by various separate classes. Below is | |
28 | // diagram showing the relationship between the various FMD classes | |
29 | // that handles the simulation | |
30 | // | |
31 | // +--------+ 1 +-----------------+ | |
32 | // | AliFMD |<>-----| AliFMDSimulator | | |
33 | // +--------+ +-----------------+ | |
34 | // ^ | |
35 | // | | |
36 | // +-------------+-------------+ | |
37 | // | | | |
38 | // +--------------------+ +-------------------+ | |
39 | // | AliFMDGeoSimulator | | AliFMDG3Simulator | | |
40 | // +--------------------+ +---------+---------+ | |
41 | // | |
42 | // | |
43 | // * AliFMD | |
44 | // This defines the interface for the various parts of AliROOT that | |
45 | // uses the FMD, like AliFMDSimulator, AliFMDDigitizer, | |
46 | // AliFMDReconstructor, and so on. | |
47 | // | |
48 | // * AliFMDSimulator | |
49 | // This is the base class for the FMD simulation tasks. The | |
50 | // simulator tasks are responsible to implment the geoemtry, and | |
51 | // process hits. | |
52 | // | |
53 | // * AliFMDGeoSimulator | |
54 | // This is a concrete implementation of the AliFMDSimulator that | |
55 | // uses the TGeo classes directly only. This defines the active | |
56 | // volume as an ONLY XTRU shape with a divided MANY TUBS shape | |
57 | // inside to implement the particular shape of the silicon | |
58 | // sensors. | |
59 | // | |
60 | // * AliFMDG3Simulator | |
61 | // This is a concrete implementation of the AliFMDSimulator that | |
62 | // uses the TVirtualMC interface with GEANT 3.21-like messages. | |
63 | // This implements the active volume as a divided TUBS shape. Hits | |
64 | // in the corners should be cut away at run time (but currently | |
65 | // isn't). | |
66 | // | |
ede5852a | 67 | #include <math.h> |
1a1fdef7 | 68 | #include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_H |
69 | #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H | |
70 | #include "AliFMDDetector.h" // ALIFMDDETECTOR_H | |
71 | #include "AliFMDRing.h" // ALIFMDRING_H | |
72 | #include "AliFMD1.h" // ALIFMD1_H | |
73 | #include "AliFMD2.h" // ALIFMD2_H | |
74 | #include "AliFMD3.h" // ALIFMD3_H | |
75 | #include "AliFMD.h" // ALIFMD_H | |
76 | #include <AliLog.h> // ALILOG_H | |
77 | #include <TVector2.h> // ROOT_TVector2 | |
78 | #include <TVirtualMC.h> // ROOT_TVirtualMC | |
79 | #include <TArrayI.h> // ROOT_TArrayI | |
80 | ||
81 | //==================================================================== | |
82 | ClassImp(AliFMDG3Simulator) | |
83 | #if 0 | |
84 | ; // This is here to keep Emacs for indenting the next line | |
85 | #endif | |
86 | ||
87 | //____________________________________________________________________ | |
88 | AliFMDG3Simulator::AliFMDG3Simulator() | |
89 | { | |
90 | // Default constructor | |
91 | fSectorOff = 1; | |
92 | fModuleOff = 3; | |
93 | fRingOff = 4; | |
94 | fDetectorOff = 5; | |
95 | } | |
96 | ||
97 | //____________________________________________________________________ | |
98 | AliFMDG3Simulator::AliFMDG3Simulator(AliFMD* fmd, Bool_t detailed) | |
99 | : AliFMDSimulator(fmd, detailed) | |
100 | { | |
101 | // Normal constructor | |
102 | // | |
103 | // Parameters: | |
104 | // | |
105 | // fmd Pointer to AliFMD object | |
106 | // detailed Whether to make a detailed simulation or not | |
107 | // | |
108 | fSectorOff = 1; | |
109 | fModuleOff = 3; | |
110 | fRingOff = 4; | |
111 | fDetectorOff = 5; | |
112 | } | |
113 | ||
114 | //____________________________________________________________________ | |
115 | Bool_t | |
116 | AliFMDG3Simulator::RingGeometry(AliFMDRing* r) | |
117 | { | |
118 | // Setup the geometry of a ring. The defined TGeoVolume is | |
119 | // returned, and should be used when setting up the rest of the | |
120 | // volumes. | |
121 | // | |
122 | // Parameters: | |
123 | // | |
124 | // r Pointer to ring geometry object | |
125 | // | |
126 | // Returns: | |
127 | // true on success | |
128 | // | |
129 | if (!r) { | |
130 | AliError("Didn't get a ring object"); | |
131 | return kFALSE; | |
132 | } | |
133 | Char_t id = r->GetId(); | |
134 | Double_t siThick = r->GetSiThickness(); | |
135 | // const Int_t nv = r->GetNVerticies(); | |
136 | TVector2* a = r->GetVertex(5); | |
137 | TVector2* b = r->GetVertex(3); | |
138 | TVector2* c = r->GetVertex(4); | |
139 | Double_t theta = r->GetTheta(); | |
140 | Double_t off = (TMath::Tan(TMath::Pi() * theta / 180) | |
141 | * r->GetBondingWidth()); | |
142 | Double_t rmax = b->Mod(); | |
143 | Double_t rmin = r->GetLowR(); | |
144 | Double_t pcbThick = r->GetPrintboardThickness(); | |
145 | Double_t modSpace = r->GetModuleSpacing(); | |
146 | Double_t legr = r->GetLegRadius(); | |
147 | Double_t legl = r->GetLegLength(); | |
148 | Double_t legoff = r->GetLegOffset(); | |
149 | Int_t ns = r->GetNStrips(); | |
150 | Double_t stripoff = a->Mod(); | |
151 | Double_t dstrip = (rmax - stripoff) / ns; | |
152 | Double_t par[10]; | |
153 | TString name; | |
154 | TString name2; | |
155 | TVirtualMC* mc = TVirtualMC::GetMC(); | |
156 | ||
157 | Int_t siId = fFMD->GetIdtmed()->At(kSiId); | |
158 | Int_t airId = fFMD->GetIdtmed()->At(kAirId); | |
159 | Int_t pcbId = fFMD->GetIdtmed()->At(kPcbId); | |
160 | Int_t plaId = fFMD->GetIdtmed()->At(kPlasticId); | |
161 | ||
162 | // Virtual volume shape to divide - This volume is only defined if | |
163 | // the geometry is set to be detailed. | |
164 | // Ring mother volume | |
165 | par[0] = rmin; | |
166 | par[1] = rmax; | |
167 | par[2] = (siThick + pcbThick + legl + modSpace) / 2; | |
168 | name = Form(fgkRingName, id); | |
169 | mc->Gsvolu(name.Data(), "TUBE", airId, par, 3); | |
170 | ||
171 | par[0] = rmin; | |
172 | par[1] = rmax; | |
173 | par[2] = siThick / 2; | |
174 | par[3] = -theta; | |
175 | par[4] = theta; | |
176 | name = Form(fgkActiveName, id); | |
177 | mc->Gsvolu(name.Data(), "TUBS", (fDetailed ? airId : siId), par, 5); | |
178 | ||
179 | Int_t sid = -1; | |
180 | if (fDetailed) { | |
181 | name2 = name; | |
182 | name = Form(fgkSectorName, id); | |
183 | mc->Gsdvn2(name.Data(), name2.Data(), 2, 2, -theta, airId); | |
184 | ||
185 | name2 = name; | |
186 | name = Form(fgkStripName, id); | |
187 | mc->Gsdvt2(name.Data(), name2.Data(), dstrip, 1, stripoff, siId, ns); | |
188 | sid = mc->VolId(name.Data()); | |
189 | AliDebug(10, Form("Got volume id %d for volume %s", sid, name.Data())); | |
190 | } | |
191 | ||
192 | switch (id) { | |
193 | case 'i': | |
194 | case 'I': | |
195 | fInnerId = sid; | |
196 | // fInnerV = moduleVolume->GetNumber(); | |
197 | break; | |
198 | case 'o': | |
199 | case 'O': | |
200 | fOuterId = sid; | |
201 | // fOuterV = moduleVolume->GetNumber(); | |
202 | break; | |
203 | } | |
204 | ||
205 | // Shape of Printed circuit Board | |
206 | // Top | |
207 | par[0] = c->Y() - off; | |
208 | par[1] = b->Y() - off; | |
209 | par[2] = pcbThick / 2; | |
210 | par[3] = (b->X() - c->X()) / 2; | |
211 | par[4] = off; | |
212 | name = Form(fgkPCBName, id, 'T'); | |
213 | mc->Gsvolu(name.Data(), "TRD1", pcbId, par, 4); | |
214 | // Bottom | |
215 | par[0] = a->Y() - off; | |
216 | par[1] = c->Y() - off; | |
217 | par[3] = (c->X() - a->X()) / 2; | |
218 | name = Form(fgkPCBName, id, 'B'); | |
219 | mc->Gsvolu(name.Data(), "TRD1", pcbId, par, 4); | |
220 | ||
221 | // Short leg volume | |
222 | par[0] = legr - .1; | |
223 | par[1] = legr; | |
224 | par[2] = legl / 2; | |
225 | name = Form(fgkShortLegName, id); | |
226 | mc->Gsvolu(name.Data(), "TUBE", plaId, par, 3); | |
227 | ||
228 | // Long leg volume | |
229 | par[2] += modSpace / 2; | |
230 | name = Form(fgkLongLegName, id); | |
231 | mc->Gsvolu(name.Data(), "TUBE", plaId, par, 3); | |
232 | ||
233 | // Back container volume | |
234 | par[0] = rmin; | |
235 | par[1] = rmax; | |
236 | par[2] = (siThick + pcbThick + legl) / 2; | |
237 | par[3] = -theta; | |
238 | par[4] = +theta; | |
239 | name = Form(fgkBackVName, id); | |
240 | mc->Gsvolu(name.Data(), "TUBS", airId, par, 5); | |
241 | ||
242 | Double_t x = 0; | |
243 | Double_t y = 0; | |
244 | Double_t z = - par[2] + siThick / 2; | |
245 | name2 = name; | |
246 | name = Form(fgkActiveName, id); | |
247 | mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY"); | |
248 | ||
249 | Double_t pbTopL = (b->X() - c->X()); | |
250 | Double_t pbBotL = (c->X() - a->X()); | |
251 | Int_t pbRot; | |
252 | mc->Matrix(pbRot, 90, 90, 0, 90, 90, 0); | |
253 | ||
254 | x = rmin + pbBotL + pbTopL / 2; | |
255 | z += siThick / 2 + pcbThick / 2; | |
256 | name = Form(fgkPCBName, id, 'T'); | |
257 | mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, pbRot, "ONLY"); | |
258 | ||
259 | x = rmin + pbBotL / 2; | |
260 | name = Form(fgkPCBName, id, 'B'); | |
261 | mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, pbRot, "ONLY"); | |
262 | ||
263 | x = a->X() + legoff + legr; | |
264 | y = 0; | |
265 | z += pcbThick / 2 + legl / 2; | |
266 | name = Form(fgkShortLegName, id); | |
267 | mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY"); | |
268 | ||
269 | x = c->X(); | |
270 | y = c->Y() - legoff - legr - off; | |
271 | mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY"); | |
272 | ||
273 | y = -y; | |
274 | mc->Gspos(name.Data(), 2, name2.Data(), x, y, z, 0, "ONLY"); | |
275 | ||
276 | ||
277 | // Front container volume | |
278 | par[2] += modSpace / 2; | |
279 | name = Form(fgkFrontVName, id); | |
280 | mc->Gsvolu(name.Data(), "TUBS", airId, par, 5); | |
281 | ||
282 | x = 0; | |
283 | y = 0; | |
284 | z = - par[2] + siThick / 2; | |
285 | name2 = name; | |
286 | name = Form(fgkActiveName, id); | |
287 | mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY"); | |
288 | ||
289 | pbTopL = (b->X() - c->X()); | |
290 | pbBotL = (c->X() - a->X()); | |
291 | x = rmin + pbBotL + pbTopL / 2; | |
292 | z += siThick / 2 + pcbThick / 2; | |
293 | name = Form(fgkPCBName, id, 'T'); | |
294 | mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, pbRot, "ONLY"); | |
295 | ||
296 | x = rmin + pbBotL / 2; | |
297 | name = Form(fgkPCBName, id, 'B'); | |
298 | mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, pbRot, "ONLY"); | |
299 | ||
300 | x = a->X() + legoff + legr; | |
301 | y = 0; | |
302 | z += pcbThick / 2 + legl / 2 + modSpace / 2; | |
303 | name = Form(fgkLongLegName, id); | |
304 | mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY"); | |
305 | ||
306 | x = c->X(); | |
307 | y = c->Y() - legoff - legr - off; | |
308 | mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY"); | |
309 | ||
310 | y = -y; | |
311 | mc->Gspos(name.Data(), 2, name2.Data(), x, y, z, 0, "ONLY"); | |
312 | ||
313 | ||
314 | ||
315 | Int_t nmod = r->GetNModules(); | |
316 | name2 = Form(fgkRingName, id); | |
317 | AliDebug(10, Form("making %d modules in ring %c", nmod, id)); | |
318 | for (Int_t i = 0; i < nmod; i++) { | |
319 | Double_t th = (i + .5) * 2 * theta; | |
320 | Bool_t isFront = (i % 2 == 0); | |
321 | name = (isFront ? Form(fgkFrontVName,id) : | |
322 | Form(fgkBackVName,id)); | |
323 | Double_t z = (isFront ? 0 : modSpace) / 2; | |
324 | Int_t rot; | |
325 | mc->Matrix(rot, 90, th, 90, fmod(90 + th, 360), 0, 0); | |
326 | mc->Gspos(name.Data(), i, name2.Data(), 0, 0, z, rot, "ONLY"); | |
327 | } | |
328 | ||
329 | return kTRUE; | |
330 | } | |
331 | ||
332 | //____________________________________________________________________ | |
333 | Bool_t | |
334 | AliFMDG3Simulator::DetectorGeometry(AliFMDDetector* d, Double_t zmother) | |
335 | { | |
336 | // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries. | |
337 | // This includes putting the Honeycomb support plates and the rings | |
338 | // into the mother volumes. | |
339 | // | |
340 | // Parameeters: | |
341 | // d The detector geometry to use | |
342 | // zmother The midpoint in global coordinates of detector vol. | |
343 | // | |
344 | // Returns: | |
345 | // true on success | |
346 | // | |
347 | if (!d) return kFALSE; | |
348 | ||
349 | TString name; | |
350 | TString name2; | |
351 | TVirtualMC* mc = TVirtualMC::GetMC(); | |
352 | ||
353 | // Loop over the defined rings | |
354 | for (int i = 0; i < 2; i++) { | |
355 | AliFMDRing* r = 0; | |
356 | Double_t lowr = 0; | |
357 | Double_t highr = 0; | |
358 | Double_t rz = 0; | |
359 | switch (i) { | |
360 | case 0: | |
361 | r = d->GetInner(); | |
362 | lowr = d->GetInnerHoneyLowR(); | |
363 | highr = d->GetInnerHoneyHighR(); | |
364 | rz = d->GetInnerZ(); | |
365 | break; | |
366 | case 1: | |
367 | r = d->GetOuter(); | |
368 | lowr = d->GetOuterHoneyLowR(); | |
369 | highr = d->GetOuterHoneyHighR(); | |
370 | rz = d->GetOuterZ(); | |
371 | break; | |
372 | } | |
373 | if (!r) continue; | |
374 | Char_t c = r->GetId(); | |
375 | Int_t id = d->GetId(); | |
376 | Int_t airId = (fFMD->GetIdtmed()->At(kAirId)); | |
377 | Int_t alId = (fFMD->GetIdtmed()->At(kAlId)); | |
378 | Double_t hcThick = d->GetHoneycombThickness(); | |
379 | Double_t alThick = d->GetAlThickness(); | |
380 | Double_t par[10]; | |
381 | Double_t z; | |
382 | // Place ring in mother volume | |
383 | if (zmother > 0) z = rz - zmother + r->GetRingDepth() / 2; | |
384 | else z = zmother - rz + r->GetRingDepth() / 2; | |
385 | name = Form(fgkRingName, c); | |
386 | name2 = d->GetName(); | |
387 | mc->Gspos(name.Data(), Int_t(c), name2.Data(), 0, 0, z, 0, "ONLY"); | |
388 | ||
389 | // Place Top Honeycomb in mother volume | |
390 | z += + r->GetRingDepth() / 2 + hcThick / 2; | |
391 | // Top of Honeycomb | |
392 | par[0] = lowr; | |
393 | par[1] = highr; | |
394 | par[2] = hcThick / 2; | |
395 | par[3] = 0; | |
396 | par[4] = 180; | |
397 | name = Form(fgkTopHCName, id, c); | |
398 | mc->Gsvolu(name.Data(), "TUBS", alId, par, 5); | |
399 | mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, z, 0, "ONLY"); | |
400 | ||
401 | par[0] += alThick; | |
402 | par[1] -= alThick; | |
403 | par[2] -= alThick / 2; | |
404 | name2 = name; | |
405 | name = Form(fgkTopIHCName, id, c); | |
406 | mc->Gsvolu(name.Data(), "TUBS", airId, par, 5); | |
407 | mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, 0, 0, "ONLY"); | |
408 | ||
409 | // Bot of Honeycomb | |
410 | par[0] = lowr; | |
411 | par[1] = highr; | |
412 | par[2] = hcThick / 2; | |
413 | par[3] = 180; | |
414 | par[4] = 360; | |
415 | name2 = d->GetName(); | |
416 | name = Form(fgkBotHCName, id, c); | |
417 | mc->Gsvolu(name.Data(), "TUBS", alId, par, 5); | |
418 | mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, z, 0, "ONLY"); | |
419 | ||
420 | par[0] += alThick; | |
421 | par[1] -= alThick; | |
422 | par[2] -= alThick / 2; | |
423 | name2 = name; | |
424 | name = Form(fgkBotIHCName, id, c); | |
425 | mc->Gsvolu(name.Data(), "TUBS", airId, par, 5); | |
426 | mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, 0, 0, "ONLY"); | |
427 | } | |
428 | return kTRUE; | |
429 | } | |
430 | ||
431 | //____________________________________________________________________ | |
432 | Bool_t | |
433 | AliFMDG3Simulator::FMD1Geometry(AliFMD1* fmd1) | |
434 | { | |
435 | // Setup the FMD1 geometry. The FMD1 only has one ring, and no | |
436 | // special support as it is at the momement. | |
437 | // | |
438 | // See also AliFMDG3Simulator::DetectorGeometry | |
439 | // | |
440 | if (!fmd1) return kFALSE; | |
441 | Double_t rmin = fmd1->GetInner()->GetLowR(); | |
442 | Double_t rmax = fmd1->GetInnerHoneyHighR(); | |
443 | Double_t hcThick = fmd1->GetHoneycombThickness(); | |
444 | Double_t w = fmd1->GetInner()->GetRingDepth() + hcThick; | |
445 | Double_t z = fmd1->GetInnerZ() + w / 2; | |
446 | TVirtualMC* mc = TVirtualMC::GetMC(); | |
447 | Int_t airId = (fFMD->GetIdtmed()->At(kAirId)); | |
448 | ||
449 | Double_t par[3]; | |
450 | par[0] = rmin; | |
451 | par[1] = rmax; | |
452 | par[2] = w / 2; | |
453 | mc->Gsvolu(fmd1->GetName(), "TUBE", airId, par, 3); | |
454 | mc->Gspos(fmd1->GetName(), fmd1->GetId(), "ALIC", 0, 0, z, 0, "ONLY"); | |
455 | ||
456 | return DetectorGeometry(fmd1, z); | |
457 | } | |
458 | ||
459 | //____________________________________________________________________ | |
460 | Bool_t | |
461 | AliFMDG3Simulator::FMD2Geometry(AliFMD2* fmd2) | |
462 | { | |
463 | // Setup the FMD2 geometry. The FMD2 has no | |
464 | // special support as it is at the momement. | |
465 | // | |
466 | // See also AliFMDG3Simulator::DetectorGeometry | |
467 | // | |
468 | if (!fmd2) return kFALSE; | |
469 | Double_t rmin = fmd2->GetInner()->GetLowR(); | |
470 | Double_t rmax = fmd2->GetOuterHoneyHighR(); | |
471 | Double_t hcThick = fmd2->GetHoneycombThickness(); | |
472 | Double_t ow = fmd2->GetInner()->GetRingDepth(); | |
473 | Double_t iz = fmd2->GetInnerZ(); | |
474 | Double_t oz = fmd2->GetOuterZ(); | |
475 | Double_t w = TMath::Abs(oz - iz) + ow + hcThick; | |
476 | Double_t z = oz + w / 2; | |
477 | ||
478 | TVirtualMC* mc = TVirtualMC::GetMC(); | |
479 | Int_t airId = (fFMD->GetIdtmed()->At(kAirId)); | |
480 | ||
481 | Double_t par[3]; | |
482 | par[0] = rmin; | |
483 | par[1] = rmax; | |
484 | par[2] = w / 2; | |
485 | mc->Gsvolu(fmd2->GetName(), "TUBE", airId, par, 3); | |
486 | mc->Gspos(fmd2->GetName(), fmd2->GetId(), "ALIC", 0, 0, z, 0, "ONLY"); | |
487 | ||
488 | return DetectorGeometry(fmd2, z); | |
489 | } | |
490 | ||
491 | //____________________________________________________________________ | |
492 | Bool_t | |
493 | AliFMDG3Simulator::FMD3Geometry(AliFMD3* fmd3) | |
494 | { | |
495 | // Setup the FMD3 geometry. The FMD2 has a rather elaborate support | |
496 | // structure, as the support will also support the vacuum | |
497 | // beam-pipe. | |
498 | // | |
499 | // See also AliFMDG3Simulator::DetectorGeometry | |
500 | // | |
501 | if (!fmd3) return kFALSE; | |
502 | Double_t nlen = fmd3->GetNoseLength(); | |
503 | Double_t nz = fmd3->GetNoseZ(); | |
504 | Double_t noser1 = fmd3->GetNoseLowR(); | |
505 | Double_t noser2 = fmd3->GetNoseHighR(); | |
506 | Double_t conel = fmd3->GetConeLength(); | |
507 | Double_t backl = fmd3->GetBackLength(); | |
508 | Double_t backr1 = fmd3->GetBackLowR(); | |
509 | Double_t backr2 = fmd3->GetBackHighR(); | |
510 | Double_t zdist = conel - backl - nlen; | |
511 | Double_t tdist = backr2 - noser2; | |
512 | Double_t beaml = TMath::Sqrt(zdist * zdist + tdist * tdist); | |
513 | Double_t theta = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi(); | |
514 | Double_t innerZ = fmd3->GetInnerZ(); | |
515 | Double_t innerZh = (innerZ - fmd3->GetInner()->GetRingDepth() | |
516 | - fmd3->GetHoneycombThickness()); | |
517 | Double_t outerZ = fmd3->GetOuterZ(); | |
518 | Double_t outerZh = (outerZ - fmd3->GetOuter()->GetRingDepth() | |
519 | - fmd3->GetHoneycombThickness()); | |
520 | Double_t innerr1 = fmd3->GetInner()->GetLowR(); | |
521 | // Double_t innerr2 = fmd3->GetInner()->GetHighR(); | |
522 | Double_t outerr1 = fmd3->GetOuter()->GetLowR(); | |
523 | // Double_t outerr2 = fmd3->GetOuter()->GetHighR(); | |
524 | Double_t flanger = fmd3->GetFlangeR(); | |
525 | Double_t minZ = TMath::Min(nz - conel, outerZh); | |
526 | Double_t z = fmd3->GetZ(); | |
527 | Double_t zi; | |
528 | TVirtualMC* mc = TVirtualMC::GetMC(); | |
529 | Int_t airId = (fFMD->GetIdtmed()->At(kAirId)); | |
530 | Int_t cId = (fFMD->GetIdtmed()->At(kCarbonId)); | |
531 | Double_t par[27]; | |
532 | ||
533 | // FMD3 volume | |
534 | par[0] = 0; | |
535 | par[1] = 360; | |
536 | par[2] = 8; | |
537 | // First | |
538 | par[3] = z - nz; | |
539 | par[4] = noser1; | |
540 | par[5] = noser2; | |
541 | // Second | |
542 | par[6] = z - (nz - nlen); | |
543 | par[7] = noser1; | |
544 | par[8] = fmd3->ConeR(z - par[6])+.15; | |
545 | // Third | |
546 | par[9] = z - innerZ; | |
547 | par[10] = innerr1; | |
548 | par[11] = fmd3->ConeR(z - par[9])+.15; | |
549 | // Fourth | |
550 | par[12] = z - innerZh; | |
551 | par[13] = innerr1; | |
552 | par[14] = fmd3->ConeR(z - par[12])+.15; | |
553 | // Fifth | |
554 | par[15] = par[12]; | |
555 | par[16] = outerr1; | |
556 | par[17] = fmd3->ConeR(z - par[15])+.15; | |
557 | // Sixth | |
558 | par[18] = z - nz + zdist + nlen; | |
559 | par[19] = outerr1; | |
560 | par[20] = fmd3->ConeR(z - par[18])+.15; | |
561 | // Seventh | |
562 | par[21] = z - nz + nlen + zdist; | |
563 | par[22] = outerr1; | |
564 | par[23] = flanger+1.5; | |
565 | // Eight | |
566 | par[24] = z - minZ; | |
567 | par[25] = outerr1; | |
568 | par[26] = flanger+1.5; | |
569 | mc->Gsvolu(fmd3->GetName(), "PCON", airId, par, 27); | |
570 | ||
571 | Int_t id; | |
572 | mc->Matrix(id, 270, 180, 90, 90, 180, 0); | |
573 | mc->Gspos(fmd3->GetName(), fmd3->GetId(), "ALIC", 0, 0, z, id, "ONLY"); | |
574 | ||
575 | // Nose volume | |
576 | par[0] = noser1; | |
577 | par[1] = noser2; | |
578 | par[2] = nlen / 2; | |
579 | zi = z - nz + nlen / 2; | |
580 | mc->Gsvolu(fgkNoseName, "TUBE", cId, par, 3); | |
581 | mc->Gspos(fgkNoseName, 0, fmd3->GetName(), 0, 0, zi, 0, "MANY"); | |
582 | ||
583 | // Back | |
584 | par[0] = backr1; | |
585 | par[1] = backr2; | |
586 | par[2] = backl / 2; | |
587 | zi = z - nz + conel - backl / 2; | |
588 | mc->Gsvolu(fgkBackName, "TUBE", cId, par, 3); | |
589 | mc->Gspos(fgkBackName, 0, fmd3->GetName(), 0, 0, zi, 0, "ONLY"); | |
590 | ||
591 | Int_t n; | |
592 | Double_t r; | |
593 | // The flanges | |
594 | par[0] = (flanger - backr2) / 2; | |
595 | par[1] = fmd3->GetBeamWidth() / 2; | |
596 | par[2] = backl / 2; | |
597 | mc->Gsvolu(fgkFlangeName, "BOX", cId, par, 3); | |
598 | n = fmd3->GetNFlange(); | |
599 | r = backr2 + (flanger - backr2) / 2; | |
600 | for (Int_t i = 0; i < n; i++) { | |
601 | Double_t phi = 360. / n * i + 180. / n; | |
602 | Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi); | |
603 | Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi); | |
604 | Int_t id; | |
605 | mc->Matrix(id, 90, phi, 90, 90 + phi, 0, 0); | |
606 | mc->Gspos(fgkFlangeName, i, fmd3->GetName(), x, y, zi, id, "ONLY"); | |
607 | } | |
608 | ||
609 | // The Beams | |
610 | par[0] = fmd3->GetBeamThickness() / 2; | |
611 | par[1] = fmd3->GetBeamWidth() / 2; | |
612 | par[2] = beaml / 2; | |
613 | mc->Gsvolu(fgkBeamName, "BOX", cId, par, 3); | |
614 | n = fmd3->GetNBeam(); | |
615 | r = noser2 + tdist / 2; | |
616 | zi = z - nz + nlen + zdist / 2; | |
617 | for (Int_t i = 0; i < n; i++) { | |
618 | Double_t phi = 360. / n * i; | |
619 | Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi); | |
620 | Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi); | |
621 | Int_t id; | |
622 | (void)theta; | |
623 | mc->Matrix(id, 90-theta, phi, 90, 90 + phi, 360 - theta, phi); | |
624 | mc->Gspos(fgkBeamName, i, fmd3->GetName(), x, y, zi, id, "MANY"); | |
625 | } | |
626 | ||
627 | return DetectorGeometry(fmd3, z); | |
628 | } | |
629 | ||
630 | //____________________________________________________________________ | |
631 | void | |
632 | AliFMDG3Simulator::DefineGeometry() | |
633 | { | |
634 | // Setup up the FMD geometry. | |
635 | AliDebug(10, "Setting up volume"); | |
636 | ||
637 | AliFMDGeometry* fmd = AliFMDGeometry::Instance(); | |
638 | if (!RingGeometry(fmd->GetInner())) { | |
639 | AliError("Failed to create inner ring volume"); | |
640 | return; | |
641 | } | |
642 | if (!RingGeometry(fmd->GetOuter())) { | |
643 | AliError("Failed to create outer ring volume"); | |
644 | return; | |
645 | } | |
646 | FMD1Geometry(fmd->GetFMD1()); | |
647 | FMD2Geometry(fmd->GetFMD2()); | |
648 | FMD3Geometry(fmd->GetFMD3()); | |
649 | } | |
650 | ||
651 | //____________________________________________________________________ | |
652 | // | |
653 | // EOF | |
654 | // |