1 /**************************************************************************
2 * Copyright(c) 2007-2009, 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 // This class Defines the Geometry for the ITS services and support cones
17 // outside of the ceneteral volume (except for the Ceneteral support
18 // cylinders. Other classes define the rest of the ITS. Specificaly the ITS
19 // The SSD support cone, SSD Support centeral cylinder, SDD support cone,
20 // The SDD cupport centeral cylinder, the SPD Thermal Sheald, The supports
21 // and cable trays on both the RB26 (muon dump) and RB24 sides, and all of
22 // the cabling from the ladders/stave ends out past the TPC.
27 // General Root includes
28 #include <Riostream.h>
32 #include <TPolyLine.h>
33 #include <TPolyMarker.h>
34 // Root Geometry includes
35 #include <TGeoVolume.h>
36 #include <TGeoTube.h> // contains TGeoTubeSeg
40 #include <TGeoMatrix.h>
41 #include <TGeoMaterial.h>
42 #include <TGeoMedium.h>
43 #include <TGeoCompositeShape.h>
48 #include "AliITSv11GeometrySPD.h"
50 ClassImp(AliITSv11GeometrySPD)
54 //______________________________________________________________________
55 Int_t AliITSv11GeometrySPD::CreateSPDCentralMaterials(Int_t &medOffset, Int_t &matOffset) const
57 // Define the specific materials used for the ITS SPD central
58 // detectors. Note, These are the same old names. By the ALICE
59 // naming convension, these should start out at ITS SPD ....
60 // This data has been taken from AliITSvPPRasymmFMD::CreateMaterials().
62 // Int_t &medOffset The starting number of the list of media
63 // Int_t &matOffset The starting number of the list of Materials
65 // Int_t &medOffset The ending number of the list of media
66 // Int_t &matOffset The ending number of the list of Materials
68 // the last material number used +1 (the next avaiable material number).
71 <img src="http://alice.pd.infn.it/latestdr/all-sections-module.ps"
72 title="SPD Sector drawing with all cross sections defined">
73 <p>The SPD Sector definition.
74 <img src="http://alice.pd.infn.it/latestdr/assembly-10-modules.ps"
75 titile="SPD All Sectors end view with thermal sheald">
76 <p>The SPD all sector end view with thermal sheald.
77 <img src="http://alice.pd.infn.it/latestdr/assembly.ps"
78 title="SPD side view cross section">
79 <p>SPD side view cross section with condes and thermal shealds.
80 <img src="http://alice.pd.infn.it/latestdr/SECTION-A_A.jpg"
81 title="Cross setion A-A"><p>Cross section A-A
82 <img src="http://alice.pd.infn.it/latestdr/SECTION-B_B.jpg"
83 title="Cross section B-B"><p>Cross section B-B
84 <img src="http://alice.pd.infn.it/latestdr/SECTION-C_C.jpg"
85 title-"Cross section C-C"><p>Cross section C-C
86 <img src="http://alice.pd.infn.it/latestdr/SECTION-D_D.jpg"
87 title="Cross section D-D"><p>Cross section D-D
88 <img src="http://alice.pd.infn.it/latestdr/SECTION-F_F.jpg"
89 title="Cross section F-F"><p>Cross section F-F
90 <img src="http://alice.pd.infn.it/latestdr/SECTION-G_G.jpg"
91 title="Cross section G-G"><p>Cross section G-G
94 const Double_t ktmaxfd = 0.1*fgkDegree; // Degree
95 const Double_t kstemax = 1.0*fgkcm; // cm
96 const Double_t kdeemax = 0.1; // Fraction of particle's energy 0<deemax<=1
97 const Double_t kepsil = 1.0E-4; //
98 const Double_t kstmin = 0.0*fgkcm; // cm "Default value used"
99 const Double_t ktmaxfdAir = 0.1*fgkDegree; // Degree
100 const Double_t kstemaxAir = 1.0000E+00*fgkcm; // cm
101 const Double_t kdeemaxAir = 0.1; //Fraction of particle's energy 0<deemax<=1
102 const Double_t kepsilAir = 1.0E-4;//
103 const Double_t kstminAir = 0.0*fgkcm; // cm "Default value used"
104 const Double_t ktmaxfdSi = 0.1*fgkDegree; // .10000E+01; // Degree
105 const Double_t kstemaxSi = 0.0075*fgkcm; // .10000E+01; // cm
106 const Double_t kdeemaxSi = 0.1; // Fraction of particle's energy 0<deemax<=1
107 const Double_t kepsilSi = 1.0E-4;//
108 const Double_t kstminSi = 0.0*fgkcm; // cm "Default value used"
110 Int_t matindex=matOffset;
111 Int_t medindex=medOffset;
112 Double_t params[8]={8*0.0};
117 Int_t ifield = (gAlice->Field()->Integ());
118 Double_t fieldm = (gAlice->Field()->Max());
119 params[1] = (Double_t) ifield;
121 params[3] = ktmaxfdSi;
122 params[4] = kstemaxSi;
123 params[5] = kdeemaxSi;
124 params[6] = kepsilSi;
125 params[7] = kstminSi;
127 mat = new TGeoMaterial("SI",28.086,14.0,2.33*fgkgcm3,
128 TGeoMaterial::kMatStateSolid,25.0*fgkCelsius,
130 mat->SetIndex(matindex);
131 med = new TGeoMedium("SI",medindex++,mat,params);
132 //med = new TGeoMedium("SI",medindex++,matindex++,0,ifield,
133 // fieldm,ktmaxfdSi,kstemaxSi,kdeemaxSi,kepsilSi,kstminSi);
135 mat = new TGeoMaterial("SPD SI CHIP",28.086,14.0,2.33*fgkgcm3,
136 TGeoMaterial::kMatStateSolid,25.0*fgkCelsius,
138 mat->SetIndex(matindex);
139 med = new TGeoMedium("SPD SI CHIP",medindex++,mat,params);
140 //med = new TGeoMedium("SPD SI CHIP",medindex++,matindex++,0,ifield,
141 // fieldm,ktmaxfdSi,kstemaxSi,kdeemaxSi,kepsilSi,kstminSi);
143 mat = new TGeoMaterial("SPD SI BUS",28.086,14.0,2.33*fgkgcm3,
144 TGeoMaterial::kMatStateSolid,25.0*fgkCelsius,
146 mat->SetIndex(matindex);
147 med = new TGeoMedium("SPD SI BUS",medindex++,mat,params);
148 //med = new TGeoMedium("SPD SI BUS",medindex++,matindex++,0,ifield,
149 // fieldm,ktmaxfdSi,kstemaxSi,kdeemaxSi,kepsilSi,kstminSi);
151 // Carbon fiber by fractional weight "C (M55J)"
152 mix = new TGeoMixture("C (M55J)",4,1.9866*fgkgcm3);
153 mix->SetIndex(matindex);
154 // Carbon by fractional weight
155 mix->DefineElement(0,12.0107,6.0,0.908508078);
156 // Nitrogen by fractional weight
157 mix->DefineElement(1,14.0067,7.0,0.010387573);
158 // Oxigen by fractional weight
159 mix->DefineElement(2,15.9994,8.0,0.055957585);
160 // Hydrogen by fractional weight
161 mix->DefineElement(3,1.00794,1.0,0.025146765);
162 mix->SetPressure(0.0*fgkPascal);
163 mix->SetTemperature(25.0*fgkCelsius);
164 mix->SetState(TGeoMaterial::kMatStateSolid);
170 med = new TGeoMedium("ITSspdCarbonFiber",medindex++,mix,params);
171 //med = new TGeoMedium("ITSspdCarbonFiber",medindex++,matindex++,0,ifield,
172 // fieldm,ktmaxfd,kstemax,kdeemax,kepsil,kstmin);
174 // Carbon fiber by fractional weight
175 mix = new TGeoMixture("Air",4,1.20479E-3*fgkgcm3);
176 mix->SetIndex(matindex);
177 mix->DefineElement(0,12.0107,6.0,0.000124); // Carbon by fractional weight
178 mix->DefineElement(1,14.0067,7.0,0.755267); // Nitrogen by fractional weight
179 mix->DefineElement(2,15.9994,8.0,0.231781); // Oxigen by fractional weight
180 mix->DefineElement(3,39.948,18.0,0.012827); // Argon by fractional weight
181 mix->SetPressure(101325.0*fgkPascal); // 1 atmosphere
182 mix->SetTemperature(25.0*fgkCelsius);
183 mix->SetState(TGeoMaterial::kMatStateGas);
184 params[3] = ktmaxfdAir;
185 params[4] = kstemaxAir;
186 params[5] = kdeemaxAir;
187 params[6] = kepsilAir;
188 params[7] = kstminAir;
189 med = new TGeoMedium("ITSspdAir",medindex++,mix,params);
190 //med = new TGeoMedium("ITSspdAir",medindex++,matindex++,0,ifield,
191 // fieldm,ktmaxfdAir,kstemaxAir,kdeemaxAir,kepsilAir,kstminAir);
193 // Carbon fiber by fractional weight
194 mix = new TGeoMixture("INOX",9,8.03*fgkgcm3);
195 mix->SetIndex(matindex);
196 mix->DefineElement(0,12.0107, 6.0,0.0003); // Carbon by fractional weight
197 mix->DefineElement(1,54.9380,25.0,0.02); // Iron by fractional weight
198 mix->DefineElement(2,28.0855,14.0,0.01); // Sodium by fractional weight
199 mix->DefineElement(3,30.9738,15.0,0.00045); // by fractional weight
200 mix->DefineElement(4,32.066 ,16.0,0.0003); // by fractional weight
201 mix->DefineElement(5,58.6928,28.0,0.12); // Nickel by fractional weight
202 mix->DefineElement(6,55.9961,24.0,0.17); // by fractional weight
203 mix->DefineElement(7,95.84 ,42.0,0.025); // by fractional weight
204 mix->DefineElement(8,55.845 ,26.0,0.654); // by fractional weight
205 mix->SetPressure(0.0*fgkPascal); //
206 mix->SetTemperature(25.0*fgkCelsius);
207 mix->SetState(TGeoMaterial::kMatStateSolid);
208 params[3] = ktmaxfdAir;
209 params[4] = kstemaxAir;
210 params[5] = kdeemaxAir;
211 params[6] = kepsilAir;
212 params[7] = kstminAir;
213 med = new TGeoMedium("ITSspdStainlessSteel",medindex++,mix,params);
214 //med =new TGeoMedium("ITSspdStainlessSteel",medindex++,matindex++,0,ifield,
215 // fieldm,ktmaxfdAir,kstemaxAir,kdeemaxAir,kepsilAir,kstminAir);
217 // Carbon fiber by fractional weight
218 mix->SetIndex(matindex);
219 mix = new TGeoMixture("Freon",2,1.63*fgkgcm3);
220 mix->DefineElement(0,12.0107,6.0,4); // Carbon by fractional weight
221 mix->DefineElement(1,18.9984032,9.0,10); // Florine by fractional weight
222 mix->SetPressure(101325.0*fgkPascal); // 1 atmosphere
223 mix->SetTemperature(25.0*fgkCelsius);
224 mix->SetState(TGeoMaterial::kMatStateLiquid);
225 params[3] = ktmaxfdAir;
226 params[4] = kstemaxAir;
227 params[5] = kdeemaxAir;
228 params[6] = kepsilAir;
229 params[7] = kstminAir;
230 med = new TGeoMedium("ITSspdCoolingFluid",medindex++,mix,params);
231 //med = new TGeoMedium("ITSspdCoolingFluid",medindex++,matindex++,0,ifield,
232 // fieldm,ktmaxfdAir,kstemaxAir,kdeemaxAir,kepsilAir,kstminAir);
234 medOffset = medindex;
235 matOffset = matindex;
238 //______________________________________________________________________
239 void AliITSv11GeometrySPD::InitSPDCentral(Int_t offset,TVirtualMC *vmc) const {
240 // Do any SPD Central detector related initilizations, setting
241 // transport cuts for example.
242 // Some GEANT3 Physics switches
244 // Multiple scattering. The variable IMULS controls this process. For
245 // more information see [PHYS320 or 325 or 328].
246 // 0 - No multiple scattering.
247 // 1 - Multiple scattering according to Moli�re theory. Default setting.
248 // 2 - Same as 1. Kept for backward compatibility.
249 // 3 - Pure Gaussian scattering according to the Rossi formula.
251 // delta ray production. The variable IDRAY controls this process.
253 // 0 - No delta rays production.
254 // 1 - delta rays production with generation of . Default setting.
255 // 2 - delta rays production without generation of .
257 // Continuous energy loss. The variable ILOSS controls this process.
258 // 0 - No continuous energy loss, IDRAY is set to 0.
259 // 1 - Continuous energy loss with generation of delta rays above
260 // DCUTE (common/GCUTS/) and restricted Landau fluctuations below DCUTE.
261 // 2 - Continuous energy loss without generation of delta rays and full
262 // Landau-Vavilov-Gauss fluctuations. In this case the variable IDRAY
263 // is forced to 0 to avoid double counting of fluctuations. Default
265 // 3 - Same as 1, kept for backward compatibility.
266 // 4 - Energy loss without fluctuation. The value obtained from the
267 // tables is used directly.
269 // Int_t offset The material/medium index offset.
270 // TVirturalMC *vmc The pointer to the virtual Monte Carlo default gMC.
278 vmc->Gstpar(i+offset,"CUTGAM",30.0*fgkKeV);
279 vmc->Gstpar(i+offset,"CUTELE",30.0*fgkKeV);
280 vmc->Gstpar(i+offset,"CUTNEU",30.0*fgkKeV);
281 vmc->Gstpar(i+offset,"CUTHAD",30.0*fgkKeV);
282 vmc->Gstpar(i+offset,"CUTMUO",30.0*fgkKeV);
283 vmc->Gstpar(i+offset,"BCUTE",30.0*fgkKeV);
284 vmc->Gstpar(i+offset,"BCUTM",30.0*fgkKeV);
285 vmc->Gstpar(i+offset,"DCUTE",30.0*fgkKeV);
286 vmc->Gstpar(i+offset,"DCUTM",30.0*fgkKeV);
287 //vmc->Gstpar(i+offset,"PPCUTM",);
288 //vmc->Gstpar(i+offset,"PAIR",);
289 //vmc->Gstpar(i+offset,"COMPT",);
290 //vmc->Gstpar(i+offset,"PHOT",);
291 //vmc->Gstpar(i+offset,"PFIS",);
292 vmc->Gstpar(i+offset,"DRAY",1);
293 //vmc->Gstpar(i+offset,"ANNI",);
294 //vmc->Gstpar(i+offset,"BREM",);
295 //vmc->Gstpar(i+offset,"HADR",);
296 //vmc->Gstpar(i+offset,"MUNU",);
297 //vmc->Gstpar(i+offset,"DCAY",);
298 vmc->Gstpar(i+offset,"LOSS",1);
299 //vmc->Gstpar(i+offset,"MULS",);
300 //vmc->Gstpar(i+offset,"GHCOR1",);
301 //vmc->Gstpar(i+offset,"BIRK1",);
302 //vmc->Gstpar(i+offset,"BRIK2",);
303 //vmc->Gstpar(i+offset,"BRIK3",);
304 //vmc->Gstpar(i+offset,"LABS",);
305 //vmc->Gstpar(i+offset,"SYNC",);
306 //vmc->Gstpar(i+offset,"STRA",);
309 //______________________________________________________________________
310 void AliITSv11GeometrySPD::SPDSector(TGeoVolume *moth,TGeoManager *mgr){
311 // Position of the Carbon Fiber Assembly based on distance
312 // of closest point of SPD stave to beam pipe figures
313 // all-sections-modules.ps of 7.22mm at section A-A.
315 // TGeoVolume *moth the mother volume which this
316 // object/volume is to be placed in.
321 const Double_t kSPDclossesStaveAA = 7.22*fgkmm;
322 const Double_t kSectorStartingAngle = -72.0*fgkDegree;
323 const Double_t kNSectorsTotal = 10.; // number
324 const Double_t kSectorRelativeAngle = 360./kNSectorsTotal*fgkDegree;
325 const Double_t kBeamPipeRadius = 0.5*60.0*fgkmm;
328 Double_t angle,radiusSector,xAAtubeCenter0,yAAtubeCenter0;
329 Double_t staveThicknessAA=1.03*fgkmm; // get from stave geometry.
330 TGeoCombiTrans *secRot=new TGeoCombiTrans();
331 TGeoVolume *vCarbonFiberSector;
332 TGeoMedium *medSPDcf;
334 medSPDcf = mgr->GetMedium("ITSspdCarbonFiber");
335 vCarbonFiberSector = new TGeoVolumeAssembly("ITSSPDCarbonFiberSectorV");
336 vCarbonFiberSector->SetMedium(medSPDcf);
337 CarbonFiberSector(vCarbonFiberSector,xAAtubeCenter0,yAAtubeCenter0);
338 //SectorPlusStaves(vCarbonFiberSector,xAAtubeCenter0,yAAtubeCenter0);
339 vCarbonFiberSector->SetVisibility(kTRUE); // logical volume
340 // Compute the radial shift out of the sectors.
341 radiusSector = kBeamPipeRadius+kSPDclossesStaveAA+staveThicknessAA;
342 radiusSector *= radiusSector; // squaring;
343 radiusSector -= xAAtubeCenter0*xAAtubeCenter0;
344 radiusSector = -yAAtubeCenter0+TMath::Sqrt(radiusSector);
345 angle = kSectorStartingAngle;
346 secRot->RotateZ(angle);
347 for(i=0;i<(Int_t)kNSectorsTotal;i++){
348 secRot->SetDx(-radiusSector*TMath::Sin(angle/fgkRadian));
349 secRot->SetDy(radiusSector*TMath::Cos(angle/fgkRadian));
350 //secRot->RegisterYourself();
351 moth->AddNode(vCarbonFiberSector,i+1,new TGeoCombiTrans(*secRot));
353 printf("i=%d angle=%g angle[rad]=%g radiusSector=%g x=%g y=%g \n",
354 i,angle,angle/fgkRadian,radiusSector,
355 -radiusSector*TMath::Sin(angle/fgkRadian),
356 radiusSector*TMath::Cos(angle/fgkRadian));
357 } // end if GetDebug(5)
358 angle += kSectorRelativeAngle;
359 secRot->RotateZ(kSectorRelativeAngle);
363 } // end if GetDebug().
366 //______________________________________________________________________
367 void AliITSv11GeometrySPD::CarbonFiberSector(TGeoVolume *moth,
368 Double_t &xAAtubeCenter0,
369 Double_t &yAAtubeCenter0,
371 // Define the detail SPD Carbon fiber support Sector geometry.
372 // Based on the drawings ALICE-Pixel "Construzione Profilo Modulo"
373 // March 25 2004 and ALICE-SUPPORTO "construzione Profilo Modulo"
374 // Define Outside radii as negitive, Outside in the sence that the
375 // center of the arc is outside of the object.
378 // TGeoVolume *moth The mother volume to put this object
380 // Double_t &xAAtubeCenter0 The x location of the outer surface
381 // of the cooling tube center for tube 0.
382 // This location helps determine where
383 // this sector is to be located (information
384 // used for this is the distance the
385 // center of the #0 detector is from the
386 // beam pipe. Measurements taken at
387 // cross section A-A.
388 // Double_t &yAAtubeCenter0 The y location of the outer surface
389 // of the cooling tube center for tube 0
390 // This location helps determine where
391 // this sector is to be located (information
392 // used for this is the distance the
393 // center of the #0 detector is from the
394 // beam pipe. Measurements taken at
395 // cross section A-A.
396 // TGeoManager *mgr The TGeoManager as needed, default is
400 TGeoMedium *medSPDcf = 0; // SPD support cone Carbon Fiber materal number.
401 //TGeoMedium *medSPDfs = 0; // SPD support cone inserto stesalite 4411w.
402 //TGeoMedium *medSPDfo = 0; // SPD support cone foam, Rohacell 50A.
403 TGeoMedium *medSPDss = 0; // SPD support cone screw material,Stainless
404 TGeoMedium *medSPDair = 0; // SPD support cone Air
405 //TGeoMedium *medSPDal = 0; // SPD support cone SDD mounting bracket Al
406 TGeoMedium *medSPDcoolfl = 0; // SPD cooling fluid, Freeon
407 medSPDcf = mgr->GetMedium("ITSspdCarbonFiber");
408 //medSPDfs = mgr->GetMedium("ITSspdStaselite4411w");
409 //medSPDfo = mgr->GetMedium("ITSspdRohacell50A");
410 medSPDss = mgr->GetMedium("ITSspdStainlessSteel");
411 medSPDair= mgr->GetMedium("ITSspdAir");
412 medSPDcoolfl= mgr->GetMedium("ITSspdCoolingFluid");
414 const Double_t ksecDz = 0.5*500.0*fgkmm;
415 const Double_t ksecLen = 30.0*fgkmm;
416 const Double_t ksecCthick = 0.20*fgkmm;
417 const Double_t ksecDipLength = 3.2*fgkmm;
418 const Double_t ksecDipRadii = 0.4*fgkmm;
419 //const Double_t ksecCoolingTubeExtraDepth = 0.86*fgkmm;
420 // These positions, ksecX*,ksecY* are the center of curvatures
421 // for the different point around the SPD sector. The radii,
422 // inner and outer, are the radous of curvature about the centers
423 // ksecX* and ksecY*. To draw this SPD sector, first plot all of
424 // the ksecX and ksecY points and draw circles of the specified
425 // radius about these points. Connect the circles, such that the
426 // lines are tangent to the circles, in accordance with the
427 // radii being "Inside" or "Outside". These lines and the
428 // corresponding arc's are the surface of this SPD sector.
429 const Double_t ksecX0 = -10.725*fgkmm;
430 const Double_t ksecY0 = -14.853*fgkmm;
431 const Double_t ksecR0 = -0.8*fgkmm; // Outside
432 const Double_t ksecX1 = -13.187*fgkmm;
433 const Double_t ksecY1 = -19.964*fgkmm;
434 const Double_t ksecR1 = +0.6*fgkmm; // Inside
435 //const Double_t ksecDip0 = 5.9*fgkmm;
437 const Double_t ksecX2 = -3.883*fgkmm;
438 const Double_t ksecY2 = -17.805*fgkmm;
439 const Double_t ksecR2 = +0.80*fgkmm; // Inside Guess.
440 const Double_t ksecX3 = -3.123*fgkmm;
441 const Double_t ksecY3 = -14.618*fgkmm;
442 const Double_t ksecR3 = -0.6*fgkmm; // Outside
443 //const Double_t ksecDip1 = 8.035*fgkmm;
445 const Double_t ksecX4 = +11.280*fgkmm;
446 const Double_t ksecY4 = -14.473*fgkmm;
447 const Double_t ksecR4 = +0.8*fgkmm; // Inside
448 const Double_t ksecX5 = +19.544*fgkmm;
449 const Double_t ksecY5 = +10.961*fgkmm;
450 const Double_t ksecR5 = +0.8*fgkmm; // Inside
451 //const Double_t ksecDip2 = 4.553*fgkmm;
453 const Double_t ksecX6 = +10.830*fgkmm;
454 const Double_t ksecY6 = +16.858*fgkmm;
455 const Double_t ksecR6 = +0.6*fgkmm; // Inside
456 const Double_t ksecX7 = +11.581*fgkmm;
457 const Double_t ksecY7 = +13.317*fgkmm;
458 const Double_t ksecR7 = -0.6*fgkmm; // Outside
459 //const Double_t ksecDip3 = 6.978*fgkmm;
461 const Double_t ksecX8 = -0.733*fgkmm;
462 const Double_t ksecY8 = +17.486*fgkmm;
463 const Double_t ksecR8 = +0.6*fgkmm; // Inside
464 const Double_t ksecX9 = +0.562*fgkmm;
465 //const Double_t ksecY9 = +14.486*fgkmm; // correction by
466 const Double_t ksecY9 = +14.107*fgkmm; // Alberto
467 const Double_t ksecR9 = -0.6*fgkmm; // Outside
468 //const Double_t ksecDip4 = 6.978*fgkmm;
470 const Double_t ksecX10 = -12.252*fgkmm;
471 const Double_t ksecY10 = +16.298*fgkmm;
472 const Double_t ksecR10 = +0.6*fgkmm; // Inside
473 const Double_t ksecX11 = -10.445*fgkmm;
474 const Double_t ksecY11 = +13.162*fgkmm;
475 const Double_t ksecR11 = -0.6*fgkmm; // Outside
476 //const Double_t ksecDip5 = 6.978*fgkmm;
478 const Double_t ksecX12 = -22.276*fgkmm;
479 const Double_t ksecY12 = +12.948*fgkmm;
480 const Double_t ksecR12 = +0.85*fgkmm; // Inside
481 //const Double_t ksecX13 = *fgkmm;
482 //const Double_t ksecY13 = *fgkmm;
483 const Double_t ksecR13 = -0.8*fgkmm; // Outside
484 const Double_t ksecAngleSide13 = 36.0*fgkDegree;
486 const Int_t ksecNRadii = 20;
487 const Int_t ksecNPointsPerRadii = 4;
488 const Int_t ksecNCoolingTubeDips = 6;
489 // Since the Rounded parts are aproximated by a regular polygon and
490 // a cooling tube of the propper diameter must fit, a scaling factor
491 // increases the size of the polygon for the tube to fit.
492 //const Double_t ksecRCoolScale = 1./TMath::Cos(TMath::Pi()/
493 // (Double_t)ksecNPointsPerRadii);
494 const Double_t ksecZEndLen = 30.00*fgkmm;
495 //const Double_t ksecZFlangLen= 45.00*fgkmm;
496 const Double_t ksecTl = 0.860*fgkmm;
497 const Double_t ksecCthick2 = 0.600*fgkmm;
498 //const Double_t ksecCthick3 = 1.800*fgkmm;
499 //const Double_t ksecSidelen = 22.00*fgkmm;
500 //const Double_t ksecSideD5 = 3.679*fgkmm;
501 //const Double_t ksecSideD12 = 7.066*fgkmm;
502 const Double_t ksecRCoolOut = 2.400*fgkmm;
503 const Double_t ksecRCoolIn = 2.000*fgkmm;
504 const Double_t ksecDl1 = 5.900*fgkmm;
505 const Double_t ksecDl2 = 8.035*fgkmm;
506 const Double_t ksecDl3 = 4.553*fgkmm;
507 const Double_t ksecDl4 = 6.978*fgkmm;
508 const Double_t ksecDl5 = 6.978*fgkmm;
509 const Double_t ksecDl6 = 6.978*fgkmm;
510 const Double_t ksecCoolTubeThick = 0.04*fgkmm;
511 const Double_t ksecCoolTubeROuter = 2.6*fgkmm;
512 const Double_t ksecCoolTubeFlatX = 3.696*fgkmm;
513 const Double_t ksecCoolTubeFlatY = 0.68*fgkmm;
514 //const Double_t ksecBeamX0 = 0.0*fgkmm; // guess
515 //const Double_t ksecBeamY0 = (15.223+40.)*fgkmm; // guess
517 const Int_t ksecNPoints = (ksecNPointsPerRadii+1)*ksecNRadii + 8;
518 Double_t secX[ksecNRadii] = {ksecX0,ksecX1,-1000.0,ksecX2 ,ksecX3 ,-1000.0,
519 ksecX4,ksecX5,-1000.0,ksecX6 ,ksecX7 ,-1000.0,
520 ksecX8,ksecX9,-1000.0,ksecX10,ksecX11,-1000.0,
522 Double_t secY[ksecNRadii] = {ksecY0,ksecY1,-1000.0,ksecY2 ,ksecY3 ,-1000.0,
523 ksecY4,ksecY5,-1000.0,ksecY6 ,ksecY7 ,-1000.0,
524 ksecY8,ksecY9,-1000.0,ksecY10,ksecY11,-1000.0,
526 Double_t secR[ksecNRadii] ={ksecR0 ,ksecR1 ,-.5*ksecDipLength-ksecDipRadii,
527 ksecR2 ,ksecR3 ,-.5*ksecDipLength-ksecDipRadii,
528 ksecR4 ,ksecR5 ,-.5*ksecDipLength-ksecDipRadii,
529 ksecR6 ,ksecR7 ,-.5*ksecDipLength-ksecDipRadii,
530 ksecR8 ,ksecR9 ,-.5*ksecDipLength-ksecDipRadii,
531 ksecR10,ksecR11,-.5*ksecDipLength-ksecDipRadii,
533 Double_t secDip[ksecNRadii]={0.0,0.0,ksecDip0,0.0,0.0,ksecDip1,
534 0.0,0.0,ksecDip2,0.0,0.0,ksecDip3,
535 0.0,0.0,ksecDip4,0.0,0.0,ksecDip5,
537 Double_t secX2[ksecNRadii];
538 Double_t secY2[ksecNRadii];
539 Double_t secR2[ksecNRadii] = {
540 ksecR0,ksecR1,ksecRCoolOut,ksecR2,ksecR3,ksecRCoolOut,ksecR4,ksecR5,
541 ksecRCoolOut,ksecR6,ksecR7,ksecRCoolOut,ksecR8,ksecR9,ksecRCoolOut,
542 ksecR10,ksecR11,ksecRCoolOut,ksecR12,ksecR13};
543 Double_t secDip2[ksecNCoolingTubeDips]={ksecDl1,ksecDl2,ksecDl3,
544 ksecDl4,ksecDl5,ksecDl6};
545 Double_t secX3[ksecNRadii];
546 Double_t secY3[ksecNRadii];
547 const Int_t ksecDipIndex[ksecNCoolingTubeDips] = {2,5,8,11,14,17};
548 Double_t secAngleStart[ksecNRadii];
549 Double_t secAngleEnd[ksecNRadii];
550 Double_t secAngleStart2[ksecNRadii];
551 Double_t secAngleEnd2[ksecNRadii];
552 Double_t secAngleTurbo[ksecNCoolingTubeDips] = {0.0,0.0,0.0,0.0,0.0,0.0};
553 //Double_t secAngleStart3[ksecNRadii];
554 //Double_t secAngleEnd3[ksecNRadii];
555 Double_t xpp[ksecNPoints],ypp[ksecNPoints];
556 Double_t xpp2[ksecNPoints],ypp2[ksecNPoints];
557 Double_t *xp[ksecNRadii],*xp2[ksecNRadii];
558 Double_t *yp[ksecNRadii],*yp2[ksecNRadii];
559 TGeoXtru *sA0,*sA1,*sB0,*sB1;
560 TGeoEltu *sTA0,*sTA1;
561 TGeoTube *sTB0,*sTB1; //,*sM0;
563 TGeoTranslation *trans;
564 TGeoCombiTrans *rotrans;
565 Double_t t,t0,t1,a,b,x0,y0,x1,y1;
570 Error("CarbonFiberSector","moth=%p",moth);
574 for(i=0;i<ksecNRadii;i++){
575 xp[i] = &(xpp[i*(ksecNPointsPerRadii+1)]);
576 yp[i] = &(ypp[i*(ksecNPointsPerRadii+1)]);
577 xp2[i] = &(xpp2[i*(ksecNPointsPerRadii+1)]);
578 yp2[i] = &(ypp2[i*(ksecNPointsPerRadii+1)]);
585 // Find starting and ending angles for all but cooling tube sections
586 secAngleStart[0] = 0.5*ksecAngleSide13;
587 for(i=0;i<ksecNRadii-2;i++){
589 for(j=0;j<ksecNCoolingTubeDips;j++) tst = tst||i==ksecDipIndex[j];
592 for(j=0;j<ksecNCoolingTubeDips;j++) tst = tst||(i+1)==ksecDipIndex[j];
595 AnglesForRoundedCorners(secX[i],secY[i],secR[i],
596 secX[j],secY[j],secR[j],t0,t1);
598 secAngleStart[j] = t1;
599 if(secR[i]>0.0&&secR[j]>0.0)if(secAngleStart[i]>secAngleEnd[i])
600 secAngleEnd[i] += 360.0;
601 secAngleStart2[i] = secAngleStart[i];
602 secAngleEnd2[i] = secAngleEnd[i];
604 secAngleEnd[ksecNRadii-2] = secAngleStart[ksecNRadii-2] +
605 (secAngleEnd[ksecNRadii-5]-
606 secAngleStart[ksecNRadii-5]);
607 if(secAngleEnd[ksecNRadii-2]<0.0) secAngleEnd[ksecNRadii-2] += 360.0;
608 secAngleStart[ksecNRadii-1] = secAngleEnd[ksecNRadii-2] - 180.0;
609 secAngleEnd[ksecNRadii-1] = secAngleStart[0];
610 secAngleStart2[ksecNRadii-2] = secAngleStart[ksecNRadii-2];
611 secAngleEnd2[ksecNRadii-2] = secAngleEnd[ksecNRadii-2];
612 secAngleStart2[ksecNRadii-1] = secAngleStart[ksecNRadii-1];
613 secAngleEnd2[ksecNRadii-1] = secAngleEnd[ksecNRadii-1];
614 // Find location of circle last rounded corner.
617 t0 = TanD(secAngleStart[i]-90.);
618 t1 = TanD(secAngleEnd[j]-90.);
619 t = secY[i] - secY[j];
620 // Note, secR[i=0] <0; secR[j=18]>0; and secR[j+1=19] <0
621 t += (-secR[i]+secR[j+1])*SinD(secAngleStart[i]);
622 t -= (secR[j]-secR[j+1])*SinD(secAngleEnd[j]);
623 t += t1*secX[j] - t0*secX[i];
624 t += t1*(secR[j]-secR[j+1])*CosD(secAngleEnd[j]);
625 t -= t0*(-secR[i]+secR[j+1])*CosD(secAngleStart[i]);
626 secX[ksecNRadii-1] = t/(t1-t0);
627 secY[ksecNRadii-1] = TanD(90.+0.5*ksecAngleSide13)*
628 (secX[ksecNRadii-1]-secX[0]) + secY[0];
629 secX2[ksecNRadii-1] = secX[ksecNRadii-1];
630 secY2[ksecNRadii-1] = secY[ksecNRadii-1];
631 secX3[ksecNRadii-1] = secX[ksecNRadii-1];
632 secY3[ksecNRadii-1] = secY[ksecNRadii-1];
633 // find location of cooling tube centers
634 for(i=0;i<ksecNCoolingTubeDips;i++){
636 x0 = secX[j-1] + TMath::Abs(secR[j-1])*CosD(secAngleEnd[j-1]);
637 y0 = secY[j-1] + TMath::Abs(secR[j-1])*SinD(secAngleEnd[j-1]);
638 x1 = secX[j+1] + TMath::Abs(secR[j+1])*CosD(secAngleStart[j+1]);
639 y1 = secY[j+1] + TMath::Abs(secR[j+1])*SinD(secAngleStart[j+1]);
640 t0 = TMath::Sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
644 if(i==0){ // get location of tube center->Surface for locating
645 // this sector around the beam pipe. This needs to be
646 // double checked, but I need my notes for that, Bjorn Nilsen
647 xAAtubeCenter0 = x0+(x1-x0)*t*0.5;
648 yAAtubeCenter0 = y0+(y1-y0)*t*0.5;
650 if(a+b*(a-x0)/(b-y0)>0.0){
651 secX[j] = a + TMath::Abs(y1-y0)*2.0*ksecDipRadii/t0;
652 secY[j] = b - TMath::Sign(2.0*ksecDipRadii,y1-y0)*(x1-x0)/t0;
653 secX2[j] = a + TMath::Abs(y1-y0)*ksecTl/t0;
654 secY2[j] = b - TMath::Sign(ksecTl,y1-y0)*(x1-x0)/t0;
655 secX3[j] = a + TMath::Abs(y1-y0)*(2.0*ksecDipRadii-
656 0.5*ksecCoolTubeFlatY)/t0;
657 secY3[j] = b - TMath::Sign(2.0*ksecDipRadii-0.5*ksecCoolTubeFlatY,
660 secX[j] = a - TMath::Abs(y1-y0)*2.0*ksecDipRadii/t0;
661 secY[j] = b + TMath::Sign(2.0*ksecDipRadii,y1-y0)*(x1-x0)/t0;
662 secX2[j] = a - TMath::Abs(y1-y0)*ksecTl/t0;
663 secY2[j] = b + TMath::Sign(ksecTl,y1-y0)*(x1-x0)/t0;
664 secX3[j] = a - TMath::Abs(y1-y0)*(2.0*ksecDipRadii-
665 0.5*ksecCoolTubeFlatY)/t0;
666 secY3[j] = b + TMath::Sign(2.0*ksecDipRadii-0.5*ksecCoolTubeFlatY,
669 // Set up Start and End angles to correspond to start/end of dips.
670 t1 = (secDip2[i]-TMath::Abs(secR[j]))/t0;
671 secAngleStart[j] = TMath::RadToDeg()*TMath::ATan2(
672 y0+(y1-y0)*t1-secY[j],x0+(x1-x0)*t1-secX[j]);
673 if(secAngleStart[j]<0.0) secAngleStart[j] += 360.0;
674 secAngleStart2[j] = secAngleStart[j];
675 t1 = (secDip2[i]+TMath::Abs(secR[j]))/t0;
676 secAngleEnd[j] = TMath::RadToDeg()*TMath::ATan2(
677 y0+(y1-y0)*t1-secY[j],x0+(x1-x0)*t1-secX[j]);
678 if(secAngleEnd[j]<0.0) secAngleEnd[j] += 360.0;
679 secAngleEnd2[j] = secAngleEnd[j];
680 if(secAngleEnd[j]>secAngleStart[j]) secAngleEnd[j] -= 360.0;
681 secR[j] = TMath::Sqrt(secR[j]*secR[j]+4.0*ksecDipRadii*ksecDipRadii);
684 secAngleStart2[8] -= 360.;
685 secAngleStart2[11] -= 360.;
687 fSPDsectorPoints0.Set(ksecNCoolingTubeDips);
688 fSPDsectorPoints1.Set(ksecNCoolingTubeDips);
690 for(i=0;i<ksecNCoolingTubeDips;i++){
691 // Find index in xpp[] and ypp[] corresponding to where the
692 // SPD ladders are to be attached. Order them according to
693 // the ALICE numbering schema. Using array of indexes (+-1 for
694 // cooling tubes. For any "bend/dip/edge, there are
695 // ksecNPointsPerRadii+1 points involved.
699 fSPDsectorPoints0[i] = (ksecDipIndex[j]-1)*(ksecNPointsPerRadii+1)+
700 (ksecNPointsPerRadii);
701 fSPDsectorPoints1[i] = (ksecDipIndex[j]+1)*(ksecNPointsPerRadii+1);
703 SPDsectorShape(ksecNRadii,secX,secY,secR,secAngleStart,secAngleEnd,
704 ksecNPointsPerRadii,m,xp,yp);
705 // Fix up dips to be square.
706 for(i=0;i<ksecNCoolingTubeDips;i++){
708 t = 0.5*ksecDipLength+ksecDipRadii;
709 t0 = TMath::RadToDeg()*TMath::ATan(2.0*ksecDipRadii/t);
710 t1 = secAngleEnd[j] + t0;
711 t0 = secAngleStart[j] - t0;
712 x0 = xp[j][1] = secX[j] + t*CosD(t0);
713 y0 = yp[j][1] = secY[j] + t*SinD(t0);
714 x1 = xp[j][ksecNPointsPerRadii-1] = secX[j] + t*CosD(t1);
715 y1 = yp[j][ksecNPointsPerRadii-1] = secY[j] + t*SinD(t1);
716 t0 = 1./((Double_t)(ksecNPointsPerRadii-2));
717 for(k=2;k<ksecNPointsPerRadii-1;k++){// extra points spread them out.
718 t = ((Double_t)(k-1))*t0;
719 xp[j][k] = x0+(x1-x0)*t;
720 yp[j][k] = y0+(y1-y0)*t;
722 secAngleTurbo[i] = -TMath::RadToDeg()*TMath::ATan2(y1-y0,x1-x0);
724 cout <<"i="<<i<<" angle="<<secAngleTurbo[i]<<" x0,y0{"
725 <<x0<<","<<y0<<"} x1y1={"<<x1<<","<<y1<<"}"<<endl;
728 sA0 = new TGeoXtru(2);
729 // This shape needs to be access later to mount the SPD sector to.
730 //fSPDsectorShapeName = "ITS SPD Carbon fiber support Sector A0";
731 //sA0->SetName(fSPDsectorShapeName.Data());
732 sA0->SetName("ITS SPD Carbon fiber support Sector A0");
733 sA0->DefinePolygon(m,xpp,ypp);
734 sA0->DefineSection(0,-ksecDz);
735 sA0->DefineSection(1,ksecDz);
737 //printf("SectorA#%d ",0);
738 InsidePoint(xpp[m-1],ypp[m-1],xpp[0],ypp[0],xpp[1],ypp[1],
739 ksecCthick,xpp2[0],ypp2[0]);
741 j = i/(ksecNPointsPerRadii+1);
742 //printf("SectorA#%d ",i);
743 InsidePoint(xpp[i-1],ypp[i-1],xpp[i],ypp[i],xpp[i+1],ypp[i+1],
744 ksecCthick,xpp2[i],ypp2[i]);
746 //printf("SectorA#%d ",m);
747 InsidePoint(xpp[m-2],ypp[m-2],xpp[m-1],ypp[m-1],xpp[0],ypp[0],
748 ksecCthick,xpp2[m-1],ypp2[m-1]);
749 // Fix center value of cooling tube dip.
750 // find location of cooling tube centers
751 for(i=0;i<ksecNCoolingTubeDips;i++){
755 x1 = xp2[j][ksecNPointsPerRadii-1];
756 y1 = yp2[j][ksecNPointsPerRadii-1];
757 t0 = TMath::Sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
759 for(k=2;k<ksecNPointsPerRadii-1;k++){// extra points spread them out.
760 t = ((Double_t)(k-1))*t0;
761 xp2[j][k] = x0+(x1-x0)*t;
762 yp2[j][k] = y0+(y1-y0)*t;
765 sA1 = new TGeoXtru(2);
766 sA1->SetName("ITS SPD Carbon fiber support Sector Air A1");
767 sA1->DefinePolygon(m,xpp2,ypp2);
768 sA1->DefineSection(0,-ksecDz);
769 sA1->DefineSection(1,ksecDz);
771 // Error in TGeoEltu. Semi-axis X must be < Semi-axis Y (?).
772 sTA0 = new TGeoEltu("ITS SPD Cooling Tube TA0",
773 0.5* ksecCoolTubeFlatY, 0.5* ksecCoolTubeFlatX,ksecDz);
774 sTA1 = new TGeoEltu("ITS SPD Cooling Tube coolant TA1",
775 sTA0->GetA()-ksecCoolTubeThick,
776 sTA0->GetB()-ksecCoolTubeThick,ksecDz);
778 SPDsectorShape(ksecNRadii,secX2,secY2,secR2,secAngleStart2,secAngleEnd2,
779 ksecNPointsPerRadii,m,xp,yp);
781 sB0 = new TGeoXtru(2);
782 sB0->SetName("ITS SPD Carbon fiber support Sector End B0");
783 sB0->DefinePolygon(m,xpp,ypp);
784 sB0->DefineSection(0,ksecDz);
785 sB0->DefineSection(1,ksecDz+ksecZEndLen);
787 //printf("SectorB#%d ",0);
788 InsidePoint(xpp[m-1],ypp[m-1],xpp[0],ypp[0],xpp[1],ypp[1],
789 ksecCthick2,xpp2[0],ypp2[0]);
792 for(k=0;k<ksecNCoolingTubeDips;k++)
793 if((i/(ksecNPointsPerRadii+1))==ksecDipIndex[k])
794 if(!(ksecDipIndex[k]*(ksecNPointsPerRadii+1)==i ||
795 ksecDipIndex[k]*(ksecNPointsPerRadii+1)+
796 ksecNPointsPerRadii==i ))
797 t = ksecRCoolOut-ksecRCoolIn;
798 //printf("SectorB#%d ",i);
799 InsidePoint(xpp[i-1],ypp[i-1],xpp[i],ypp[i],xpp[i+1],ypp[i+1],
802 //printf("SectorB#%d ",m);
803 InsidePoint(xpp[m-2],ypp[m-2],xpp[m-1],ypp[m-1],xpp[0],ypp[0],
804 ksecCthick2,xpp2[m-1],ypp2[m-1]);
805 sB1 = new TGeoXtru(2);
806 sB1->SetName("ITS SPD Carbon fiber support Sector Air End B1");
807 sB1->DefinePolygon(m,xpp2,ypp2);
808 sB1->DefineSection(0,ksecDz);
809 sB1->DefineSection(1,ksecDz+ksecLen);
810 sTB0 = new TGeoTube("ITS SPD Cooling Tube End TB0",0.0,
811 0.5*ksecCoolTubeROuter,0.5*ksecLen);
812 sTB1 = new TGeoTube("ITS SPD Cooling Tube End coolant TB0",0.0,
813 sTB0->GetRmax()-ksecCoolTubeThick,0.5*ksecLen);
815 //sM0 = new TGeoTube("ITS SPD Sensitive Virutual Volume M0",0.0,8.0,
816 // sA0->GetZ(1)+sB0->GetZ(1));
819 if(medSPDcf) medSPDcf->Dump();
820 else printf("medSPDcf=0\n");
821 if(medSPDss) medSPDss->Dump();
822 else printf("medSPDss=0\n");
823 if(medSPDair) medSPDair->Dump();
824 else printf("medSPDAir=0\n");
825 if(medSPDcoolfl) medSPDcoolfl->Dump();
826 else printf("medSPDcoolfl=0\n");
827 //sM0->InspectShape();
834 TGeoVolume *vA0,*vA1,*vTA0,*vTA1,*vB0,*vB1,*vTB0,*vTB1;
835 TGeoVolumeAssembly *vM0;
836 vM0 = new TGeoVolumeAssembly("ITSSPDSensitiveVirtualvolumeM0");
837 //vM0 = new TGeoVolume("ITSSPDSensitiveVirtualvolumeM0",sM0,medSPDair);
838 //vM0->SetVisibility(kTRUE);
839 //vM0->SetLineColor(7); // light Blue
840 //vM0->SetLineWidth(1);
841 //vM0->SetFillColor(vM0->GetLineColor());
842 //vM0->SetFillStyle(4090); // 90% transparent
844 fSPDsectorShapeName = "ITSSPDCarbonFiberSupportSectorA0";
845 vA0 = new TGeoVolume(fSPDsectorShapeName,sA0,medSPDcf);
846 //vA0 = new TGeoVolume("ITSSPDCarbonFiberSupportSectorA0",sA0,medSPDcf);
847 vA0->SetVisibility(kTRUE);
848 vA0->SetLineColor(4); // Blue
849 vA0->SetLineWidth(1);
850 vA0->SetFillColor(vA0->GetLineColor());
851 vA0->SetFillStyle(4010); // 10% transparent
852 vA1 = new TGeoVolume("ITSSPDCarbonFiberSupportSectorAirA1",sA1,medSPDair);
853 vA1->SetVisibility(kTRUE);
854 vA1->SetLineColor(7); // light Blue
855 vA1->SetLineWidth(1);
856 vA1->SetFillColor(vA1->GetLineColor());
857 vA1->SetFillStyle(4090); // 90% transparent
858 vTA0 = new TGeoVolume("ITSSPDCoolingTubeTA0",sTA0,medSPDss);
859 vTA0->SetVisibility(kTRUE);
860 vTA0->SetLineColor(1); // Black
861 vTA0->SetLineWidth(1);
862 vTA0->SetFillColor(vTA0->GetLineColor());
863 vTA0->SetFillStyle(4000); // 0% transparent
864 vTA1 = new TGeoVolume("ITSSPDCoolingTubeFluidTA1",sTA1,medSPDcoolfl);
865 vTA1->SetVisibility(kTRUE);
866 vTA1->SetLineColor(6); // Purple
867 vTA1->SetLineWidth(1);
868 vTA1->SetFillColor(vTA1->GetLineColor());
869 vTA1->SetFillStyle(4000); // 0% transparent
870 vB0 = new TGeoVolume("ITSSPDCarbonFiberSupportSectorEndB0",sB0,medSPDcf);
871 vB0->SetVisibility(kTRUE);
872 vB0->SetLineColor(4); // Blue
873 vB0->SetLineWidth(1);
874 vB0->SetFillColor(vB0->GetLineColor());
875 vB0->SetFillStyle(4010); // 10% transparent
876 vB1 = new TGeoVolume("ITSSPDCarbonFiberSupportSectorEndAirB1",
878 vB1->SetVisibility(kTRUE);
879 vB1->SetLineColor(7); // light Blue
880 vB1->SetLineWidth(1);
881 vB1->SetFillColor(vB1->GetLineColor());
882 vB1->SetFillStyle(4090); // 90% transparent
883 vTB0 = new TGeoVolume("ITSSPDCoolingTubeEndTB0",sTB0,medSPDss);
884 vTB0->SetVisibility(kTRUE);
885 vTB0->SetLineColor(1); // Black
886 vTB0->SetLineWidth(1);
887 vTB0->SetFillColor(vTB0->GetLineColor());
888 vTB0->SetFillStyle(4000); // 0% transparent
889 vTB1 = new TGeoVolume("ITSSPDCoolingTubeEndFluidTB1",sTB1,medSPDcoolfl);
890 vTB1->SetVisibility(kTRUE);
891 vTB1->SetLineColor(6); // Purple
892 vTB1->SetLineWidth(1);
893 vTB1->SetFillColor(vTB1->GetLineColor());
894 vTB1->SetFillStyle(4000); // 0% transparent
897 moth->AddNode(vM0,1,0); // Add virtual volume to mother
898 vA0->AddNode(vA1,1,0); // Put air inside carbon fiber.
899 vB0->AddNode(vB1,1,0); // Put air inside carbon fiber.
900 vTA0->AddNode(vTA1,1,0); // Put air inside carbon fiber.
901 vTB0->AddNode(vTB1,1,0); // Put air inside carbon fiber.
902 for(i=0;i<ksecNCoolingTubeDips;i++){
903 x0 = secX3[ksecDipIndex[i]];
904 y0 = secY3[ksecDipIndex[i]];
905 t = 90.0-secAngleTurbo[i];
906 trans = new TGeoTranslation("",x0,y0,0.5*(sB1->GetZ(0)+sB1->GetZ(1)));
907 vB1->AddNode(vTB0,i+1,trans);
908 rot = new TGeoRotation("",0.0,0.0,t);
909 rotrans = new TGeoCombiTrans("",x0,y0,0.0,rot);
910 vM0->AddNode(vTA0,i+1,rotrans);
911 //delete rot; // rot owned by AliITSv11GeometerySPD::CarbonFiberSector
913 vM0->AddNode(vA0,1,0);
914 vM0->AddNode(vB0,1,0);
916 vM0->AddNode(vB0,2,new TGeoRotation("",90.,0.,90.,90.,180.,0.));
930 //----------------------------------------------------------------------
931 Bool_t AliITSv11GeometrySPD::GetSectorMountingPoints(Int_t index,
932 Double_t &x0,Double_t &y0,
933 Double_t &x1,Double_t &y1,TGeoManager *mgr)const{
934 // Return's the mounting locations needed to mount the SPD ladders
935 // on the SPD Carbon fiber Sectors (A cross section). Coordinate
936 // system is that of the carbon fiber sector TVolume
937 // "ITSSPDCarbonFiberSupportSectorA0". Index numbering is as follows
943 // Int_t index the index for which location on the SPD sector [0-5]
945 // Double_t &x0 The x0 location or the ladder sector [cm]
946 // Double_t &y0 The y0 location of the ladder sector [cm]
947 // Double_t &x1 The x1 location or the ladder sector [cm]
948 // Double_t &y1 The y1 location of the ladder sector [cm]
949 // TGeoManager *mgr The Geometry manager to use [gGeoManager]
951 // Returns kTRUE if no problems incountered. Returns kFALSE
952 // if a problem was incountered (for example the shape has
954 TGeoVolume *spdSectorV=0;
955 TGeoXtru *spdSector=0;
958 x0 = x1 = y0 = y1 = 0.0;
959 if(index<0 || index>fSPDsectorPoints0.GetSize()){
960 Error("GetSectorMountingPoints","index=%d size=%d",index,
961 fSPDsectorPoints0.GetSize());
964 spdSectorV = mgr->GetVolume(fSPDsectorShapeName.Data());
966 Error("GetSectorMountingPoints","spdSectorV==0 name=%s",
967 fSPDsectorShapeName.Data());
970 spdSector = dynamic_cast<TGeoXtru*>(spdSectorV->GetShape());
972 Error("GetSectorMountingPoints","spdSector==0");
975 ixy0 = fSPDsectorPoints0.At(index);
976 ixy1 = fSPDsectorPoints1.At(index);
977 x0 = spdSector->GetX(ixy0);
978 y0 = spdSector->GetY(ixy0);
979 x1 = spdSector->GetX(ixy1);
980 y1 = spdSector->GetY(ixy1);
983 //----------------------------------------------------------------------
984 void AliITSv11GeometrySPD::SPDsectorShape(Int_t n,const Double_t *xc,
985 const Double_t *yc,const Double_t *r,const Double_t *ths,const Double_t *the,
986 Int_t npr,Int_t &m,Double_t **xp,Double_t **yp){
987 // Code to compute the points that make up the shape of the SPD
988 // Carbon fiber support sections
990 // Int_t n Size of arrays xc,yc, and r.
991 // Double_t *xc Array of x values for radii centers.
992 // Double_t *yc Array of y values for radii centers.
993 // Double_t *r Array of signed radii values.
994 // Double_t *ths Array of starting angles [degrees].
995 // Double_t *the Array of ending angles [degrees].
996 // Int_t npr The number of lines segments to aproximate the arc.
998 // Int_t m The number of enetries in the arrays *xp[npr+1]
1000 // Double_t **xp Array of x coordinate values of the line segments
1001 // which make up the SPD support sector shape.
1002 // Double_t **yp Array of y coordinate values of the line segments
1003 // which make up the SPD support sector shape.
1011 cout <<" X \t Y \t R \t S \t E"<< m <<endl;
1013 cout <<"{"<< xc[i] <<",";
1014 cout << yc[i] <<",";
1016 cout << ths[i] <<",";
1017 cout << the[i] <<"},"<< endl;
1019 } // end if GetDebug
1021 if(GetDebug(3)) cout <<"Double_t sA0 = ["<< n*(npr+1)+1<<"][";
1022 if(GetDebug(4)) cout <<"3]{";
1023 else if(GetDebug(3)) cout <<"2]{";
1026 t1 = (the[i]-ths[i])/t0;
1027 if(GetDebug(5)) cout<<"t1="<< t1<<endl;
1028 for(k=0;k<=npr;k++){
1029 t=ths[i]+((Double_t)k)*t1;
1030 xp[i][k] = TMath::Abs(r[i])*CosD(t)+xc[i];
1031 yp[i][k] = TMath::Abs(r[i])*SinD(t)+yc[i];
1033 cout << "{"<<xp[i][k]<<","<<yp[i][k];
1034 if(GetDebug(4)) cout <<","<<t;
1036 } // end if GetDebug
1038 if(GetDebug(3)) cout << endl;
1040 if(GetDebug(3)) cout<<"{"<<xp[0][0]<<","<<yp[0][0];
1041 if(GetDebug(4)) cout<<","<< ths[0];
1042 if(GetDebug(3)) cout<<"}}"<<endl;
1046 //----------------------------------------------------------------------
1047 void AliITSv11GeometrySPD::CreateFigure0(const Char_t *filepath,
1050 // Creates Figure 0 for the documentation of this class. In this
1051 // specific case, it creates the X,Y cross section of the SPD suport
1052 // section, center and ends. The output is written to a standard
1053 // file name to the path specificed.
1055 // const Char_t *filepath Path where the figure is to be drawn
1056 // const Char_t *type The type of file, default is gif.
1057 // TGeoManager *mgr The TGeoManager default gGeoManager
1062 TGeoXtru *sA0,*sA1,*sB0,*sB1;
1063 //TPolyMarker *pmA,*pmB;
1064 TPolyLine plA0,plA1,plB0,plB1;
1067 Double_t x=0.0,y=0.0;
1070 if(strcmp(filepath,"")){
1071 Error("CreateFigure0","filepath=%s type=%s",filepath,type);
1074 sA0 = (TGeoXtru*) mgr->GetVolume(
1075 "ITSSPDCarbonFiberSupportSectorA0_1")->GetShape();
1076 sA1 = (TGeoXtru*) mgr->GetVolume(
1077 "ITSSPDCarbonFiberSupportSectorAirA1_1")->GetShape();
1078 sB0 = (TGeoXtru*) mgr->GetVolume(
1079 "ITSSPDCarbonFiberSupportSectorEndB0_1")->GetShape();
1080 sB1 = (TGeoXtru*) mgr->GetVolume(
1081 "ITSSPDCarbonFiberSupportSectorEndAirB1_1")->GetShape();
1082 //pmA = new TPolyMarker();
1083 //pmA.SetMarkerStyle(2); // +
1084 //pmA.SetMarkerColor(7); // light blue
1085 //pmB = new TPolyMarker();
1086 //pmB.SetMarkerStyle(5); // X
1087 //pmB.SetMarkerColor(6); // purple
1088 plA0.SetPolyLine(sA0->GetNvert());
1089 plA0.SetLineColor(1); // black
1090 plA0.SetLineStyle(1);
1091 plA1.SetPolyLine(sA1->GetNvert());
1092 plA1.SetLineColor(2); // red
1093 plA1.SetLineStyle(1);
1094 plB0.SetPolyLine(sB0->GetNvert());
1095 plB0.SetLineColor(3); // Green
1096 plB0.SetLineStyle(2);
1097 plB1.SetPolyLine(sB1->GetNvert());
1098 plB1.SetLineColor(4); // Blue
1099 plB1.SetLineStyle(2);
1100 //for(i=0;i<kNRadii;i++) pmA.SetPoint(i,xyB1p[i][0],xyB1p[i][1]);
1101 //for(i=0;i<kNRadii;i++) pmB.SetPoint(i,xyB1p[i][0],xyB1p[i][1]);
1102 for(i=0;i<sA0->GetNvert();i++) plA0.SetPoint(i,sA0->GetX(i),sA0->GetY(i));
1103 for(i=0;i<sA1->GetNvert();i++) plA1.SetPoint(i,sA1->GetX(i),sA1->GetY(i));
1104 for(i=0;i<sB0->GetNvert();i++) plB0.SetPoint(i,sB0->GetX(i),sB0->GetY(i));
1105 for(i=0;i<sB1->GetNvert();i++) plB1.SetPoint(i,sB1->GetX(i),sB1->GetY(i));
1106 canvas = new TCanvas("AliITSv11GeometrySPDFig0","",1000,1000);
1107 canvas->Range(-3.,-3.,3.,3.);
1108 txt.SetTextSize(0.05);
1109 txt.SetTextAlign(33);
1110 txt.SetTextColor(1);
1111 txt.DrawLatex(2.9,2.9,"Section A-A outer Carbon Fiber surface");
1112 txt.SetTextColor(2);
1113 txt.DrawLatex(2.9,2.5,"Section A-A Inner Carbon Fiber surface");
1114 txt.SetTextColor(3);
1115 txt.DrawLatex(2.9,2.1,"Section E-E outer Carbon Fiber surface");
1116 txt.SetTextColor(4);
1117 txt.DrawLatex(2.9,1.7,"Section E-E Inner Carbon Fiber surface");
1128 for(i=0;i<kNRadii;i++){
1129 sprintf(chr,"%2d",i);txt.DrawLatex(x-0.1,y,chr);
1130 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x,y,chr);
1131 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x+0.5,y,chr);
1132 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x+1.0,y,chr);
1133 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x+1.5,y,chr);
1134 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x+2.0,y,chr);
1135 if(kTRUE) txt.DrawLatex(x+2.5,y,"A-A/E-E");
1136 else txt.DrawLatex(x+2.5,y,"E-E");
1138 txt.DrawLatex(x,y,"x_{c} mm");
1139 txt.DrawLatex(x+0.5,y,"y_{c} mm");
1140 txt.DrawLatex(x+1.0,y,"R mm");
1141 txt.DrawLatex(x+1.5,y,"#theta_{start}^{#circle}");
1142 txt.DrawLatex(x+2.0,y,"#theta_{end}^{#circle}");
1143 txt.DrawLatex(x+2.5,y,"Section");
1147 //______________________________________________________________________
1148 TGeoVolume* AliITSv11GeometrySPD::CreateLadder(Int_t layer,Double_t &length,
1149 Double_t &width,Double_t &thickness, TGeoManager *mgr){
1150 // Creates the "ladder" = silicon sensor + 5 chips.
1151 // All parts are implemented as TGeoBBox and inserted
1152 // into a container which is the return value of this method.
1153 // The sizes of the components come from drawings
1154 // of the Technical office of INFN Padova.
1155 // Due to the requirement to specify the sensitive volume
1156 // separately from the rest, the sensor is implemented as the
1157 // sum of a central sensitive part + a guard ring.
1158 // Also the bump-bondings are added in form of small cylinders.
1161 // - the layer which will own this ladder (MUST be 1 or 2)
1162 // - the used TGeoManager
1165 // - the container TGeoBBox (return value)
1166 // - the size of the container box (arguments passed by reference)
1169 // Here and in the other methods which contribute to the stave
1170 // definition a convention is used for the naming of the three
1171 // dimensions of the volumes:
1172 // - 'length' refers to the size in the Z direction of the
1173 // ALICE reference frame
1174 // - 'width' refers to the "large" dimension orthogonal to
1175 // Z axis in the local reference frame of the
1176 // object being implemented (e.g., 15.95 mm for
1178 // - 'thickness' refers to the "small" dimension orthogonal to
1179 // Z axis, which is also the direction along which
1180 // the components are superimposed on each other
1183 // all sizes taken are expressed in mm in drawings, and this is
1184 // kept as is, to avoid confusion the conversion is made
1185 // multiplying by the conversion factor
1187 // ** CRITICAL CHECK **
1188 // layer number can be ONLY 1 or 2
1189 if (layer != 1 && layer != 2) AliFatal("Layer number MUST be 1 or 2");
1191 // instantiate all required media
1192 TGeoMedium *medAir = mgr->GetMedium("Air");
1193 TGeoMedium *medSPDSiChip = mgr->GetMedium("SPD SI CHIP");
1194 TGeoMedium *medSi = mgr->GetMedium("Si");
1195 TGeoMedium *medBumpBond = mgr->GetMedium("BumpBond");
1197 // ** Define sizes **
1198 // they are expressed in mm in the drawings so they require conversion
1199 // 'length' is in the direction of the detector length (Z axis)
1200 // 'thickness' is obvious
1201 // 'width' is in the direction orthogonal to 'width' and 'thickness'
1203 // for the chip, also the spacing between them is required
1204 Double_t chipThickness = fgkmm * 0.150;
1205 Double_t chipWidth = fgkmm * 15.950;
1206 Double_t chipLength = fgkmm * 13.600;
1207 Double_t chipSpacing = fgkmm * 0.400;
1209 // for the sensor, we define the area of sensitive volume
1210 // while the guard ring is added as a separate piece
1211 Double_t sensThickness = fgkmm * 0.200;
1212 Double_t sensLength = fgkmm * 69.600;
1213 Double_t sensWidth = fgkmm * 13.920;
1214 Double_t guardRingWidth = fgkmm * 0.560;
1216 // bump bond is defined as a small stripe of height = 0.012 mm
1217 // and a suitable width to keep the same volume it has
1218 // before being compressed (a line of spheres of 0.025 mm radius)
1219 Double_t bbLength = fgkmm * 0.042;
1220 Double_t bbWidth = sensWidth;
1221 Double_t bbThickness = fgkmm * 0.012;
1222 Double_t bbPos = 0.080; // Z position w.r. to left pixel edge
1224 // ** Create volumes **
1225 // the container is the return value, and is built as a box
1226 // whose edges exactly enclose the stuff we inserted here,
1227 // filled with air. Its name depends on the layer number.
1229 length = sensLength + 2.0*guardRingWidth;
1230 thickness = sensThickness + chipThickness + bbThickness;
1231 TGeoVolume *container = mgr->MakeBox(Form("LAY%d_LADDER", layer),
1232 medAir, 0.5*thickness, 0.5*width, 0.5*length);
1233 // the chip is a simple box:
1234 TGeoVolume *volChip = mgr->MakeBox("CHIP", medSPDSiChip,
1235 0.5*chipThickness, 0.5*chipWidth, 0.5*chipLength);
1237 // the sensor is the union of a box and a border, to separate
1238 // sensitive part from the rest the sensitive volume (inner part)
1239 // is named according to the owner layer. To compute the shape
1240 // subtraction which is needed for this we create two shapes,
1241 // which are two boxes with the same center. The smaller one is
1242 // then used to define the sensor, while the subtraction of the two
1243 // is used for the guard ring.
1244 TGeoBBox *shSens = new TGeoBBox(0.5*sensThickness, 0.5*sensWidth,
1246 TGeoBBox *shIn = new TGeoBBox(sensThickness, 0.5*sensWidth,
1248 TGeoBBox *shOut = new TGeoBBox(0.5*sensThickness,
1249 0.5*sensWidth + guardRingWidth,
1250 0.5*sensLength + guardRingWidth);
1251 shIn->SetName("innerBox");
1252 shOut->SetName("outerBox");
1253 TGeoCompositeShape *shBorder = new TGeoCompositeShape("",
1254 "outerBox-innerBox");
1255 TGeoVolume *volSens = new TGeoVolume(Form("LAY%d_SENSOR", layer),
1257 TGeoVolume *volBorder = new TGeoVolume("GUARD_RING", shBorder, medSi);
1259 // one line of bumpbonds
1260 TGeoVolume *volBB = mgr->MakeBox("BB", medBumpBond, 0.5*bbThickness,
1261 0.5*bbWidth, 0.5*bbLength);
1263 // set colors of all objects for visualization
1264 volSens->SetLineColor(kYellow + 1);
1265 volChip->SetLineColor(kGreen);
1266 volBorder->SetLineColor(kYellow + 3);
1268 // translations for the chip box: direction of length and
1269 // thickness (moved down)
1270 TGeoTranslation *trChip[5] = {0, 0, 0, 0, 0};
1271 Double_t x = 0.5 * (chipThickness - thickness);
1275 for (i = 0; i < 5; i++) {
1276 z = -0.5*length + guardRingWidth + (Double_t)i*chipSpacing +
1277 ((Double_t)(i) + 0.5)*chipLength;
1278 trChip[i] = new TGeoTranslation(x, y, z);
1281 // translation for the sensor parts: direction of width (moved
1282 // to edge of container) and thickness (moved up)
1283 x = 0.5 * (thickness - sensThickness);
1284 y = 0.5 * (width - sensWidth - 2.0*guardRingWidth);
1286 TGeoTranslation *trSens = new TGeoTranslation(x, y, z);
1288 // translation for the bump bonds:
1289 // keep same y used for sensors, but change the Z
1290 TGeoTranslation *trBB[160];
1291 //x = 0.5 * (thickness - bbThickness) + 0.5*sensThickness;
1292 x = 0.5 * (thickness - bbThickness) - sensThickness;
1293 z = -0.5 * sensLength + guardRingWidth + fgkmm*0.425 - bbPos;
1294 for (i = 0; i < 160; i++) {
1295 trBB[i] = new TGeoTranslation(x, y, z);
1301 z += fgkmm * 0.625 + fgkmm * 0.2;
1308 // add nodes to container
1309 container->AddNode(volSens, 1, trSens);
1310 container->AddNode(volBorder, 1, trSens);
1311 for (i = 0; i < 160; i++) container->AddNode(volBB, i, trBB[i]);
1312 for (i = 0; i < 5; i++){
1313 container->AddNode(volChip, i + 2, trChip[i]);
1316 // return the container
1320 //______________________________________________________________________
1321 TGeoVolume* AliITSv11GeometrySPD::CreateGroundingFoilSingle(Bool_t kaptonLayer,
1322 Double_t &length, Double_t &width, Double_t &thickness, TGeoManager *mgr){
1324 // Creates the grounding foil layer made in Kapton.
1325 // Both layers of the grounding foil have the same shape, but
1326 // with small differences in the size of some parts (holes,
1327 // overall size). The Kapton layer is a little bit wider and
1328 // has smaller holes.
1330 // The complete object is created as the superimposition of
1331 // an XTRU with some holes
1333 // Whenever possible, the size of the parts is parameterized with
1334 // variable names, even if their value is fixed according
1335 // to the design parameters given by engineers' drawings.
1337 // Returns: a TGeoVolume object which contains all parts of this layer
1340 // The shape of the grounding foil is an irregular polygon, which
1341 // can easily be implemented as a TGeoXtru using the corners as
1342 // reference points:
1345 // +-----------------------------------------------------------------------------+
1347 // | +--------------+ +----------------+ 2
1349 // | 9 /-----+ 8 +------+ 4
1351 // | 11 /--------------/ 10
1355 // in total: 14 points (X is just a referencem but is unused in
1356 // the implementation. The whole shape can be subdivided into
1357 // sectors delimited by vertical lines passing througth the
1358 // points in the lower part of the shape. This convention is
1359 // used to names their length which is different for each one
1360 // (the widths, instead, are common for some)
1361 // instantiate the media:
1362 // - kapton/aluminum for the pysical volumes
1363 TGeoMedium *material = kaptonLayer ? mgr->GetMedium("KAPTON") :
1364 mgr->GetMedium("AL");
1370 thickness = fgkmm * 0.05;
1374 thickness = fgkmm * 0.02;
1377 // define the length of all sectors (from leftmost to rightmost)
1379 Double_t sectorLength[] = {140.71,2.48,26.78,4.0,10.0,24.4,10.0,24.81};
1381 sectorLength[0] -= 0.2;
1382 sectorLength[4] -= 0.2;
1383 sectorLength[5] += 0.4;
1384 sectorLength[6] -= 0.4;
1387 for (i = 0; i < 8; i++) {
1388 sectorLength[i] *= fgkmm;
1389 length += sectorLength[i];
1392 // as shown in the drawing, we have three different widths in
1394 Double_t widthMax = fgkmm * 15.95;
1395 Double_t widthMed1 = fgkmm * 15.00;
1396 Double_t widthMed2 = fgkmm * 11.00;
1397 Double_t widthMin = fgkmm * 4.40;
1399 widthMax -= fgkmm * 0.4;
1400 widthMed1 -= fgkmm * 0.4;
1401 widthMed2 -= fgkmm * 0.4;
1402 widthMin -= fgkmm * 0.4;
1406 // the vertices of the polygon are arrays correctly ordered in
1407 // the counterclockwise direction: initially we place the point
1408 // 0 in the origin, and all others will be defined accordingly
1409 Double_t x[14], y[14];
1413 x[ 1] = x[0] + length;
1419 x[ 3] = x[2] - sectorLength[7];
1425 x[ 5] = x[4] - sectorLength[6];
1431 x[ 7] = x[6] - sectorLength[5];
1437 x[ 9] = x[8] - sectorLength[4];
1440 x[10] = x[9] - sectorLength[3];
1443 x[11] = x[10] - sectorLength[2];
1446 x[12] = x[11] - sectorLength[1];
1452 // then, we shift all points in such a way that the origin will
1453 // be at the centers
1454 for (i = 0; i < 14; i++) {
1461 sprintf(shName, "SH_%sGFOIL_FULL", type);
1462 TGeoXtru *shGroundFull = new TGeoXtru(2);
1463 shGroundFull->SetName(shName);
1464 shGroundFull->DefinePolygon(14, x, y);
1465 shGroundFull->DefineSection(0, -0.5*thickness, 0., 0., 1.0);
1466 shGroundFull->DefineSection(1, 0.5*thickness, 0., 0., 1.0);
1468 // this volume contains some holes which are here implemented
1469 // as simple boxes of fixed size, which are displaced along the
1470 // shape itself and then composed using the facilities of the
1473 Double_t holeLength = fgkmm * 10.00;
1474 Double_t holeWidth = fgkmm * 7.50;
1475 Double_t holeSepX0 = fgkmm * 7.05;//separation between center
1476 //of first hole and left border
1477 Double_t holeSepXC = fgkmm * 14.00;//separation between the
1478 // centers of two consecutive holes
1479 Double_t holeSepX1 = fgkmm * 15.42;//separation between centers
1480 // of 5th and 6th hole
1481 Double_t holeSepX2 = fgkmm * 22.00;//separation between centers
1482 // of 10th and 11th hole
1484 holeSepX0 -= fgkmm * 0.2;
1485 holeLength += fgkmm * 0.4;
1486 holeWidth += fgkmm * 0.4;
1489 // X position of hole center (will change for each hole)
1490 Double_t holeX = -0.5*length;
1491 // Y position of center of all holes (= 4.4 mm from upper border)
1492 Double_t holeY = 0.5*(width - holeWidth) - widthMin;
1493 //if (!kaptonLayer) holeY += 0.02;
1495 // create a shape for the holes (common)
1497 sprintf(holeName, "%sHOLE", type);
1498 TGeoBBox *shHole = 0;
1499 shHole = new TGeoBBox(holeName,0.5*holeLength,0.5*holeWidth,thickness);
1501 // insert the holes in the XTRU shape:
1502 // starting from the first value of X, they are simply shifted
1505 TGeoTranslation *transHole[11];
1506 TString strComposite(shName);
1507 strComposite.Append("-(");
1508 for (Int_t i = 0; i < 11; i++) {
1509 // set the position of the hole, depending on index
1525 sprintf(trName, "%sTR%d", type, i);
1526 transHole[i] = new TGeoTranslation(trName, holeX, holeY, 0.0);
1527 transHole[i]->RegisterYourself();
1528 strComposite.Append(holeName);
1529 strComposite.Append(":");
1530 strComposite.Append(trName);
1531 if (i < 10) strComposite.Append("+");
1532 //MM cout << holeX << endl;
1534 strComposite.Append(")");
1535 //MM cout << strComposite.Data() << endl;
1537 // create composite shape (with holes)
1538 TGeoCompositeShape *shGround = new TGeoCompositeShape(
1539 Form("SH_%sGFOIL", type), strComposite.Data());
1541 // create the volume
1542 TGeoVolume *vol = new TGeoVolume(Form("%sGFOIL",type),shGround,
1547 //______________________________________________________________________
1548 TGeoVolume* AliITSv11GeometrySPD::CreateGroundingFoilSingle(
1549 Bool_t kaptonLayer, Double_t &length, Double_t &width,
1550 Double_t &thickness, TGeoManager *mgr){
1551 // Creates the grounding foil layer made in Kapton.
1552 // Both layers of the grounding foil have the same shape, but with small
1553 // differences in the size of some parts (holes, overall size).
1554 // The Kapton layer is a little bit wider and has smaller holes.
1556 // The complete object is created as the sum of the following parts:
1557 // 1) the part which is connected to the chips, which is a
1558 // simple BOX with some box-shaped holes at regular intervals
1559 // 2) a trapezoidal connection where the Y size changes
1560 // 3) another box with a unique hole of the same shape and size as above
1561 // 4) another trapezoidal connection where the Y size changes
1562 // 5) a final part which is built as a sequence of 4 BOX volumes
1563 // where the first and the third are equal and the others have
1566 // Whenever possible, the size of the parts is parameterized with
1567 // variable names, even if their value is fixed according
1568 // to the design parameters given by engineers' drawings.
1570 // Returns: a TGeoVolume object which contanis all parts of this layer
1573 // instantiate the media:
1574 // - vacuum for the container volume
1575 // - kapton for the pysical volumes
1576 TGeoMedium *vacuum = mgr->GetMedium("VACUUM");
1577 TGeoMedium *material = mgr->GetMedium("KAPTON");
1579 // === Define size of all elements ===
1580 Double_t sizeZ = fgkmm * 0.05;
1582 Double_t part1X = fgkmm * 140.71;
1583 Double_t part2X = fgkmm * 2.48;
1584 Double_t part3X = fgkmm * 26.78;
1585 Double_t part4X = fgkmm * 4.00;
1586 Double_t part5X = fgkmm * 10.00;
1587 Double_t part6X = fgkmm * 24.40;
1588 Double_t part7X = fgkmm * 10.00;
1589 Double_t part8X = fgkmm * 24.81;
1591 Double_t sizeYMax = fgkmm * 15.95;
1592 Double_t sizeYMed1 = fgkmm * 15.00;
1593 Double_t sizeYMed2 = fgkmm * 11.00;
1594 Double_t sizeYMin = fgkmm * 4.40;
1596 Double_t holeX = fgkmm * 10.00;
1597 Double_t holeY = fgkmm * 7.50;
1598 Double_t holeSepX = fgkmm * 14.00; // separation between the
1599 // centers of two consecutive
1601 Double_t holeSepX1 = fgkmm * 1.42; // to be added after 4th hole
1603 Double_t holeFirstX = fgkmm * 7.05; // position of center of first
1605 Double_t holeSepY = fgkmm * 4.40; // dist between hole's and
1606 // volume's upper border
1607 Double_t holeAloneX = fgkmm * 13.28; // position of hole center
1610 // correct data in case we are on Aluminum foil
1612 material = mgr->GetMedium("AL");
1613 sizeZ = fgkmm * 0.02;
1614 part1X -= fgkmm * 0.2;
1615 part5X -= fgkmm * 0.2;
1616 part6X += fgkmm * 0.4;
1617 part7X -= fgkmm * 0.4;
1619 sizeYMax -= fgkmm * 0.4;
1620 sizeYMed1 -= fgkmm * 0.4;
1621 sizeYMed2 -= fgkmm * 0.4;
1622 sizeYMin -= fgkmm * 0.4;
1624 holeX += fgkmm * 0.4;
1625 holeY += fgkmm * 0.4;
1626 holeFirstX -= fgkmm * 0.2;
1627 holeSepY -= fgkmm * 0.4;
1630 // define names for the object
1632 if (kaptonLayer) strcpy(type, "KAP"); else strcpy(type, "ALU");
1634 // compute full length and width
1635 length = part1X + part2X + part3X + part4X + part5X + part6X +
1640 // grounding foil world, bounded exactly around the limits
1642 TGeoVolume *container = mgr->MakeBox(Form("GFOIL_%s", type),
1643 vacuum, 0.5*length, 0.5*sizeYMax, 0.5*sizeZ);
1645 // === PART 1: box with holes ===
1647 TGeoBBox *shBox1 = 0, *shHole = 0;
1648 shBox1 = new TGeoBBox(Form("GF%s_BOX1", type), 0.5*part1X,
1649 0.5*sizeYMax, 0.5*sizeZ);
1650 shHole = new TGeoBBox(Form("GF%s_HOLE", type), 0.5*holeX, 0.5*holeY,
1653 // define the position of all holes and compose the expression
1654 // to define the composite shape (box - holes)
1655 Double_t firstX = -0.5*part1X + holeFirstX;
1656 Double_t transY = 0.5*sizeYMax - holeSepY - 0.5*holeY;
1658 TGeoTranslation *transHole[10];
1659 TString strComposite(Form("%s - (", shBox1->GetName()));
1660 for (Int_t i = 0; i < 10; i++) {
1661 transX = firstX + (Double_t)i * holeSepX;
1662 if (i > 4) transX += holeSepX1;
1663 transHole[i] = new TGeoTranslation(Form("TGF%s_HOLE%d",type,i),
1664 transX, transY, 0.0);
1665 transHole[i]->RegisterYourself();
1666 strComposite.Append(Form("%s:%s", shHole->GetName(),
1667 transHole[i]->GetName()));
1668 if (i < 9) strComposite.Append("+");
1669 else strComposite.Append(")");
1671 // create composite shape
1672 TGeoCompositeShape *shPart1 = new TGeoCompositeShape(
1673 Form("GF%s_PART1_SHAPE", type), strComposite.Data());
1674 // create the volume
1675 TGeoVolume *volPart1 = new TGeoVolume(Form("GF%s_PART1", type),
1678 // === PART 2: first trapezoidal connection
1680 TGeoArb8 *shTrap1 = new TGeoArb8(0.5*sizeZ);
1681 shTrap1->SetVertex(0, -0.5*part2X, 0.5*sizeYMax);
1682 shTrap1->SetVertex(1, 0.5*part2X, 0.5*sizeYMax);
1683 shTrap1->SetVertex(2, 0.5*part2X, 0.5*sizeYMax - sizeYMed1);
1684 shTrap1->SetVertex(3, -0.5*part2X, -0.5*sizeYMax);
1685 shTrap1->SetVertex(4, -0.5*part2X, 0.5*sizeYMax);
1686 shTrap1->SetVertex(5, 0.5*part2X, 0.5*sizeYMax);
1687 shTrap1->SetVertex(6, 0.5*part2X, 0.5*sizeYMax - sizeYMed1);
1688 shTrap1->SetVertex(7, -0.5*part2X, -0.5*sizeYMax);
1689 TGeoVolume *volPart2 = new TGeoVolume(Form("GF%s_PART2", type),
1692 // === PART 3: other box with one hole
1694 TGeoBBox *shBox2 = 0;
1695 shBox2 = new TGeoBBox(Form("GF%s_BOX2", type), 0.5*part3X,
1696 0.5*sizeYMed1, 0.5*sizeZ);
1698 // define the position of the hole
1699 transX = holeAloneX - 0.5*part3X;
1700 TGeoTranslation *transHoleAlone = new TGeoTranslation(
1701 Form("TGF%s_HOLE_ALONE", type), transX, transY, 0.0);
1702 transHoleAlone->RegisterYourself();
1703 // create composite shape
1704 TGeoCompositeShape *shPart3 = new TGeoCompositeShape(
1705 Form("GF%sPART3_SHAPE", type),
1706 Form("%s - %s:%s", shBox2->GetName(),
1707 shHole->GetName(), transHoleAlone->GetName()));
1708 // create the volume
1709 TGeoVolume *volPart3 = new TGeoVolume(Form("GF%s_PART3", type),
1712 // === PART 4: second trapezoidal connection
1714 TGeoArb8 *shTrap2 = new TGeoArb8(0.5*sizeZ);
1715 shTrap2->SetVertex(0, -0.5*part4X, 0.5*sizeYMed1);
1716 shTrap2->SetVertex(1, 0.5*part4X, 0.5*sizeYMed1);
1717 shTrap2->SetVertex(2, 0.5*part4X, 0.5*sizeYMed1 - sizeYMed2);
1718 shTrap2->SetVertex(3, -0.5*part4X, -0.5*sizeYMed1);
1719 shTrap2->SetVertex(4, -0.5*part4X, 0.5*sizeYMed1);
1720 shTrap2->SetVertex(5, 0.5*part4X, 0.5*sizeYMed1);
1721 shTrap2->SetVertex(6, 0.5*part4X, 0.5*sizeYMed1 - sizeYMed2);
1722 shTrap2->SetVertex(7, -0.5*part4X, -0.5*sizeYMed1);
1723 TGeoVolume *volPart4 = new TGeoVolume(Form("GF%s_PART4", type),
1726 // === PART 5 --> 8: sequence of boxes ===
1728 TGeoVolume *volPart5 = mgr->MakeBox(Form("GF%s_BOX3", type),
1729 material, 0.5*part5X, 0.5*sizeYMed2, 0.5*sizeZ);
1730 TGeoVolume *volPart6 = mgr->MakeBox(Form("GF%s_BOX4", type),
1731 material, 0.5*part6X, 0.5*sizeYMin , 0.5*sizeZ);
1732 TGeoVolume *volPart7 = mgr->MakeBox(Form("GF%s_BOX5", type),
1733 material, 0.5*part7X, 0.5*sizeYMed2, 0.5*sizeZ);
1734 TGeoVolume *volPart8 = mgr->MakeBox(Form("GF%s_BOX6", type),
1735 material, 0.5*part8X, 0.5*sizeYMin , 0.5*sizeZ);
1737 // === SET COLOR ===
1739 volPart1->SetLineColor(kRed + 3);
1740 volPart2->SetLineColor(kRed + 3);
1741 volPart3->SetLineColor(kRed + 3);
1742 volPart4->SetLineColor(kRed + 3);
1743 volPart5->SetLineColor(kRed + 3);
1744 volPart6->SetLineColor(kRed + 3);
1745 volPart7->SetLineColor(kRed + 3);
1746 volPart8->SetLineColor(kRed + 3);
1748 volPart1->SetLineColor(kGreen);
1749 volPart2->SetLineColor(kGreen);
1750 volPart3->SetLineColor(kGreen);
1751 volPart4->SetLineColor(kGreen);
1752 volPart5->SetLineColor(kGreen);
1753 volPart6->SetLineColor(kGreen);
1754 volPart7->SetLineColor(kGreen);
1755 volPart8->SetLineColor(kGreen);
1756 } // end if (kaptonLayer)
1758 // === TRANSLATION OF ALL PARTS ===
1760 transX = 0.5*(part1X - length);
1761 TGeoTranslation *transPart1 = new TGeoTranslation(transX, 0.0, 0.0);
1762 transX += 0.5*(part1X + part2X);
1763 TGeoTranslation *transPart2 = new TGeoTranslation(transX, 0.0, 0.0);
1764 transX += 0.5*(part2X + part3X);
1765 transY = 0.5*(sizeYMax - sizeYMed1);
1766 TGeoTranslation *transPart3 = new TGeoTranslation(transX, transY, 0.0);
1767 transX += 0.5*(part3X + part4X);
1768 TGeoTranslation *transPart4 = new TGeoTranslation(transX, transY, 0.0);
1769 transX += 0.5*(part4X + part5X);
1770 transY = 0.5*(sizeYMax - sizeYMed2);
1771 TGeoTranslation *transPart5 = new TGeoTranslation(transX, transY, 0.0);
1772 transX += 0.5*(part5X + part6X);
1773 transY = 0.5*(sizeYMax - sizeYMin);
1774 TGeoTranslation *transPart6 = new TGeoTranslation(transX, transY, 0.0);
1775 transX += 0.5*(part6X + part7X);
1776 transY = 0.5*(sizeYMax - sizeYMed2);
1777 TGeoTranslation *transPart7 = new TGeoTranslation(transX, transY, 0.0);
1778 transX += 0.5*(part7X + part8X);
1779 transY = 0.5*(sizeYMax - sizeYMin);
1780 TGeoTranslation *transPart8 = new TGeoTranslation(transX, transY, 0.0);
1782 // add the partial volumes to the container
1783 container->AddNode(volPart1, 1, transPart1);
1784 container->AddNode(volPart2, 2, transPart2);
1785 container->AddNode(volPart3, 3, transPart3);
1786 container->AddNode(volPart4, 4, transPart4);
1787 container->AddNode(volPart5, 5, transPart5);
1788 container->AddNode(volPart6, 6, transPart6);
1789 container->AddNode(volPart7, 7, transPart7);
1790 container->AddNode(volPart8, 8, transPart8);
1795 //______________________________________________________________________
1796 TGeoVolume* AliITSv11GeometrySPD::CreateGroundingFoil(Double_t &thickness,
1798 // Joins two Kapton and two Aluminum layers of the grounding foil
1799 // in order to create the complete grounding foil for a whole stave.
1800 // into a unique container volume, which is returned as output.
1801 // The use of the TGeoXtru shape requires that in the separate
1802 // foils, the Z axis lies perpendicularly to the polygonal basis
1803 // of this shape; this caused the components to have their Z
1804 // axis corresponding to the X axis of the ALICE reference frame
1805 // and vieceversa; to correct this, a rotation is necessary
1806 // around their middle axis, to exchange X and Z axes and displace
1807 // the object correctly in the ALICE frame.
1810 // - the sizes of the container box (passed by reference and
1812 // - the TGeoManager
1815 // - the container TGeoBBox (return value)
1816 // - the size of the container (reference variables)
1819 // sizes of the added volumes, which are filled by passing them
1820 // to the volume creation methods
1821 Double_t kpLength, kpWidth, kpThick;
1822 Double_t alLength, alWidth, alThick;
1823 // separation between left and right volumes
1824 Double_t separation = fgkmm * 1.42;
1826 // create the two component volumes (each one will be replicated
1827 // twice) this gives also the size of their virtual container
1828 // boxes (just a reference, not a volume)
1829 TGeoVolume *kVol = CreateGroundingFoilSingle(kTRUE, kpLength,
1830 kpWidth, kpThick, mgr);
1831 TGeoVolume *aVol = CreateGroundingFoilSingle(kFALSE, alLength,
1832 alWidth, alThick, mgr);
1833 kVol->SetLineColor(kRed);
1834 aVol->SetLineColor(kGray);
1836 // kapton leads the total size of the foil (including spagcing
1837 // of 1.42 mm between them in the center)
1838 Double_t length, width;
1839 length = 2.0 * kpLength + separation;
1841 thickness = kpThick + alThick;
1843 // create the container
1844 TGeoMedium *vacuum = mgr->GetMedium("VACUUM");
1845 TGeoVolume *container = mgr->MakeBox("GFOIL", vacuum, 0.5*thickness,
1846 0.5*width, 0.5*length);
1848 // create the common correction rotations
1849 TGeoRotation *rotCorr1 = new TGeoRotation(*gGeoIdentity);
1850 TGeoRotation *rotCorr2 = new TGeoRotation(*gGeoIdentity);
1851 rotCorr1->RotateY(-90.0);
1852 rotCorr2->RotateY( 90.0);
1854 // compute the translations to place the objects at the edges of
1855 // the volume the kapton foils are also shifted down, and the
1856 // aluminum foils are shifted up with respect to the thickness
1858 TGeoTranslation *kTrans1 = new TGeoTranslation(0.5*(-thickness+kpThick),
1860 0.5*(length-kpLength));
1861 TGeoTranslation *kTrans2 = new TGeoTranslation(0.5*(-thickness+kpThick),
1863 0.5*(-length+kpLength));
1864 TGeoTranslation *aTrans1 = new TGeoTranslation(0.5*(thickness-alThick),
1866 0.5*(length-alLength)-0.02);
1867 TGeoTranslation *aTrans2 = new TGeoTranslation(0.5*(thickness-alThick),
1869 0.5*(-length+alLength)+0.02);
1871 // combine translations and rotations
1872 TGeoCombiTrans *kCombi1 = new TGeoCombiTrans(*kTrans1, *rotCorr1);
1873 TGeoCombiTrans *kCombi2 = new TGeoCombiTrans(*kTrans2, *rotCorr2);
1874 TGeoCombiTrans *aCombi1 = new TGeoCombiTrans(*aTrans1, *rotCorr1);
1875 TGeoCombiTrans *aCombi2 = new TGeoCombiTrans(*aTrans2, *rotCorr2);
1878 container->AddNode(kVol, 0, kCombi1);
1879 container->AddNode(kVol, 1, kCombi2);
1880 container->AddNode(aVol, 0, aCombi1);
1881 container->AddNode(aVol, 1, aCombi2);
1886 //______________________________________________________________________
1887 TGeoVolume* AliITSv11GeometrySPD::CreateMCMBase(TGeoManager *geom) const{
1888 // Creates the MCM basis volume.
1889 // It is a little bit more complicated because this is a plain base
1890 // with a poly shape similar to the one of grounding foil but
1891 // there are also some chips glued to its base and covered with
1894 // The complete MCM object is created as the sum of the following parts:
1895 // 1) a planar basis shaped according to the MCM typical shape
1896 // 2) some boxes which represent the chips and devices mounted on
1898 // 3) a cave cap which covers the portion of MCM containing these chips
1900 // Due to the different widths of MCM, it is implemented in a
1901 // more complicated way:
1902 // - cap and chips will define a sub-volume of this structure,
1903 // which can be bounded by a complete box
1904 // - base of MCM will be a separate volume
1905 // - these two objects will need to be glued together into an
1906 // upper-level volume
1908 // This metod creates only the thin base (point 1 in the list)
1912 TGeoMedium *medBase = geom->GetMedium("MCM BASE");
1914 // parameterize the interesting sizes of MCM
1915 // it is divided into 3 sectors which have different size in
1916 // X and Y and are connected by trapezoidal-based shapes,
1917 // where the oblique angle makes a 45 degrees angle with the
1918 // vertical, so that the X size and Y size of these "intermezzo"'s
1920 // +--------------------------------+
1922 // | sect 1 --------------------+
1924 Double_t sizeZ = fgkmm * 0.35;
1925 Double_t sizeXtot = fgkmm * 105.6;
1926 Double_t sizeXsector[3] = {fgkmm * 28.4, fgkmm * 41.4, fgkmm * 28.8};
1927 Double_t sizeYsector[3] = {fgkmm * 15.0, fgkmm * 11.0, fgkmm * 8.0};
1928 Double_t sizeSep01 = fgkmm * 4.0, sizeSep12 = fgkmm * 3.0;
1929 Double_t sizeHole = fgkmm * 1.0;
1930 Double_t posHoleX = fgkmm * -0.5*sizeXtot + 26.7 + 0.5*sizeHole;
1931 Double_t posHoleY = fgkmm * -0.5*sizeYsector[0] + 0.5*sizeHole;
1933 // define the shape of base volume as an XTRU with two identical faces
1934 // distantiated by the width of the itself
1935 Double_t x[8], y[8];
1936 x[0] = -0.5*sizeXtot;
1937 y[0] = 0.5*sizeYsector[0];
1941 y[2] = y[1] - sizeYsector[2];
1942 x[3] = x[2] - sizeXsector[2];
1944 x[4] = x[3] - sizeSep12;
1945 y[4] = y[3] - sizeSep12;
1946 x[5] = x[4] - sizeXsector[1];
1948 x[6] = x[5] - sizeSep01;
1949 y[6] = y[5] - sizeSep01;
1954 TGeoXtru *shPoly = new TGeoXtru(2);
1955 shPoly->SetName("SH_MCMBASE_POLY");
1956 shPoly->DefinePolygon(8, x, y);
1957 shPoly->DefineSection(0, -0.5*sizeZ, 0., 0., 1.0);
1958 shPoly->DefineSection(1, 0.5*sizeZ, 0., 0., 1.0);
1960 // create small hole
1961 TGeoBBox *shHole = 0;
1962 shHole = new TGeoBBox("SH_MCMBASE_HOLE", 0.5*sizeHole, 0.5*sizeHole,
1964 TGeoTranslation *transHole = new TGeoTranslation("TR_MCMBASE_HOLE",
1965 posHoleX, posHoleY, 0.0);
1966 transHole->RegisterYourself();
1968 // create shape intersection
1969 TGeoCompositeShape *shBase = new TGeoCompositeShape("SH_MCMBASE",
1970 "SH_MCMBASE_POLY - SH_MCMBASE_HOLE:TR_MCMBASE_HOLE");
1973 TGeoVolume *volBase = new TGeoVolume("VOL_MCMBASE", shBase, medBase);
1974 volBase->SetLineColor(kRed);
1978 //______________________________________________________________________
1979 TGeoVolume* AliITSv11GeometrySPD::CreateMCMCoverBorder(TGeoManager *geom){
1980 // Creates the MCM basis volume.
1981 // It is a little bit more complicated because this is a plain base
1982 // with a poly shape similar to the one of grounding foil but there
1983 // are also some chips glued to its base and covered with a cave cap.
1985 // The complete MCM object is created as the sum of the following parts:
1986 // 1) a planar basis shaped according to the MCM typical shape
1987 // 2) some boxes which represent the chips and devices mounted on
1989 // 3) a cave cap which covers the portion of MCM containing these chips
1991 // Due to the different widths of MCM, it is implemented in a more
1993 // - cap and chips will define a sub-volume of this structure,
1994 // which can be bounded by a complete box
1995 // - base of MCM will be a separate volume
1996 // - these two objects will need to be glued together into an
1997 // upper-level volume
1999 // This metod creates the thicker cap and its contents (points 2-3
2000 // in the list). Since it covers only two of the three sectors of
2001 // the MCM base with different width
2002 // the computations and variables related to the largest sector
2003 // are removed, while
2004 // the other are the same as the other part of the MCM.
2008 TGeoMedium *medCap = geom->GetMedium("MCM COVER");
2010 // parameterize the interesting sizes of MCM
2011 // it is divided into 3 sectors which have different size in
2012 // X and Y and are connected by trapezoidal-based shapes,
2013 // where the oblique angle makes a 45 degrees angle with the
2014 // vertical, so that the X size and Y size of these "intermezzo"'s
2016 // +--------------------------------+
2018 // | sect 1 --------------------+
2020 Double_t sizeZ = fgkmm * 0.3;
2021 Double_t capHeight = fgkmm * 1.7 - sizeZ;
2022 Double_t sizeXtot = fgkmm * 73.2;
2023 Double_t sizeXsector[2] = {fgkmm * 41.4, fgkmm * 28.8};
2024 Double_t sizeYsector[2] = {fgkmm * 11.0, fgkmm * 8.0};
2025 Double_t sizeSep = fgkmm * 3.0;
2027 // === PART 1: border ===
2029 // define the shape of base volume as an XTRU with two identical faces
2030 // distantiated by the width of the itself
2031 Double_t x[6], y[6];
2032 x[0] = -0.5*sizeXtot;
2033 y[0] = 0.5*sizeYsector[0];
2037 y[2] = y[1] - sizeYsector[1];
2038 x[3] = x[2] - sizeXsector[1];
2040 x[4] = x[3] - sizeSep;
2041 y[4] = y[3] - sizeSep;
2045 // create outer border shape with above coordinates
2046 TGeoXtru *capOut = new TGeoXtru(2);
2047 capOut->SetName("SH_MCMCAPOUT");
2048 capOut->DefinePolygon(6, x, y);
2049 capOut->DefineSection(0, -0.5*capHeight, 0., 0., 1.0);
2050 capOut->DefineSection(1, 0.5*capHeight, 0., 0., 1.0);
2052 // the inner border is built similarly but subtracting the thickness
2053 Double_t angle = 45.0;
2054 Double_t cs = TMath::Cos( 0.5*(TMath::Pi() - angle*TMath::DegToRad()) );
2055 Double_t xin[6], yin[6];
2056 xin[0] = x[0] + sizeZ;
2057 yin[0] = y[0] - sizeZ;
2058 xin[1] = x[1] - sizeZ;
2061 yin[2] = y[2] + sizeZ;
2062 xin[3] = x[3] - sizeZ*cs;
2064 xin[4] = xin[3] - sizeSep;
2065 yin[4] = y[4] + sizeZ;
2069 // create inner border shape
2070 TGeoXtru *capIn = new TGeoXtru(2);
2071 capIn->SetName("SH_MCMCAPIN");
2072 capIn->DefinePolygon(6, xin, yin);
2073 capIn->DefineSection(0, -0.5*capHeight-0.01, 0., 0., 1.0);
2074 capIn->DefineSection(1, 0.5*capHeight+0.01, 0., 0., 1.0);
2077 TGeoCompositeShape *shBorder = new TGeoCompositeShape("SH_MCMCAPBORDER",
2078 "SH_MCMCAPOUT-SH_MCMCAPIN");
2081 TGeoVolume *volBorder = new TGeoVolume("VOL_MCMCAPBORDER", shBorder,
2083 volBorder->SetLineColor(kGreen);
2087 //______________________________________________________________________
2088 TGeoVolume* AliITSv11GeometrySPD::CreateMCMCoverTop(TGeoManager *geom){
2089 // Creates the MCM basis volume.
2090 // It is a little bit more complicated because this is a plain base
2091 // with a poly shape similar to the one of grounding foil but
2093 // some chips glued to its base and covered with a cave cap.
2095 // The complete MCM object is created as the sum of the following parts:
2096 // 1) a planar basis shaped according to the MCM typical shape
2097 // 2) some boxes which represent the chips and devices mounted on
2099 // 3) a cave cap which covers the portion of MCM containing these chips
2101 // Due to the different widths of MCM, it is implemented in a
2102 // more complicated way:
2103 // - cap and chips will define a sub-volume of this structure,
2104 // which can be bounded by a complete box
2105 // - base of MCM will be a separate volume
2106 // - these two objects will need to be glued together into an
2107 // upper-level volume
2109 // This metod creates the thicker cap and its contents (points
2110 // 2-3 in the list). Since it covers only two of the three
2111 // sectors of the MCM base with different width
2112 // the computations and variables related to the largest sector
2113 // are removed, while the other are the same as the other part
2118 TGeoMedium *medCap = geom->GetMedium("MCM COVER");
2120 // parameterize the interesting sizes of MCM
2121 // it is divided into 3 sectors which have different size in X
2122 // and Y and are connected by trapezoidal-based shapes, where
2123 // the oblique angle makes a 45 degrees angle with the vertical,
2124 // so that the X size and Y size of these "intermezzo"'s is the same
2125 // +--------------------------------+
2127 // | sect 1 --------------------+
2129 Double_t sizeZ = fgkmm * 0.3;
2130 Double_t sizeXtot = fgkmm * 73.2;
2131 Double_t sizeXsector[2] = {fgkmm * 41.4, fgkmm * 28.8};
2132 Double_t sizeYsector[2] = {fgkmm * 11.0, fgkmm * 8.0};
2133 Double_t sizeSep = fgkmm * 3.0;
2135 // === PART 1: border ===
2137 // define the shape of base volume as an XTRU with two identical faces
2138 // distantiated by the width of the itself
2139 Double_t x[6], y[6];
2140 x[0] = -0.5*sizeXtot;
2141 y[0] = 0.5*sizeYsector[0];
2145 y[2] = y[1] - sizeYsector[1];
2146 x[3] = x[2] - sizeXsector[1];
2148 x[4] = x[3] - sizeSep;
2149 y[4] = y[3] - sizeSep;
2153 // create outer border shape with above coordinates
2154 TGeoXtru *capOut = new TGeoXtru(2);
2155 capOut->SetName("SH_MCMCAPOUT");
2156 capOut->DefinePolygon(6, x, y);
2157 capOut->DefineSection(0, -0.5*sizeZ, 0., 0., 1.0);
2158 capOut->DefineSection(1, 0.5*sizeZ, 0., 0., 1.0);
2160 // the inner border is built similarly but subtracting the thickness
2161 Double_t angle = 45.0;
2162 Double_t cs = TMath::Cos( 0.5*(TMath::Pi() - angle*TMath::DegToRad()) );
2163 Double_t xin[6], yin[6];
2164 xin[0] = x[0] + sizeZ;
2165 yin[0] = y[0] - sizeZ;
2166 xin[1] = x[1] - sizeZ;
2169 yin[2] = y[2] + sizeZ;
2170 xin[3] = x[3] - sizeZ*cs;
2172 xin[4] = xin[3] - sizeSep;
2173 yin[4] = y[4] + sizeZ;
2177 // coverage of upper part (equal to external border, but full)
2178 TGeoXtru *shCover = new TGeoXtru(2);
2179 shCover->SetName("SH_MCMCAPCOVER");
2180 shCover->DefinePolygon(6, x, y);
2181 shCover->DefineSection(0, -0.5*sizeZ, 0., 0., 1.0);
2182 shCover->DefineSection(1, 0.5*sizeZ, 0., 0., 1.0);
2185 TGeoVolume *volCover = new TGeoVolume("VOL_MCMCAPCOVER", shCover,
2187 volCover->SetLineColor(kBlue);
2191 //______________________________________________________________________
2192 TGeoVolumeAssembly* AliITSv11GeometrySPD::CreateStave(Int_t layer,
2193 Double_t &fullThickness, TGeoManager *mgr){
2194 // Creates the complete stave as an assembly which contains all
2195 // the stuff defined in the "CreateStaveBase" method (which are
2196 // the thin part of the structure) and adds to this the thick
2197 // cover of the MCM and the Pixel bus. This is done as an
2198 // assembly to avoid the problem of a "ghost" overlap which occurs
2199 // when putting the stave on the carbon fiber sector, in the case
2200 // that we define it as a volume container.
2203 // - the layer where the stave has to be put (hard check on this)
2204 // - the geometry manager
2207 // ** CRITICAL CHECK **
2208 // layer number can be ONLY 1 or 2
2209 if (layer != 1 && layer != 2)
2210 AliFatal("Required that layer number be 1 or 2");
2212 // sizes regarding the components
2213 Double_t baseWidth, baseHeight, baseThickness;
2214 Double_t mcmCapBorderThickness = fgkmm * 0.3;
2215 Double_t mcmCapThickness = fgkmm * 1.7 - mcmCapBorderThickness;
2216 Double_t mcmCapHeight = fgkmm * 11.0;
2217 Double_t mcmCapWidth = fgkmm * 73.2;
2220 TGeoVolumeAssembly *container = new TGeoVolumeAssembly(
2221 Form("LAY%d_FULLSTAVE", layer));
2223 // create subvolumes
2224 TGeoVolume *staveBase = CreateStaveBase(layer, baseWidth, baseHeight,
2225 baseThickness, mgr);
2226 TGeoVolume *mcmCapBorder = CreateMCMCoverBorder(mgr);
2227 TGeoVolume *mcmCapTop = CreateMCMCoverTop(mgr);
2229 TGeoVolumeAssembly *bus0 = CreatePixelBusAndExtensions(kTRUE, mgr);
2231 TGeoVolumeAssembly *bus1 = CreatePixelBusAndExtensions(kFALSE, mgr);
2233 // the full width and height of the area which contains all
2234 // components corresponds to the one of the stave base built with
2235 // the "CreateStaveBase" method while the thickness must be
2236 // computed as the sum of this base + the cover
2237 fullThickness = baseThickness + mcmCapThickness + mcmCapBorderThickness;
2241 // translations (in the X direction, MCM is at the same level as ladder)
2242 Double_t xBase = -0.5*fullThickness + 0.5*baseThickness;
2243 TGeoTranslation *trBase = new TGeoTranslation(xBase, 0.0, 0.0);
2244 Double_t xMCMCapB = xBase + 0.5*baseThickness + 0.5*mcmCapThickness;
2245 Double_t xMCMCapT = xMCMCapB + 0.5*mcmCapThickness +
2246 0.5*mcmCapBorderThickness;
2247 Double_t yMCMCap = 0.5*(baseHeight - mcmCapHeight);
2248 Double_t zMCMCap1 = 0.5*baseWidth - 0.5*mcmCapWidth;
2249 Double_t zMCMCap0 = -zMCMCap1;
2250 // correction rotations
2251 TGeoRotation *rotCorr0 = new TGeoRotation(*gGeoIdentity);
2252 TGeoRotation *rotCorr1 = new TGeoRotation(*gGeoIdentity);
2253 rotCorr0->RotateY( 90.0);
2254 rotCorr1->RotateY(-90.0);
2255 TGeoCombiTrans *trMCMCapBorder0 = new TGeoCombiTrans(xMCMCapB,
2256 yMCMCap, zMCMCap0, rotCorr0);
2257 TGeoCombiTrans *trMCMCapBorder1 = new TGeoCombiTrans(xMCMCapB,
2258 yMCMCap, zMCMCap1, rotCorr1);
2259 TGeoCombiTrans *trMCMCapTop0 = new TGeoCombiTrans(xMCMCapT,
2260 yMCMCap, zMCMCap0, rotCorr0);
2261 TGeoCombiTrans *trMCMCapTop1 = new TGeoCombiTrans(xMCMCapT,
2262 yMCMCap, zMCMCap1, rotCorr1);
2264 container->AddNode(staveBase, 0, trBase);
2265 container->AddNode(mcmCapBorder, 0, trMCMCapBorder0);
2266 container->AddNode(mcmCapBorder, 1, trMCMCapBorder1);
2267 container->AddNode(mcmCapTop, 0, trMCMCapTop0);
2268 container->AddNode(mcmCapTop, 1, trMCMCapTop1);
2273 // for the moment, a correction amount of 0.04 is required to
2274 // place correctly the object in X and another correction of
2276 Double_t busHeight = fgkmm * 13.8;
2277 Double_t xPixelBus = xBase + baseThickness + 0.04;
2278 Double_t yPixelBus1 = 0.5*baseHeight - 0.5*busHeight +
2279 0.5*(baseHeight - busHeight);
2280 Double_t zPixelBus0 = -0.25*baseWidth + 0.015 - 0.03;
2281 //Double_t zPixelBus0 = -0.5*(0.5*baseWidth - 0.04);
2282 Double_t zPixelBus1 = -zPixelBus0;
2283 // correction rotations
2284 TGeoRotation *rotCorrBus1 = new TGeoRotation(*gGeoIdentity);
2285 rotCorrBus1->RotateX(180.0);
2286 //TGeoCombiTrans *trBus0 = new TGeoCombiTrans(xPixelBus, 0.0,
2287 // zPixelBus0, rotCorrBus);
2288 TGeoTranslation *trBus0 = new TGeoTranslation(xPixelBus, 0.0,
2290 //TGeoTranslation *trBus1 = new TGeoTranslation(xPixelBus, 0.0,
2292 TGeoCombiTrans *trBus1 = new TGeoCombiTrans(xPixelBus, yPixelBus1,
2293 zPixelBus1, rotCorrBus1);
2296 container->AddNode(bus0, 0, trBus0);
2297 container->AddNode(bus1, 1, trBus1);
2301 //______________________________________________________________________
2302 TGeoVolumeAssembly* AliITSv11GeometrySPD::CreatePixelBusAndExtensions(
2303 Bool_t zpos, TGeoManager *mgr){
2304 // Creates an assembly which contains the pixel bus and its extension
2305 // and the extension of the MCM.
2306 // By: Renaud Vernet
2307 // NOTE: to be defined its material and its extension in the outside direction
2310 // ==== constants =====
2313 TGeoMedium *medPixelBus = mgr->GetMedium("PIXEL BUS") ;
2314 TGeoMedium *medPBExtender = mgr->GetMedium("PIXEL BUS EXTENDER") ;
2315 TGeoMedium *medMCMExtender = mgr->GetMedium("MCM EXTENDER") ;
2317 //geometrical constants
2318 const Double_t kGroundingThickness = 0.07 * fgkmm ;
2319 const Double_t kGrounding2pixelBusDz = 0.625 * fgkmm ;
2320 const Double_t kPixelBusThickness = 0.28 * fgkmm ;
2321 const Double_t kGroundingWidthX = 170.501 * fgkmm ;
2322 const Double_t kPixelBusContactDx = 1.099 * fgkmm ;
2323 const Double_t kPixelBusWidthY = 13.8 * fgkmm ;
2325 const Double_t kPixelBusContactPhi = 20.0 * TMath::DegToRad();
2326 //design=?? 70 deg. seems OK
2327 const Double_t kPbExtenderPsi = 70.0 * TMath::DegToRad();
2328 const Double_t kPbExtenderWidthY = 11.0 * fgkmm ;
2329 const Double_t kPbExtenderTopZ = 2.72 * fgkmm ;
2330 const Double_t kMcmThickness = 0.35 * fgkmm ;
2331 const Double_t kMcmExtenderThickness = 0.20 * fgkmm ;
2332 const Double_t kDeltaMcmMcmextender = 1.6 * fgkmm ;
2333 const Double_t kHalfStaveTotalLength = 247.64 * fgkmm ;
2334 const Double_t kDeltaYOrigin = 15.95/2.* fgkmm ;
2335 const Double_t kDeltaXOrigin = 1.1 * fgkmm ;
2336 const Double_t kDeltaZOrigin = kHalfStaveTotalLength / 2. ;
2338 const Double_t kGrounding2pixelBusDz2 = kGrounding2pixelBusDz+
2339 kGroundingThickness/2. + kPixelBusThickness/2. ;
2340 const Double_t kPixelBusWidthX = kGroundingWidthX ;
2341 const Double_t kPixelBusRaiseLength = (kPixelBusContactDx-
2342 kPixelBusThickness*TMath::Sin(kPixelBusContactPhi))/
2343 TMath::Cos(kPixelBusContactPhi) ;
2344 const Double_t kPbExtenderBaseZ = kGrounding2pixelBusDz2 +
2345 kPixelBusRaiseLength*TMath::Sin(kPixelBusContactPhi) +
2346 2*kPixelBusThickness*TMath::Sin(kPixelBusContactPhi)*
2347 TMath::Tan(kPixelBusContactPhi) ;
2348 const Double_t kPbExtenderDeltaZ = kPbExtenderTopZ-kPbExtenderBaseZ ;
2349 const Double_t kPbExtenderEndPointX = 2*kDeltaZOrigin - kGroundingWidthX -
2350 2*kPixelBusThickness*TMath::Sin(kPixelBusContactPhi) ;
2351 const Double_t kMcmextenderEndPointX = kDeltaZOrigin - 48.2 * fgkmm ;
2352 const Double_t kMcmExtenderWidthY = kPbExtenderWidthY ;
2354 //===== end constants =====
2358 // ----------------- CREATE THE PIXEL BUS --------------------------
2359 // At the end of the pixel bus, a small piece is added for the contact
2360 // with the pixel bus extender.
2361 // The whole piece is made with an extrusion, using 7 points
2366 // +-----------------------------+ /
2368 // +-----------------------------+--+
2371 // The length of the pixel bus is defined (170.501mm) by the technical design
2372 // this length corresponds to distance [0-1] and [6-5]
2376 TGeoVolumeAssembly *pixelBus = new TGeoVolumeAssembly("PIXEL BUS");
2378 // definition of the 7 points for the extrusion
2379 Double_t pixelBusXtruX[7] = {
2380 -kPixelBusWidthX/2. ,
2381 kPixelBusWidthX/2. ,
2382 kPixelBusWidthX/2. + kPixelBusThickness * TMath::Sin(kPixelBusContactPhi) ,
2383 kPixelBusWidthX/2. + kPixelBusThickness * TMath::Sin(kPixelBusContactPhi) +
2384 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) ,
2385 kPixelBusWidthX/2. + kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi),
2386 kPixelBusWidthX/2. ,
2389 Double_t pixelBusXtruY[7] = {
2390 -kPixelBusThickness/2. ,
2391 -kPixelBusThickness/2. ,
2392 -kPixelBusThickness/2. + kPixelBusThickness *
2393 (1 - TMath::Cos(kPixelBusContactPhi)) ,
2394 -kPixelBusThickness/2. + kPixelBusThickness *
2395 (1 - TMath::Cos(kPixelBusContactPhi)) +
2396 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) ,
2397 kPixelBusThickness/2. + kPixelBusRaiseLength *
2398 TMath::Sin(kPixelBusContactPhi) ,
2399 kPixelBusThickness/2. ,
2400 kPixelBusThickness/2.
2403 // creation of the volume
2404 TGeoXtru *pixelBusXtru = new TGeoXtru(2);
2405 TGeoVolume* pixelBusXtruVol = new TGeoVolume("pixelBusXtru",
2406 pixelBusXtru,medPixelBus) ;
2407 pixelBusXtru->DefinePolygon(7,pixelBusXtruX,pixelBusXtruY);
2408 pixelBusXtru->DefineSection(0,-kPixelBusWidthY/2.);
2409 pixelBusXtru->DefineSection(1, kPixelBusWidthY/2.);
2410 // --------------- END PIXEL BUS -------------------------------------
2413 // ------------------------- CREATE THE PIXEL BUS EXTENDER -----------
2414 // The geometry of the extender is a bit complicated sinceit is constrained
2415 // to be in contact with the pixel bus.
2416 // It consists of an extrusion using 13 points as shows the scheme below :
2419 // +---+---------------------+
2422 // / +---------------------+
2426 // +---+-----------+ /
2429 // / +-----------+---+
2436 // ==== constants =====
2437 const Double_t kPbExtenderXtru3L = 1.5 * fgkmm ; //arbitrary ?
2438 const Double_t kPbExtenderXtru4L = (kPbExtenderDeltaZ +
2439 kPixelBusThickness*(TMath::Cos(kPbExtenderPsi)-2))/
2440 TMath::Sin(kPbExtenderPsi) ;
2441 //===== end constants =====
2443 TGeoVolumeAssembly *pbExtender = new TGeoVolumeAssembly("PIXEL BUS EXTENDER");
2445 Double_t pbExtenderXtruX[13] = {
2447 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) ,
2448 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) + kPbExtenderXtru3L ,
2449 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) +
2450 kPbExtenderXtru3L + kPixelBusThickness * TMath::Sin(kPbExtenderPsi) ,
2451 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) +
2452 kPbExtenderXtru3L + kPixelBusThickness *
2453 TMath::Sin(kPbExtenderPsi) + kPbExtenderXtru4L *
2454 TMath::Cos(kPbExtenderPsi) ,
2455 kPbExtenderEndPointX ,
2456 kPbExtenderEndPointX ,
2457 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) +
2458 kPbExtenderXtru3L + kPixelBusThickness * TMath::Sin(kPbExtenderPsi)+
2459 kPbExtenderXtru4L * TMath::Cos(kPbExtenderPsi) ,
2460 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) +
2461 kPbExtenderXtru3L + kPixelBusThickness * TMath::Sin(kPbExtenderPsi)+
2462 kPbExtenderXtru4L * TMath::Cos(kPbExtenderPsi) - kPixelBusThickness*
2463 TMath::Sin(kPbExtenderPsi),
2464 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) + kPbExtenderXtru3L ,
2465 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) ,
2466 kPixelBusRaiseLength * TMath::Cos(kPixelBusContactPhi) -
2467 kPixelBusThickness*TMath::Sin(kPixelBusContactPhi) ,
2468 -kPixelBusThickness * TMath::Sin(kPixelBusContactPhi)
2470 Double_t pbExtenderXtruY[13] = {
2472 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) ,
2473 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) ,
2474 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) +
2475 kPixelBusThickness * (1-TMath::Cos(kPbExtenderPsi)) ,
2476 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) +
2477 kPixelBusThickness * (1-TMath::Cos(kPbExtenderPsi)) +
2478 kPbExtenderXtru4L * TMath::Sin(kPbExtenderPsi) ,
2479 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) +
2480 kPixelBusThickness * (1-TMath::Cos(kPbExtenderPsi)) +
2481 kPbExtenderXtru4L * TMath::Sin(kPbExtenderPsi) ,
2482 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) +
2483 kPixelBusThickness * (1-TMath::Cos(kPbExtenderPsi)) +
2484 kPbExtenderXtru4L * TMath::Sin(kPbExtenderPsi) +
2485 kPixelBusThickness ,
2486 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) +
2487 kPixelBusThickness * (1-TMath::Cos(kPbExtenderPsi)) +
2488 kPbExtenderXtru4L * TMath::Sin(kPbExtenderPsi) +
2489 kPixelBusThickness ,
2490 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi) +
2491 kPixelBusThickness + kPbExtenderXtru4L *
2492 TMath::Sin(kPbExtenderPsi),
2493 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi)+kPixelBusThickness ,
2494 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi)+kPixelBusThickness ,
2495 kPixelBusRaiseLength * TMath::Sin(kPixelBusContactPhi)+kPixelBusThickness*
2496 TMath::Cos(kPixelBusContactPhi) ,
2497 kPixelBusThickness * TMath::Cos(kPixelBusContactPhi)
2500 // creation of the volume
2501 TGeoXtru *pbExtenderXtru = new TGeoXtru(2);
2502 TGeoVolume *pbExtenderXtruVol = new TGeoVolume("pbExtenderXtru",
2503 pbExtenderXtru,medPBExtender) ;
2504 pbExtenderXtru->DefinePolygon(13,pbExtenderXtruX,pbExtenderXtruY);
2505 pbExtenderXtru->DefineSection(0,-kPbExtenderWidthY/2.);
2506 pbExtenderXtru->DefineSection(1, kPbExtenderWidthY/2.);
2507 // -------------- END PIXEL BUS EXTENDER -----------------------------
2510 // ------------------ CREATE THE MCM EXTENDER -------------------
2512 // The MCM extender is located betwen the MCM and the Pixel Bus Extender
2513 // It consists of an extrusion using 10 points as shows the scheme below :
2516 // +---+---------------------+
2519 // / +---------------------+
2526 // +-----------+---+
2530 const Double_t kMcmExtenderXtru3L = 1.5 * fgkmm ;
2533 TGeoVolumeAssembly *mcmExtender = new TGeoVolumeAssembly("MCM EXTENDER");
2534 Double_t mcmExtenderXtruX[10] = {
2536 kMcmExtenderXtru3L ,
2537 kMcmExtenderXtru3L + kMcmExtenderThickness * TMath::Sin(kPbExtenderPsi) ,
2538 kMcmExtenderXtru3L + kMcmExtenderThickness * TMath::Sin(kPbExtenderPsi) +
2539 kDeltaMcmMcmextender / TMath::Tan(kPbExtenderPsi) ,
2540 kMcmextenderEndPointX ,
2541 kMcmextenderEndPointX ,
2542 kMcmExtenderXtru3L + kMcmExtenderThickness * TMath::Sin(kPbExtenderPsi) +
2543 kDeltaMcmMcmextender / TMath::Tan(kPbExtenderPsi) ,
2544 kMcmExtenderXtru3L + kDeltaMcmMcmextender / TMath::Tan(kPbExtenderPsi) ,
2545 kMcmExtenderXtru3L ,
2549 Double_t mcmExtenderXtruY[10] = {
2552 kMcmExtenderThickness*(1.-TMath::Cos(kPbExtenderPsi)),
2553 kMcmExtenderThickness*(1.-TMath::Cos(kPbExtenderPsi))+kDeltaMcmMcmextender,
2554 kMcmExtenderThickness*(1.-TMath::Cos(kPbExtenderPsi))+kDeltaMcmMcmextender,
2555 kMcmExtenderThickness*(2.-TMath::Cos(kPbExtenderPsi))+kDeltaMcmMcmextender,
2556 kMcmExtenderThickness*(2.-TMath::Cos(kPbExtenderPsi))+kDeltaMcmMcmextender,
2557 kMcmExtenderThickness + kDeltaMcmMcmextender ,
2558 kMcmExtenderThickness ,
2559 kMcmExtenderThickness ,
2562 // creation of the volume
2563 TGeoXtru *mcmExtenderXtru = new TGeoXtru(2);
2564 TGeoVolume *mcmExtenderXtruVol = new TGeoVolume("mcmExtenderXtru",
2565 mcmExtenderXtru,medMCMExtender) ;
2566 mcmExtenderXtru->DefinePolygon(10,mcmExtenderXtruX,mcmExtenderXtruY);
2567 mcmExtenderXtru->DefineSection(0,-kMcmExtenderWidthY/2.);
2568 mcmExtenderXtru->DefineSection(1, kMcmExtenderWidthY/2.);
2571 //-------------- DEFINITION OF GEOMETRICAL TRANSFORMATIONS ---------
2572 TGeoRotation * commonRot = new TGeoRotation("commonRot",0,90,0);
2573 commonRot->MultiplyBy(new TGeoRotation("rot",-90,0,0)) ;
2574 TGeoTranslation * pixelBusTrans = new TGeoTranslation(kPixelBusThickness/2.
2575 - kDeltaXOrigin + 0.52*fgkmm ,
2576 -kPixelBusWidthY/2.+ kDeltaYOrigin ,
2577 -kGroundingWidthX/2.+ kDeltaZOrigin) ;
2578 TGeoRotation * pixelBusRot = new TGeoRotation(*commonRot);
2579 TGeoTranslation * pbExtenderTrans = new TGeoTranslation(*pixelBusTrans) ;
2580 TGeoRotation * pbExtenderRot = new TGeoRotation(*pixelBusRot) ;
2581 pbExtenderTrans->SetDz(*(pbExtenderTrans->GetTranslation()+2)-
2582 kPixelBusWidthX/2.-2.*kPixelBusThickness*
2583 TMath::Sin(kPixelBusContactPhi)) ;
2585 pbExtenderTrans->SetDy(*(pbExtenderTrans->GetTranslation()+1) -
2586 (kPixelBusWidthY - kPbExtenderWidthY)/2.);
2588 pbExtenderTrans->SetDy(*(pbExtenderTrans->GetTranslation()+1) +
2589 (kPixelBusWidthY - kPbExtenderWidthY)/2.);
2591 pbExtenderTrans->SetDx(*(pbExtenderTrans->GetTranslation()) +
2592 kPixelBusThickness/2 + 2*kPixelBusThickness*
2593 TMath::Sin(kPixelBusContactPhi)*
2594 TMath::Tan(kPixelBusContactPhi)) ;
2595 TGeoTranslation * mcmExtenderTrans = new TGeoTranslation(0.12*fgkmm +
2596 kMcmThickness - kDeltaXOrigin,
2597 pbExtenderTrans->GetTranslation()[1],-4.82);
2598 TGeoRotation * mcmExtenderRot = new TGeoRotation(*pbExtenderRot);
2600 //ADD NODES TO ASSEMBLIES
2601 pixelBus ->AddNode((TGeoVolume*)pixelBusXtruVol,0);
2602 pbExtender ->AddNode((TGeoVolume*)pbExtenderXtruVol,0);
2603 mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtruVol,0);
2604 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru3Vol,0);
2605 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru3PrimVol,1);
2606 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru4Vol,2);
2607 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru4PrimVol,3);
2608 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru5Vol,4);
2611 //CREATE FINAL VOLUME ASSEMBLY AND ROTATE IT
2612 TGeoVolumeAssembly *assembly = new TGeoVolumeAssembly("EXTENDERS");
2613 assembly->AddNode((TGeoVolume*)pixelBus ,0,
2614 new TGeoCombiTrans(*pixelBusTrans,*pixelBusRot));
2615 assembly->AddNode((TGeoVolume*)pbExtender ,0,
2616 new TGeoCombiTrans(*pbExtenderTrans,*pbExtenderRot));
2617 assembly->AddNode((TGeoVolume*)mcmExtender ,0,
2618 new TGeoCombiTrans(*mcmExtenderTrans,*mcmExtenderRot));
2619 assembly->SetTransparency(50);
2622 //______________________________________________________________________
2623 TGeoVolume* AliITSv11GeometrySPD::CreateStaveBase(Int_t layer,
2624 Double_t &fullWidth, Double_t &fullHeight, Double_t &fullThickness,
2626 // Creates a box which contains the followin parts of the whole stave:
2627 // - the two layers of grounding foil
2629 // - the thin base of the MCM (except its thick cover)
2632 // Since it is required by detector numbering conventions,
2633 // it is required as argument the layer which owns this stave.
2634 // This number will be used to define the name of the ladder volume,
2635 // which must be different for layer1 and layer2 objects.
2638 // - layer number (will be checked to be 1 or 2)
2639 // - geometry manager
2642 // - a TGeoBBox volume containing all this stuff
2643 // - the size of the container box are stored in the
2644 // reference-passed variables
2646 // sizes of all objects to be inserted
2647 // these values are used to compute the total volume of the container
2648 // and to compute parametrically the position of each piece, instead
2649 // of putting hard-coded number (this helps in eventually modifying
2651 Double_t mcmThickness = fgkmm * 0.35;
2652 Double_t grndThickness = fgkmm * 0.07; // = 0.05 + 0.02
2653 Double_t sepThickness = fgkmm * 0.05;
2655 Double_t ladderWidth = fgkmm * 70.72;
2656 Double_t mcmWidth = fgkmm * 105.60;
2657 Double_t sepLaddersWidth = fgkmm * 0.20;
2658 Double_t sepMCMWidth = fgkmm * 0.30;
2659 // separations between central ladders in the two half-staves
2660 Double_t sepLaddersCtr = fgkmm * 0.40;
2662 Double_t mcmHeight = fgkmm * 15.00;
2664 // compute the size of the container
2665 fullWidth = 2.0*sepLaddersCtr + 4.0*ladderWidth +
2666 2.0*sepMCMWidth + 2.0*sepLaddersWidth + 2.0*mcmWidth;
2667 fullHeight = fgkmm * 15.95;
2668 fullThickness = grndThickness + sepThickness + mcmThickness;
2670 // create the container
2671 TGeoVolume *container = mgr->MakeBox(Form("LAY%d_STAVE", layer),
2672 mgr->GetMedium("VACUUM"), 0.5*fullThickness,
2673 0.5*fullHeight, 0.5*fullWidth);
2675 // fill the container going from bottom to top
2676 // with respect to the thickness direction
2678 // 1 - Grounding foil
2680 TGeoVolume *grndVol = CreateGroundingFoil(grndThickness);
2682 Double_t xGrnd = -0.5*fullThickness + 0.5*grndThickness;
2683 TGeoTranslation *grndTrans = new TGeoTranslation(xGrnd, 0.0, 0.0);
2685 container->AddNode(grndVol, 1, grndTrans);
2688 // volume (will be replicated 4 times)
2689 Double_t ladderLength, ladderThickness;
2690 TGeoVolume *ladder = CreateLadder(layer, ladderLength, ladderWidth,
2691 ladderThickness, mgr);
2692 // translations (in thickness direction, the MCM thickness is used)
2693 // layers are sorted going from the one at largest Z to the one
2695 // -|Zmax| ------> |Zmax|
2697 // but it is more comfortable to start defining their Z position
2699 Double_t xLad = xGrnd + 0.5*grndThickness + 0.5*mcmThickness +
2701 Double_t zLad1 = -0.5*ladderWidth - sepLaddersCtr;
2702 Double_t zLad0 = zLad1 - ladderWidth - sepLaddersWidth;
2703 Double_t zLad2 = -zLad1;
2704 Double_t zLad3 = -zLad0;
2705 // rotLad->RotateZ(180.0);
2706 TGeoRotation *rotLad = new TGeoRotation(*gGeoIdentity);
2707 TGeoCombiTrans *trLad0 = new TGeoCombiTrans(xLad, 0.0, zLad0, rotLad);
2708 TGeoCombiTrans *trLad1 = new TGeoCombiTrans(xLad, 0.0, zLad1, rotLad);
2709 TGeoCombiTrans *trLad2 = new TGeoCombiTrans(xLad, 0.0, zLad2, rotLad);
2710 TGeoCombiTrans *trLad3 = new TGeoCombiTrans(xLad, 0.0, zLad3, rotLad);
2712 container->AddNode(ladder, 0, trLad0);
2713 container->AddNode(ladder, 1, trLad1);
2714 container->AddNode(ladder, 2, trLad2);
2715 container->AddNode(ladder, 3, trLad3);
2717 // 3 - MCM (only the base, the cover is added as a separate
2718 // volume in a more global 'stave' assembly volume (will be
2719 // replicated twice)
2720 TGeoVolume *mcm = CreateMCMBase(mgr);
2721 // translations (in the X direction, MCM is at the same
2722 // level as ladder) the two copies of the MCM are placed at
2723 // the same distance from the center, on both sides and their
2724 // sorting is the same as ladders' one (MCM0 is at Z < 0,
2726 Double_t xMCM = xLad;
2727 Double_t yMCM = 0.5*(fullHeight - mcmHeight);
2728 Double_t zMCM1 = zLad3 + 0.5*ladderWidth + 0.5*mcmWidth + sepMCMWidth;
2729 Double_t zMCM0 = -zMCM1;
2730 // create the common correction rotations
2731 TGeoRotation *rotCorr0 = new TGeoRotation(*gGeoIdentity);
2732 TGeoRotation *rotCorr1 = new TGeoRotation(*gGeoIdentity);
2733 rotCorr0->RotateY( 90.0);
2734 rotCorr1->RotateY(-90.0);
2735 TGeoCombiTrans *trMCM0 = new TGeoCombiTrans(xMCM,yMCM,zMCM0,rotCorr0);
2736 TGeoCombiTrans *trMCM1 = new TGeoCombiTrans(xMCM,yMCM,zMCM1,rotCorr1);
2738 container->AddNode(mcm, 0, trMCM0);
2739 container->AddNode(mcm, 1, trMCM1);
2743 //______________________________________________________________________
2744 void AliITSv11GeometrySPD::StavesInSector(TGeoVolume *moth, TGeoManager *mgr){
2745 // Unification of essentially two methods:
2746 // - the one which creates the sector structure
2747 // - the one which returns the complete stave
2749 // For compatibility, this method requires the same arguments
2750 // asked by "CarbonFiberSector" method, which is recalled here.
2751 // Like this cited method, this one does not return any value,
2752 // but it inserts in the mother volume (argument 'moth') all the stuff
2753 // which composes the complete SPD sector.
2755 // Arguments: see description of "CarbonFiberSector" method.
2758 // This service class is useful to this method only
2759 // to store in a meaningful way the data about the
2760 // rounded corners of the support, and some computations
2761 // which could turn out to be useful for stave placement
2762 // 'left' and 'right' (L/R) here are considered looking the support
2763 // from the positive Z side.
2764 // The sign of the radius is used to know what kind of tangent
2765 // must be found for the two circles which describe the rounded angles.
2766 class clsSupportPlane {
2768 // curvature center and radius (with sign) of left corner
2769 Double_t xL, yL, rL, sL;
2770 // curvature center and radius (with sign) of right corner
2771 Double_t xR, yR, rR, sR;
2772 // shift from the innermost position (where the stave edge is
2773 // in the point where the rounded corner begins
2776 // Constructor with arguments which allow to set
2777 // directly everything since the values are given in
2778 // millimiters from drawings, they must be converted to cm
2780 (Double_t xLin, Double_t yLin, Double_t rLin, Double_t sLin,
2781 Double_t xRin, Double_t yRin, Double_t rRin, Double_t sRin,
2783 xL(xLin), yL(yLin), rL(rLin), sL(sLin), xR(xRin), yR(yRin),
2784 rR(rRin), sR(sRin), shift(shiftin) {
2794 // Computation of the line tangent to both circles
2795 // defined here which is taken above or below the center
2796 // according to the radius sign. This method returns:
2797 // - the mid-popint of the segment between the two
2798 // points where the tangent touches the two circles,
2799 // - the inclination of this segment
2800 // - the half-length of this segment
2801 Double_t TangentSegment(Double_t &midX, Double_t &midY,
2803 // compute the straight line which is tangent to
2804 // the two circles and extract its inclination
2805 // 'phi' w.r. to X axis
2806 Double_t dx = xL - xR;
2807 Double_t dy = yL - yR;
2808 Double_t R = rL*sL + rR*sR;
2809 Double_t delta = dy*dy + dx*dx - R*R;
2810 Double_t tan05phi = (-dy+TMath::Sqrt(delta))/(R - dx);
2811 phi = 2.0 * TMath::ATan(tan05phi);
2812 // compute the points where this line touchs the
2814 Double_t leftX = xL + sL*rL*TMath::Cos(phi);
2815 Double_t leftY = yL + sL*rL*TMath::Sin(phi);
2816 Double_t rightX = xR + sR*rR*TMath::Cos(phi);
2817 Double_t rightY = yR + sR*rR*TMath::Sin(phi);
2818 // compute the mid point
2819 midX = 0.5 * (leftX + rightX);
2820 midY = 0.5 * (leftY + rightY);
2821 // compute angular coefficient for the line joining
2822 // the two points found using the above method
2823 dx = rightX - leftX;
2824 dy = rightY - leftY;
2825 phi = TMath::ATan2(dy, dx);
2826 // compute the half-length of this segment
2827 Double_t len = 0.5*TMath::Sqrt((rightX-leftX)*
2828 (rightX-leftX) + (rightY-leftY)*
2830 //MM cout << 2.0*len << endl;
2834 // instantiate this class for each layer1 and layer2 corners
2835 clsSupportPlane *plane[6] = {0, 0, 0, 0, 0, 0};
2838 plane[0] = new clsSupportPlane( 10.830, 16.858, 0.60, 1., 19.544,
2839 10.961, 0.8, 1., 1.816);
2840 plane[1] = new clsSupportPlane(- 0.733, 17.486, 0.60, 1., 11.581,
2841 13.371, 0.6, -1., -0.610);
2842 plane[2] = new clsSupportPlane(-12.252, 16.298, 0.60, 1., 0.562,
2843 14.107, 0.6, -1., -0.610);
2844 plane[3] = new clsSupportPlane(-22.276, 12.948, 0.85, 1., -10.445,
2845 13.162, 0.6, -1., -0.610);
2847 plane[4] = new clsSupportPlane(- 3.123, -14.618, 0.50, 1., 11.280,
2848 -14.473, 0.9, -1., -0.691);
2849 plane[5] = new clsSupportPlane(-13.187, -19.964, 0.50, -1., - 3.833,
2850 -17.805, 0.6, -1., 1.300);
2851 // put the sector in the container
2852 //CarbonFiberSector(moth, xAAtubeCenter0, yAAtubeCenter0, mgr);
2854 // create stave volume
2855 Double_t staveHeight = 1.595, staveThickness;
2856 TGeoVolume *stave1 = CreateStave(1, staveThickness,mgr);
2857 TGeoVolume *stave2 = CreateStave(2, staveThickness,mgr);
2859 // compute positions and rotation angles
2860 Double_t xm, ym, halfPlaneHeight, heightDiff, position, phi, xPos, yPos;
2861 for (Int_t i = 0; i < 6; i++) {
2863 // This functioninserted here for test. Added By Bjorn Nilsen
2865 Double_t x0,y0,x1,y1; // should be move out of loop
2867 lreturn = GetSectorMountingPoints(i,x0,y0,x1,y1,mgr);
2869 // recall the geometry computations defined for the classe
2870 halfPlaneHeight = plane[i]->TangentSegment(xm, ym, phi);
2871 // compute the difference between plane and stave heights
2872 heightDiff = halfPlaneHeight - 0.5*staveHeight;
2873 // It is necessary to shift the stave by at least
2874 // an amount equal to this difference
2875 // to avoid overlaps.
2876 // Moreover, some more shift is done for building reasons,
2877 // and it depends on the single plane (data-member 'shift')
2878 position = heightDiff + plane[i]->shift;
2879 // taking into account this shift plus another in the direction
2880 // normal to the support plane, due to the stave thickness,
2881 // the final position of the stave is computed in a temporary
2882 // reference frame where the mid-point of the support plane
2885 ParallelPosition(0.5*staveThickness, position, phi,
2888 ParallelPosition(-0.5*staveThickness, -position, phi,
2891 ParallelPosition(-0.5*staveThickness, -position, phi,
2894 // then we go into the true reference frame
2899 TGeoVolume *tubeTemp1 = mgr->MakeTube("tubeTemp1", NULL,
2901 TGeoTranslation *trTemp1 = new TGeoTranslation(xm, ym, 0.0);
2902 tubeTemp1->SetLineColor(kRed);
2903 moth->AddNode(tubeTemp1, i + 1, trTemp1);
2904 TGeoVolume *tubeTemp2 = mgr->MakeTube("tubeTemp2", NULL,
2906 TGeoTranslation *trTemp2 = new TGeoTranslation(xPos, yPos, 0.0);
2907 tubeTemp2->SetLineColor(kBlue);
2908 moth->AddNode(tubeTemp2, i + 1, trTemp2);
2911 // using the parameters found here, compute the
2912 // translation and rotation of this stave:
2913 TGeoRotation *rot = new TGeoRotation(*gGeoIdentity);
2914 if (i >= 4) rot->RotateY(180.0);
2915 rot->RotateZ(90.0 + phi * TMath::RadToDeg());
2916 TGeoCombiTrans *trans = new TGeoCombiTrans(xPos,yPos,0.0,rot);
2918 moth->AddNode(stave2, i, trans);
2920 moth->AddNode(stave1, i - 4, trans);
2924 //______________________________________________________________________
2925 void AliITSv11GeometrySPD::ParallelPosition(Double_t dist1, Double_t dist2,
2926 Double_t phi, Double_t &x, Double_t &y){
2927 // Performs the following steps:
2928 // 1 - finds a straight line parallel to the one passing through
2929 // the origin and with angle 'phi' with X axis (phi in RADIANS);
2930 // 2 - finds another line parallel to the previous one, with a
2931 // distance 'dist1' from it
2932 // 3 - takes a reference point in the second line in the
2933 // intersection between the normal to both lines passing
2934 // through the origin
2935 // 4 - finds a point whith has distance 'dist2' from this
2936 // reference, in the second line (point 2)
2938 // According to the signs given to dist1 and dist2, the point
2939 // is found in different position w.r. to the origin
2941 // compute the point
2942 Double_t cs = TMath::Cos(phi);
2943 Double_t sn = TMath::Sin(phi);
2945 x = dist2*cs - dist1*sn;
2946 y = dist1*cs + dist2*sn;
2948 //----------------------------------------------------------------------
2949 Bool_t AliITSv11GeometrySPD::Make2DcrossSections(TPolyLine &a0,TPolyLine &a1,
2950 TPolyLine &b0,TPolyLine &b1,TPolyMarker &p)const{
2951 // Fill the objects with the points representing
2952 // a0 the outer carbon fiber SPD sector shape Cross Section A
2953 // a1 the inner carbon fiber SPD sector shape Cross Section A
2954 // b0 the outer carbon fiber SPD sector shape Cross Section B
2955 // b1 the inner carbon fiber SPD sector shape Cross Section B
2958 // TPolyLine &a0 The outer carbon fiber SPD sector shape
2959 // TPolyLine &a1 The Inner carbon fiber SPD sector shape
2960 // TPolyLine &b0 The outer carbon fiber SPD sector shape
2961 // TPolyLine &b1 The Inner carbon fiber SPD sector shape
2962 // TPolyMarker &p The points where the ladders are to be placed
2964 // TPolyLine &a0 The shape filled with the points
2965 // TPolyLine &a1 The shape filled with the points
2966 // TPolyLine &b0 The shape filled with the points
2967 // TPolyLine &b1 The shape filled with the points
2968 // TPolyMarker &p The filled array of points
2973 TGeoVolume *a0V,*a1V,*b0V,*b1V;
2974 TGeoXtru *a0S,*a1S,*b0S,*b1S;
2975 TGeoManager *mgr = gGeoManager;
2977 a0V = mgr->GetVolume(fSPDsectorShapeName.Data());
2978 a0S = dynamic_cast<TGeoXtru*>(a0V->GetShape());
2979 n0 = a0S->GetNvert();
2980 a0.SetPolyLine(n0+1);
2981 //for(i=0;i<fSPDsectorPoints0.GetSize();i++)
2982 // printf("%d %d %d\n",i,fSPDsectorPoints0[i],fSPDsectorPoints1[i]);
2986 //printf("%d %g %g\n",i,x,y);
2988 if(i==0) a0.SetPoint(n0,x,y);
2990 a1V = mgr->GetVolume("ITSSPDCarbonFiberSupportSectorAirA1");
2991 a1S = dynamic_cast<TGeoXtru*>(a1V->GetShape());
2992 n1 = a1S->GetNvert();
2993 a1.SetPolyLine(n1+1);
2998 if(i==0) a1.SetPoint(n1,x,y);
3001 b0V = mgr->GetVolume("ITSSPDCarbonFiberSupportSectorEndB0");
3002 b0S = dynamic_cast<TGeoXtru*>(b0V->GetShape());
3003 n0 = b0S->GetNvert();
3004 b0.SetPolyLine(n0+1);
3009 if(i==0) b0.SetPoint(n0,x,y);
3011 b1V = mgr->GetVolume("ITSSPDCarbonFiberSupportSectorEndAirB1");
3012 b1S = dynamic_cast<TGeoXtru*>(b1V->GetShape());
3013 n1 = b1S->GetNvert();
3014 b1.SetPolyLine(n1+1);
3019 if(i==0) b1.SetPoint(n1,x,y);
3022 Double_t x0,y0,x1,y1;
3023 p.SetPolyMarker(2*fSPDsectorPoints0.GetSize());
3024 for(i=0;i<fSPDsectorPoints0.GetSize();i++){
3025 GetSectorMountingPoints(i,x0,y0,x1,y1);
3026 p.SetPoint(2*i,x0,y0);
3027 p.SetPoint(2*i+1,x1,y1);