1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 // 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 // Root Geometry includes
34 #include <TGeoVolume.h>
37 #include <TGeoTube.h> // contains TGeoTubeSeg
41 #include <TGeoMatrix.h>
42 //#include <TGeoRotation.h>
43 //#include <TGeoCombiTrans.h>
44 //#include <TGeoTranslation.h>
45 #include <TGeoMaterial.h>
46 #include <TGeoMedium.h>
47 #include <TGeoCompositeShape.h>
52 #include "AliITSv11GeometrySPD.h"
54 ClassImp(AliITSv11GeometrySPD)
58 //______________________________________________________________________
59 Int_t AliITSv11GeometrySPD::CreateSPDCenteralMaterials(Int_t &medOffset, Int_t &matOffset)
61 // Define the specific materials used for the ITS SPD centeral
62 // detectors. Note, These are the same old names. By the ALICE
63 // naming convension, these should start out at ITS SPD ....
64 // This data has been taken from AliITSvPPRasymmFMD::CreateMaterials().
66 // Int_t &medOffset The starting number of the list of media
67 // Int_t &matOffset The starting number of the list of Materials
69 // Int_t &medOffset The ending number of the list of media
70 // Int_t &matOffset The ending number of the list of Materials
72 // the last material number used +1 (the next avaiable material number).
75 <img src="http://alice.pd.infn.it/latestdr/all-sections-module.ps"
76 title="SPD Sector drawing with all cross sections defined">
77 <p>The SPD Sector definition.
78 <img src="http://alice.pd.infn.it/latestdr/assembly-10-modules.ps"
79 titile="SPD All Sectors end view with thermal sheald">
80 <p>The SPD all sector end view with thermal sheald.
81 <img src="http://alice.pd.infn.it/latestdr/assembly.ps"
82 title="SPD side view cross section">
83 <p>SPD side view cross section with condes and thermal shealds.
84 <img src="http://alice.pd.infn.it/latestdr/SECTION-A_A.jpg"
85 title="Cross setion A-A"><p>Cross section A-A
86 <img src="http://alice.pd.infn.it/latestdr/SECTION-B_B.jpg"
87 title="Cross section B-B"><p>Cross section B-B
88 <img src="http://alice.pd.infn.it/latestdr/SECTION-C_C.jpg"
89 title-"Cross section C-C"><p>Cross section C-C
90 <img src="http://alice.pd.infn.it/latestdr/SECTION-D_D.jpg"
91 title="Cross section D-D"><p>Cross section D-D
92 <img src="http://alice.pd.infn.it/latestdr/SECTION-F_F.jpg"
93 title="Cross section F-F"><p>Cross section F-F
94 <img src="http://alice.pd.infn.it/latestdr/SECTION-G_G.jpg"
95 title="Cross section G-G"><p>Cross section G-G
98 const Double_t ktmaxfd = 0.1*fgkDegree; // Degree
99 const Double_t kstemax = 1.0*fgkcm; // cm
100 const Double_t kdeemax = 0.1; // Fraction of particle's energy 0<deemax<=1
101 const Double_t kepsil = 1.0E-4; //
102 const Double_t kstmin = 0.0*fgkcm; // cm "Default value used"
103 const Double_t ktmaxfdAir = 0.1*fgkDegree; // Degree
104 const Double_t kstemaxAir = 1.0000E+00*fgkcm; // cm
105 const Double_t kdeemaxAir = 0.1; // Fraction of particle's energy 0<deemax<=1
106 const Double_t kepsilAir = 1.0E-4;//
107 const Double_t kstminAir = 0.0*fgkcm; // cm "Default value used"
108 const Double_t ktmaxfdSi = 0.1*fgkDegree; // .10000E+01; // Degree
109 const Double_t kstemaxSi = 0.0075*fgkcm; // .10000E+01; // cm
110 const Double_t kdeemaxSi = 0.1; // Fraction of particle's energy 0<deemax<=1
111 const Double_t kepsilSi = 1.0E-4;//
112 const Double_t kstminSi = 0.0*fgkcm; // cm "Default value used"
114 Int_t matindex=matOffset;
115 Int_t medindex=medOffset;
116 Double_t params[8]={8*0.0};
121 Int_t ifield = (gAlice->Field()->Integ());
122 Double_t fieldm = (gAlice->Field()->Max());
123 params[1] = (Double_t) ifield;
125 params[3] = ktmaxfdSi;
126 params[4] = kstemaxSi;
127 params[5] = kdeemaxSi;
128 params[6] = kepsilSi;
129 params[7] = kstminSi;
131 mat = new TGeoMaterial("SI",28.086,14.0,2.33*fgkgcm3,
132 TGeoMaterial::kMatStateSolid,25.0*fgkCelsius,
134 mat->SetIndex(matindex);
135 med = new TGeoMedium("SI",medindex++,mat,params);
136 //med = new TGeoMedium("SI",medindex++,matindex++,0,ifield,
137 // fieldm,ktmaxfdSi,kstemaxSi,kdeemaxSi,kepsilSi,kstminSi);
139 mat = new TGeoMaterial("SPD SI CHIP",28.086,14.0,2.33*fgkgcm3,
140 TGeoMaterial::kMatStateSolid,25.0*fgkCelsius,
142 mat->SetIndex(matindex);
143 med = new TGeoMedium("SPD SI CHIP",medindex++,mat,params);
144 //med = new TGeoMedium("SPD SI CHIP",medindex++,matindex++,0,ifield,
145 // fieldm,ktmaxfdSi,kstemaxSi,kdeemaxSi,kepsilSi,kstminSi);
147 mat = new TGeoMaterial("SPD SI BUS",28.086,14.0,2.33*fgkgcm3,
148 TGeoMaterial::kMatStateSolid,25.0*fgkCelsius,
150 mat->SetIndex(matindex);
151 med = new TGeoMedium("SPD SI BUS",medindex++,mat,params);
152 //med = new TGeoMedium("SPD SI BUS",medindex++,matindex++,0,ifield,
153 // fieldm,ktmaxfdSi,kstemaxSi,kdeemaxSi,kepsilSi,kstminSi);
155 mix = new TGeoMixture("C (M55J)",4,1.9866*fgkgcm3);// Carbon fiber by fractional weight "C (M55J)"
156 mix->SetIndex(matindex);
157 mix->DefineElement(0,12.0107,6.0,0.908508078); // Carbon by fractional weight
158 mix->DefineElement(1,14.0067,7.0,0.010387573); // Nitrogen by fractional weight
159 mix->DefineElement(2,15.9994,8.0,0.055957585); // Oxigen by fractional weight
160 mix->DefineElement(3,1.00794,1.0,0.025146765); // Hydrogen by fractional weight
161 mix->SetPressure(0.0*fgkPascal);
162 mix->SetTemperature(25.0*fgkCelsius);
163 mix->SetState(TGeoMaterial::kMatStateSolid);
169 med = new TGeoMedium("ITSspdCarbonFiber",medindex++,mix,params);
170 //med = new TGeoMedium("ITSspdCarbonFiber",medindex++,matindex++,0,ifield,
171 // fieldm,ktmaxfd,kstemax,kdeemax,kepsil,kstmin);
173 mix = new TGeoMixture("Air",4,1.20479E-3*fgkgcm3);// Carbon fiber by fractional weight
174 mix->SetIndex(matindex);
175 mix->DefineElement(0,12.0107,6.0,0.000124); // Carbon by fractional weight
176 mix->DefineElement(1,14.0067,7.0,0.755267); // Nitrogen by fractional weight
177 mix->DefineElement(2,15.9994,8.0,0.231781); // Oxigen by fractional weight
178 mix->DefineElement(3,39.948,18.0,0.012827); // Argon by fractional weight
179 mix->SetPressure(101325.0*fgkPascal); // 1 atmosphere
180 mix->SetTemperature(25.0*fgkCelsius);
181 mix->SetState(TGeoMaterial::kMatStateGas);
182 params[3] = ktmaxfdAir;
183 params[4] = kstemaxAir;
184 params[5] = kdeemaxAir;
185 params[6] = kepsilAir;
186 params[7] = kstminAir;
187 med = new TGeoMedium("ITSspdAir",medindex++,mix,params);
188 //med = new TGeoMedium("ITSspdAir",medindex++,matindex++,0,ifield,
189 // fieldm,ktmaxfdAir,kstemaxAir,kdeemaxAir,kepsilAir,kstminAir);
191 mix = new TGeoMixture("INOX",9,8.03*fgkgcm3);// Carbon fiber by fractional weight
192 mix->SetIndex(matindex);
193 mix->DefineElement(0,12.0107, 6.0,0.0003); // Carbon by fractional weight
194 mix->DefineElement(1,54.9380,25.0,0.02); // Iron by fractional weight
195 mix->DefineElement(2,28.0855,14.0,0.01); // Sodium by fractional weight
196 mix->DefineElement(3,30.9738,15.0,0.00045); // by fractional weight
197 mix->DefineElement(4,32.066 ,16.0,0.0003); // by fractional weight
198 mix->DefineElement(5,58.6928,28.0,0.12); // Nickel by fractional weight
199 mix->DefineElement(6,55.9961,24.0,0.17); // by fractional weight
200 mix->DefineElement(7,95.84 ,42.0,0.025); // by fractional weight
201 mix->DefineElement(8,55.845 ,26.0,0.654); // by fractional weight
202 mix->SetPressure(0.0*fgkPascal); //
203 mix->SetTemperature(25.0*fgkCelsius);
204 mix->SetState(TGeoMaterial::kMatStateSolid);
205 params[3] = ktmaxfdAir;
206 params[4] = kstemaxAir;
207 params[5] = kdeemaxAir;
208 params[6] = kepsilAir;
209 params[7] = kstminAir;
210 med = new TGeoMedium("ITSspdStainlessSteel",medindex++,mix,params);
211 //med = new TGeoMedium("ITSspdStainlessSteel",medindex++,matindex++,0,ifield,
212 // fieldm,ktmaxfdAir,kstemaxAir,kdeemaxAir,kepsilAir,kstminAir);
214 mix = new TGeoMixture("Freon",2,1.63*fgkgcm3);// Carbon fiber by fractional weight
215 mix->SetIndex(matindex);
216 mix->DefineElement(0,12.0107,6.0,4); // Carbon by fractional weight
217 mix->DefineElement(1,18.9984032,9.0,10); // Florine by fractional weight
218 mix->SetPressure(101325.0*fgkPascal); // 1 atmosphere
219 mix->SetTemperature(25.0*fgkCelsius);
220 mix->SetState(TGeoMaterial::kMatStateLiquid);
221 params[3] = ktmaxfdAir;
222 params[4] = kstemaxAir;
223 params[5] = kdeemaxAir;
224 params[6] = kepsilAir;
225 params[7] = kstminAir;
226 med = new TGeoMedium("ITSspdCoolingFluid",medindex++,mix,params);
227 //med = new TGeoMedium("ITSspdCoolingFluid",medindex++,matindex++,0,ifield,
228 // fieldm,ktmaxfdAir,kstemaxAir,kdeemaxAir,kepsilAir,kstminAir);
230 medOffset = medindex;
231 matOffset = matindex;
234 //______________________________________________________________________
235 void AliITSv11GeometrySPD::InitSPDCenteral(Int_t offset,TVirtualMC *vmc){
236 // Do any SPD Centeral detector related initilizations, setting
237 // transport cuts for example.
238 // Some GEANT3 Physics switches
240 // Multiple scattering. The variable IMULS controls this process. For
241 // more information see [PHYS320 or 325 or 328].
242 // 0 - No multiple scattering.
243 // 1 - Multiple scattering according to Moli�re theory. Default setting.
244 // 2 - Same as 1. Kept for backward compatibility.
245 // 3 - Pure Gaussian scattering according to the Rossi formula.
247 // delta ray production. The variable IDRAY controls this process. See [PHYS430]
248 // 0 - No delta rays production.
249 // 1 - delta rays production with generation of . Default setting.
250 // 2 - delta rays production without generation of .
252 // Continuous energy loss. The variable ILOSS controls this process.
253 // 0 - No continuous energy loss, IDRAY is set to 0.
254 // 1 - Continuous energy loss with generation of delta rays above
255 // DCUTE (common/GCUTS/) and restricted Landau fluctuations below DCUTE.
256 // 2 - Continuous energy loss without generation of delta rays and full
257 // Landau-Vavilov-Gauss fluctuations. In this case the variable IDRAY
258 // is forced to 0 to avoid double counting of fluctuations. Default setting.
259 // 3 - Same as 1, kept for backward compatibility.
260 // 4 - Energy loss without fluctuation. The value obtained from the tables is
263 // Int_t offset The material/medium index offset.
264 // TVirturalMC *vmc The pointer to the virtual Monte Carlo default gMC.
272 vmc->Gstpar(i+offset,"CUTGAM",30.0*fgkKeV);
273 vmc->Gstpar(i+offset,"CUTELE",30.0*fgkKeV);
274 vmc->Gstpar(i+offset,"CUTNEU",30.0*fgkKeV);
275 vmc->Gstpar(i+offset,"CUTHAD",30.0*fgkKeV);
276 vmc->Gstpar(i+offset,"CUTMUO",30.0*fgkKeV);
277 vmc->Gstpar(i+offset,"BCUTE",30.0*fgkKeV);
278 vmc->Gstpar(i+offset,"BCUTM",30.0*fgkKeV);
279 vmc->Gstpar(i+offset,"DCUTE",30.0*fgkKeV);
280 vmc->Gstpar(i+offset,"DCUTM",30.0*fgkKeV);
281 //vmc->Gstpar(i+offset,"PPCUTM",);
282 //vmc->Gstpar(i+offset,"PAIR",);
283 //vmc->Gstpar(i+offset,"COMPT",);
284 //vmc->Gstpar(i+offset,"PHOT",);
285 //vmc->Gstpar(i+offset,"PFIS",);
286 vmc->Gstpar(i+offset,"DRAY",1);
287 //vmc->Gstpar(i+offset,"ANNI",);
288 //vmc->Gstpar(i+offset,"BREM",);
289 //vmc->Gstpar(i+offset,"HADR",);
290 //vmc->Gstpar(i+offset,"MUNU",);
291 //vmc->Gstpar(i+offset,"DCAY",);
292 vmc->Gstpar(i+offset,"LOSS",1);
293 //vmc->Gstpar(i+offset,"MULS",);
294 //vmc->Gstpar(i+offset,"GHCOR1",);
295 //vmc->Gstpar(i+offset,"BIRK1",);
296 //vmc->Gstpar(i+offset,"BRIK2",);
297 //vmc->Gstpar(i+offset,"BRIK3",);
298 //vmc->Gstpar(i+offset,"LABS",);
299 //vmc->Gstpar(i+offset,"SYNC",);
300 //vmc->Gstpar(i+offset,"STRA",);
303 //______________________________________________________________________
304 void AliITSv11GeometrySPD::SPDSector(TGeoVolume *moth,TGeoManager *mgr){
305 // Position of the Carbon Fiber Assembly based on distance
306 // of closest point of SPD stave to beam pipe figures
307 // all-sections-modules.ps of 7.22mm at section A-A.
309 // TGeoVolume *moth the mother volume which this
310 // object/volume is to be placed in.
315 const Double_t kSPDclossesStaveAA = 7.22*fgkmm;
316 const Double_t kSectorStartingAngle = -72.0*fgkDegree;
317 const Double_t kNSectorsTotal = 10.; // number
318 const Double_t kSectorRelativeAngle = 360./kNSectorsTotal*fgkDegree;
319 const Double_t kBeamPipeRadius = 0.5*60.0*fgkmm;
322 Double_t angle,radiusSector,xAAtubeCenter0,yAAtubeCenter0;
323 Double_t staveThicknessAA=1.03*fgkmm; // get from stave geometry.
324 TGeoCombiTrans *secRot=new TGeoCombiTrans();
325 TGeoVolume *vCarbonFiberSector;
326 TGeoMedium *medSPDcf;
328 medSPDcf = mgr->GetMedium("ITSspdCarbonFiber");
329 vCarbonFiberSector = new TGeoVolumeAssembly("ITSSPDCarbonFiberSectorV");
330 vCarbonFiberSector->SetMedium(medSPDcf);
331 CarbonFiberSector(vCarbonFiberSector,xAAtubeCenter0,yAAtubeCenter0);
332 //SectorPlusStaves(vCarbonFiberSector,xAAtubeCenter0,yAAtubeCenter0);
333 vCarbonFiberSector->SetVisibility(kTRUE); // logical volume
334 // Compute the radial shift out of the sectors.
335 radiusSector = kBeamPipeRadius+kSPDclossesStaveAA+staveThicknessAA;
336 radiusSector *= radiusSector; // squaring;
337 radiusSector -= xAAtubeCenter0*xAAtubeCenter0;
338 radiusSector = -yAAtubeCenter0+TMath::Sqrt(radiusSector);
339 angle = kSectorStartingAngle;
340 secRot->RotateZ(angle);
341 for(i=0;i<(Int_t)kNSectorsTotal;i++){
342 secRot->SetDx(-radiusSector*TMath::Sin(angle/fgkRadian));
343 secRot->SetDy(radiusSector*TMath::Cos(angle/fgkRadian));
344 //secRot->RegisterYourself();
345 moth->AddNode(vCarbonFiberSector,i+1,new TGeoCombiTrans(*secRot));
347 printf("i=%d angle=%g angle[rad]=%g radiusSector=%g x=%g y=%g \n",
348 i,angle,angle/fgkRadian,radiusSector,
349 -radiusSector*TMath::Sin(angle/fgkRadian),
350 radiusSector*TMath::Cos(angle/fgkRadian));
351 } // end if GetDebug(5)
352 angle += kSectorRelativeAngle;
353 secRot->RotateZ(kSectorRelativeAngle);
357 } // end if GetDebug().
360 //______________________________________________________________________
361 void AliITSv11GeometrySPD::CarbonFiberSector(TGeoVolume *moth,
362 Double_t &xAAtubeCenter0,
363 Double_t &yAAtubeCenter0,
365 // Define the detail SPD Carbon fiber support Sector geometry.
366 // Based on the drawings ALICE-Pixel "Construzione Profilo Modulo"
367 // March 25 2004 and ALICE-SUPPORTO "construzione Profilo Modulo"
368 // Define Outside radii as negitive, Outside in the sence that the
369 // center of the arc is outside of the object.
372 // TGeoVolume *moth The mother volume to put this object
374 // Double_t &xAAtubeCenter0 The x location of the outer surface
375 // of the cooling tube center for tube 0.
376 // This location helps determine where
377 // this sector is to be located (information
378 // used for this is the distance the
379 // center of the #0 detector is from the
380 // beam pipe. Measurements taken at
381 // cross section A-A.
382 // Double_t &yAAtubeCenter0 The y location of the outer surface
383 // of the cooling tube center for tube 0
384 // This location helps determine where
385 // this sector is to be located (information
386 // used for this is the distance the
387 // center of the #0 detector is from the
388 // beam pipe. Measurements taken at
389 // cross section A-A.
390 // TGeoManager *mgr The TGeoManager as needed, default is
394 TGeoMedium *medSPDcf = 0; // SPD support cone Carbon Fiber materal number.
395 //TGeoMedium *medSPDfs = 0; // SPD support cone inserto stesalite 4411w.
396 //TGeoMedium *medSPDfo = 0; // SPD support cone foam, Rohacell 50A.
397 TGeoMedium *medSPDss = 0; // SPD support cone screw material,Stainless
398 TGeoMedium *medSPDair = 0; // SPD support cone Air
399 //TGeoMedium *medSPDal = 0; // SPD support cone SDD mounting bracket Al
400 TGeoMedium *medSPDcoolfl = 0; // SPD cooling fluid, Freeon
401 medSPDcf = mgr->GetMedium("ITSspdCarbonFiber");
402 //medSPDfs = mgr->GetMedium("ITSspdStaselite4411w");
403 //medSPDfo = mgr->GetMedium("ITSspdRohacell50A");
404 medSPDss = mgr->GetMedium("ITSspdStainlessSteel");
405 medSPDair= mgr->GetMedium("ITSspdAir");
406 medSPDcoolfl= mgr->GetMedium("ITSspdCoolingFluid");
408 const Double_t ksecDz = 0.5*500.0*fgkmm;
409 const Double_t ksecLen = 30.0*fgkmm;
410 const Double_t ksecCthick = 0.20*fgkmm;
411 const Double_t ksecDipLength = 3.2*fgkmm;
412 const Double_t ksecDipRadii = 0.4*fgkmm;
413 //const Double_t ksecCoolingTubeExtraDepth = 0.86*fgkmm;
414 // These positions, ksecX*,ksecY* are the center of curvatures
415 // for the different point around the SPD sector. The radii,
416 // inner and outer, are the radous of curvature about the centers
417 // ksecX* and ksecY*. To draw this SPD sector, first plot all of
418 // the ksecX and ksecY points and draw circles of the specified
419 // radius about these points. Connect the circles, such that the
420 // lines are tangent to the circles, in accordance with the
421 // radii being "Inside" or "Outside". These lines and the
422 // corresponding arc's are the surface of this SPD sector.
423 const Double_t ksecX0 = -10.725*fgkmm;
424 const Double_t ksecY0 = -14.853*fgkmm;
425 const Double_t ksecR0 = -0.8*fgkmm; // Outside
426 const Double_t ksecX1 = -13.187*fgkmm;
427 const Double_t ksecY1 = -19.964*fgkmm;
428 const Double_t ksecR1 = +0.6*fgkmm; // Inside
429 //const Double_t ksecDip0 = 5.9*fgkmm;
431 const Double_t ksecX2 = -3.883*fgkmm;
432 const Double_t ksecY2 = -17.805*fgkmm;
433 const Double_t ksecR2 = +0.80*fgkmm; // Inside Guess.
434 const Double_t ksecX3 = -3.123*fgkmm;
435 const Double_t ksecY3 = -14.618*fgkmm;
436 const Double_t ksecR3 = -0.6*fgkmm; // Outside
437 //const Double_t ksecDip1 = 8.035*fgkmm;
439 const Double_t ksecX4 = +11.280*fgkmm;
440 const Double_t ksecY4 = -14.473*fgkmm;
441 const Double_t ksecR4 = +0.8*fgkmm; // Inside
442 const Double_t ksecX5 = +19.544*fgkmm;
443 const Double_t ksecY5 = +10.961*fgkmm;
444 const Double_t ksecR5 = +0.8*fgkmm; // Inside
445 //const Double_t ksecDip2 = 4.553*fgkmm;
447 const Double_t ksecX6 = +10.830*fgkmm;
448 const Double_t ksecY6 = +16.858*fgkmm;
449 const Double_t ksecR6 = +0.6*fgkmm; // Inside
450 const Double_t ksecX7 = +11.581*fgkmm;
451 const Double_t ksecY7 = +13.317*fgkmm;
452 const Double_t ksecR7 = -0.6*fgkmm; // Outside
453 //const Double_t ksecDip3 = 6.978*fgkmm;
455 const Double_t ksecX8 = -0.733*fgkmm;
456 const Double_t ksecY8 = +17.486*fgkmm;
457 const Double_t ksecR8 = +0.6*fgkmm; // Inside
458 const Double_t ksecX9 = +0.562*fgkmm;
459 //const Double_t ksecY9 = +14.486*fgkmm; // correction by
460 const Double_t ksecY9 = +14.107*fgkmm; // Alberto
461 const Double_t ksecR9 = -0.6*fgkmm; // Outside
462 //const Double_t ksecDip4 = 6.978*fgkmm;
464 const Double_t ksecX10 = -12.252*fgkmm;
465 const Double_t ksecY10 = +16.298*fgkmm;
466 const Double_t ksecR10 = +0.6*fgkmm; // Inside
467 const Double_t ksecX11 = -10.445*fgkmm;
468 const Double_t ksecY11 = +13.162*fgkmm;
469 const Double_t ksecR11 = -0.6*fgkmm; // Outside
470 //const Double_t ksecDip5 = 6.978*fgkmm;
472 const Double_t ksecX12 = -22.276*fgkmm;
473 const Double_t ksecY12 = +12.948*fgkmm;
474 const Double_t ksecR12 = +0.85*fgkmm; // Inside
475 //const Double_t ksecX13 = *fgkmm;
476 //const Double_t ksecY13 = *fgkmm;
477 const Double_t ksecR13 = -0.8*fgkmm; // Outside
478 const Double_t ksecAngleSide13 = 36.0*fgkDegree;
480 const Int_t ksecNRadii = 20;
481 const Int_t ksecNPointsPerRadii = 4;
482 const Int_t ksecNCoolingTubeDips = 6;
483 // Since the Rounded parts are aproximated by a regular polygon and
484 // a cooling tube of the propper diameter must fit, a scaling factor
485 // increases the size of the polygon for the tube to fit.
486 //const Double_t ksecRCoolScale = 1./TMath::Cos(TMath::Pi()/
487 // (Double_t)ksecNPointsPerRadii);
488 const Double_t ksecZEndLen = 30.00*fgkmm;
489 //const Double_t ksecZFlangLen= 45.00*fgkmm;
490 const Double_t ksecTl = 0.860*fgkmm;
491 const Double_t ksecCthick2 = 0.600*fgkmm;
492 //const Double_t ksecCthick3 = 1.800*fgkmm;
493 //const Double_t ksecSidelen = 22.00*fgkmm;
494 //const Double_t ksecSideD5 = 3.679*fgkmm;
495 //const Double_t ksecSideD12 = 7.066*fgkmm;
496 const Double_t ksecRCoolOut = 2.400*fgkmm;
497 const Double_t ksecRCoolIn = 2.000*fgkmm;
498 const Double_t ksecDl1 = 5.900*fgkmm;
499 const Double_t ksecDl2 = 8.035*fgkmm;
500 const Double_t ksecDl3 = 4.553*fgkmm;
501 const Double_t ksecDl4 = 6.978*fgkmm;
502 const Double_t ksecDl5 = 6.978*fgkmm;
503 const Double_t ksecDl6 = 6.978*fgkmm;
504 const Double_t ksecCoolTubeThick = 0.04*fgkmm;
505 const Double_t ksecCoolTubeROuter = 2.6*fgkmm;
506 const Double_t ksecCoolTubeFlatX = 3.696*fgkmm;
507 const Double_t ksecCoolTubeFlatY = 0.68*fgkmm;
508 //const Double_t ksecBeamX0 = 0.0*fgkmm; // guess
509 //const Double_t ksecBeamY0 = (15.223+40.)*fgkmm; // guess
511 const Int_t ksecNPoints = (ksecNPointsPerRadii+1)*ksecNRadii + 8;
512 Double_t secX[ksecNRadii] = {ksecX0,ksecX1,-1000.0,ksecX2 ,ksecX3 ,-1000.0,
513 ksecX4,ksecX5,-1000.0,ksecX6 ,ksecX7 ,-1000.0,
514 ksecX8,ksecX9,-1000.0,ksecX10,ksecX11,-1000.0,
516 Double_t secY[ksecNRadii] = {ksecY0,ksecY1,-1000.0,ksecY2 ,ksecY3 ,-1000.0,
517 ksecY4,ksecY5,-1000.0,ksecY6 ,ksecY7 ,-1000.0,
518 ksecY8,ksecY9,-1000.0,ksecY10,ksecY11,-1000.0,
520 Double_t secR[ksecNRadii] ={ksecR0 ,ksecR1 ,-.5*ksecDipLength-ksecDipRadii,
521 ksecR2 ,ksecR3 ,-.5*ksecDipLength-ksecDipRadii,
522 ksecR4 ,ksecR5 ,-.5*ksecDipLength-ksecDipRadii,
523 ksecR6 ,ksecR7 ,-.5*ksecDipLength-ksecDipRadii,
524 ksecR8 ,ksecR9 ,-.5*ksecDipLength-ksecDipRadii,
525 ksecR10,ksecR11,-.5*ksecDipLength-ksecDipRadii,
527 Double_t secDip[ksecNRadii]={0.0,0.0,ksecDip0,0.0,0.0,ksecDip1,
528 0.0,0.0,ksecDip2,0.0,0.0,ksecDip3,
529 0.0,0.0,ksecDip4,0.0,0.0,ksecDip5,
531 Double_t secX2[ksecNRadii];
532 Double_t secY2[ksecNRadii];
533 Double_t secR2[ksecNRadii] = {
534 ksecR0,ksecR1,ksecRCoolOut,ksecR2,ksecR3,ksecRCoolOut,ksecR4,ksecR5,
535 ksecRCoolOut,ksecR6,ksecR7,ksecRCoolOut,ksecR8,ksecR9,ksecRCoolOut,
536 ksecR10,ksecR11,ksecRCoolOut,ksecR12,ksecR13};
537 Double_t secDip2[ksecNCoolingTubeDips]={ksecDl1,ksecDl2,ksecDl3,
538 ksecDl4,ksecDl5,ksecDl6};
539 Double_t secX3[ksecNRadii];
540 Double_t secY3[ksecNRadii];
541 const Int_t ksecDipIndex[ksecNCoolingTubeDips] = {2,5,8,11,14,17};
542 Double_t secAngleStart[ksecNRadii];
543 Double_t secAngleEnd[ksecNRadii];
544 Double_t secAngleStart2[ksecNRadii];
545 Double_t secAngleEnd2[ksecNRadii];
546 Double_t secAngleTurbo[ksecNCoolingTubeDips] = {0.0,0.0,0.0,0.0,0.0,0.0};
547 //Double_t secAngleStart3[ksecNRadii];
548 //Double_t secAngleEnd3[ksecNRadii];
549 Double_t xpp[ksecNPoints],ypp[ksecNPoints];
550 Double_t xpp2[ksecNPoints],ypp2[ksecNPoints];
551 Double_t *xp[ksecNRadii],*xp2[ksecNRadii];
552 Double_t *yp[ksecNRadii],*yp2[ksecNRadii];
553 TGeoXtru *sA0,*sA1,*sB0,*sB1;
554 TGeoEltu *sTA0,*sTA1;
555 TGeoTube *sTB0,*sTB1; //,*sM0;
557 TGeoTranslation *trans;
558 TGeoCombiTrans *rotrans;
559 Double_t t,t0,t1,a,b,x0,y0,x1,y1;
564 Error("CarbonFiberSector","moth=%p",moth);
568 for(i=0;i<ksecNRadii;i++){
569 xp[i] = &(xpp[i*(ksecNPointsPerRadii+1)]);
570 yp[i] = &(ypp[i*(ksecNPointsPerRadii+1)]);
571 xp2[i] = &(xpp2[i*(ksecNPointsPerRadii+1)]);
572 yp2[i] = &(ypp2[i*(ksecNPointsPerRadii+1)]);
579 // Find starting and ending angles for all but cooling tube sections
580 secAngleStart[0] = 0.5*ksecAngleSide13;
581 for(i=0;i<ksecNRadii-2;i++){
583 for(j=0;j<ksecNCoolingTubeDips;j++) tst = tst||i==ksecDipIndex[j];
586 for(j=0;j<ksecNCoolingTubeDips;j++) tst = tst||(i+1)==ksecDipIndex[j];
589 AnglesForRoundedCorners(secX[i],secY[i],secR[i],
590 secX[j],secY[j],secR[j],t0,t1);
592 secAngleStart[j] = t1;
593 if(secR[i]>0.0&&secR[j]>0.0)if(secAngleStart[i]>secAngleEnd[i])
594 secAngleEnd[i] += 360.0;
595 secAngleStart2[i] = secAngleStart[i];
596 secAngleEnd2[i] = secAngleEnd[i];
598 secAngleEnd[ksecNRadii-2] = secAngleStart[ksecNRadii-2] +
599 (secAngleEnd[ksecNRadii-5]-
600 secAngleStart[ksecNRadii-5]);
601 if(secAngleEnd[ksecNRadii-2]<0.0) secAngleEnd[ksecNRadii-2] += 360.0;
602 secAngleStart[ksecNRadii-1] = secAngleEnd[ksecNRadii-2] - 180.0;
603 secAngleEnd[ksecNRadii-1] = secAngleStart[0];
604 secAngleStart2[ksecNRadii-2] = secAngleStart[ksecNRadii-2];
605 secAngleEnd2[ksecNRadii-2] = secAngleEnd[ksecNRadii-2];
606 secAngleStart2[ksecNRadii-1] = secAngleStart[ksecNRadii-1];
607 secAngleEnd2[ksecNRadii-1] = secAngleEnd[ksecNRadii-1];
608 // Find location of circle last rounded corner.
611 t0 = TanD(secAngleStart[i]-90.);
612 t1 = TanD(secAngleEnd[j]-90.);
613 t = secY[i] - secY[j];
614 // Note, secR[i=0] <0; secR[j=18]>0; and secR[j+1=19] <0
615 t += (-secR[i]+secR[j+1])*SinD(secAngleStart[i]);
616 t -= (secR[j]-secR[j+1])*SinD(secAngleEnd[j]);
617 t += t1*secX[j] - t0*secX[i];
618 t += t1*(secR[j]-secR[j+1])*CosD(secAngleEnd[j]);
619 t -= t0*(-secR[i]+secR[j+1])*CosD(secAngleStart[i]);
620 secX[ksecNRadii-1] = t/(t1-t0);
621 secY[ksecNRadii-1] = TanD(90.+0.5*ksecAngleSide13)*
622 (secX[ksecNRadii-1]-secX[0]) + secY[0];
623 secX2[ksecNRadii-1] = secX[ksecNRadii-1];
624 secY2[ksecNRadii-1] = secY[ksecNRadii-1];
625 secX3[ksecNRadii-1] = secX[ksecNRadii-1];
626 secY3[ksecNRadii-1] = secY[ksecNRadii-1];
627 // find location of cooling tube centers
628 for(i=0;i<ksecNCoolingTubeDips;i++){
630 x0 = secX[j-1] + TMath::Abs(secR[j-1])*CosD(secAngleEnd[j-1]);
631 y0 = secY[j-1] + TMath::Abs(secR[j-1])*SinD(secAngleEnd[j-1]);
632 x1 = secX[j+1] + TMath::Abs(secR[j+1])*CosD(secAngleStart[j+1]);
633 y1 = secY[j+1] + TMath::Abs(secR[j+1])*SinD(secAngleStart[j+1]);
634 t0 = TMath::Sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
638 if(i==0){ // get location of tube center->Surface for locating
639 // this sector around the beam pipe. This needs to be
640 // double checked, but I need my notes for that, Bjorn Nilsen
641 xAAtubeCenter0 = x0+(x1-x0)*t*0.5;
642 yAAtubeCenter0 = y0+(y1-y0)*t*0.5;
644 if(a+b*(a-x0)/(b-y0)>0.0){
645 secX[j] = a + TMath::Abs(y1-y0)*2.0*ksecDipRadii/t0;
646 secY[j] = b - TMath::Sign(2.0*ksecDipRadii,y1-y0)*(x1-x0)/t0;
647 secX2[j] = a + TMath::Abs(y1-y0)*ksecTl/t0;
648 secY2[j] = b - TMath::Sign(ksecTl,y1-y0)*(x1-x0)/t0;
649 secX3[j] = a + TMath::Abs(y1-y0)*(2.0*ksecDipRadii-
650 0.5*ksecCoolTubeFlatY)/t0;
651 secY3[j] = b - TMath::Sign(2.0*ksecDipRadii-0.5*ksecCoolTubeFlatY,
654 secX[j] = a - TMath::Abs(y1-y0)*2.0*ksecDipRadii/t0;
655 secY[j] = b + TMath::Sign(2.0*ksecDipRadii,y1-y0)*(x1-x0)/t0;
656 secX2[j] = a - TMath::Abs(y1-y0)*ksecTl/t0;
657 secY2[j] = b + TMath::Sign(ksecTl,y1-y0)*(x1-x0)/t0;
658 secX3[j] = a - TMath::Abs(y1-y0)*(2.0*ksecDipRadii-
659 0.5*ksecCoolTubeFlatY)/t0;
660 secY3[j] = b + TMath::Sign(2.0*ksecDipRadii-0.5*ksecCoolTubeFlatY,
663 // Set up Start and End angles to correspond to start/end of dips.
664 t1 = (secDip2[i]-TMath::Abs(secR[j]))/t0;
665 secAngleStart[j] = TMath::RadToDeg()*TMath::ATan2(
666 y0+(y1-y0)*t1-secY[j],x0+(x1-x0)*t1-secX[j]);
667 if(secAngleStart[j]<0.0) secAngleStart[j] += 360.0;
668 secAngleStart2[j] = secAngleStart[j];
669 t1 = (secDip2[i]+TMath::Abs(secR[j]))/t0;
670 secAngleEnd[j] = TMath::RadToDeg()*TMath::ATan2(
671 y0+(y1-y0)*t1-secY[j],x0+(x1-x0)*t1-secX[j]);
672 if(secAngleEnd[j]<0.0) secAngleEnd[j] += 360.0;
673 secAngleEnd2[j] = secAngleEnd[j];
674 if(secAngleEnd[j]>secAngleStart[j]) secAngleEnd[j] -= 360.0;
675 secR[j] = TMath::Sqrt(secR[j]*secR[j]+4.0*ksecDipRadii*ksecDipRadii);
678 secAngleStart2[8] -= 360.;
679 secAngleStart2[11] -= 360.;
681 SPDsectorShape(ksecNRadii,secX,secY,secR,secAngleStart,secAngleEnd,
682 ksecNPointsPerRadii,m,xp,yp);
683 // Fix up dips to be square.
684 for(i=0;i<ksecNCoolingTubeDips;i++){
686 t = 0.5*ksecDipLength+ksecDipRadii;
687 t0 = TMath::RadToDeg()*TMath::ATan(2.0*ksecDipRadii/t);
688 t1 = secAngleEnd[j] + t0;
689 t0 = secAngleStart[j] - t0;
690 x0 = xp[j][1] = secX[j] + t*CosD(t0);
691 y0 = yp[j][1] = secY[j] + t*SinD(t0);
692 x1 = xp[j][ksecNPointsPerRadii-1] = secX[j] + t*CosD(t1);
693 y1 = yp[j][ksecNPointsPerRadii-1] = secY[j] + t*SinD(t1);
694 t0 = 1./((Double_t)(ksecNPointsPerRadii-2));
695 for(k=2;k<ksecNPointsPerRadii-1;k++){// extra points spread them out.
696 t = ((Double_t)(k-1))*t0;
697 xp[j][k] = x0+(x1-x0)*t;
698 yp[j][k] = y0+(y1-y0)*t;
700 secAngleTurbo[i] = -TMath::RadToDeg()*TMath::ATan2(y1-y0,x1-x0);
702 cout <<"i="<<i<<" angle="<<secAngleTurbo[i]<<" x0,y0{"
703 <<x0<<","<<y0<<"} x1y1={"<<x1<<","<<y1<<"}"<<endl;
706 sA0 = new TGeoXtru(2);
707 sA0->SetName("ITS SPD Carbon fiber support Sector A0");
708 sA0->DefinePolygon(m,xpp,ypp);
709 sA0->DefineSection(0,-ksecDz);
710 sA0->DefineSection(1,ksecDz);
712 //printf("SectorA#%d ",0);
713 InsidePoint(xpp[m-1],ypp[m-1],xpp[0],ypp[0],xpp[1],ypp[1],
714 ksecCthick,xpp2[0],ypp2[0]);
716 j = i/(ksecNPointsPerRadii+1);
717 //printf("SectorA#%d ",i);
718 InsidePoint(xpp[i-1],ypp[i-1],xpp[i],ypp[i],xpp[i+1],ypp[i+1],
719 ksecCthick,xpp2[i],ypp2[i]);
721 //printf("SectorA#%d ",m);
722 InsidePoint(xpp[m-2],ypp[m-2],xpp[m-1],ypp[m-1],xpp[0],ypp[0],
723 ksecCthick,xpp2[m-1],ypp2[m-1]);
724 // Fix center value of cooling tube dip.
725 // find location of cooling tube centers
726 for(i=0;i<ksecNCoolingTubeDips;i++){
730 x1 = xp2[j][ksecNPointsPerRadii-1];
731 y1 = yp2[j][ksecNPointsPerRadii-1];
732 t0 = TMath::Sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
734 for(k=2;k<ksecNPointsPerRadii-1;k++){// extra points spread them out.
735 t = ((Double_t)(k-1))*t0;
736 xp2[j][k] = x0+(x1-x0)*t;
737 yp2[j][k] = y0+(y1-y0)*t;
740 sA1 = new TGeoXtru(2);
741 sA1->SetName("ITS SPD Carbon fiber support Sector Air A1");
742 sA1->DefinePolygon(m,xpp2,ypp2);
743 sA1->DefineSection(0,-ksecDz);
744 sA1->DefineSection(1,ksecDz);
746 // Error in TGeoEltu. Semi-axis X must be < Semi-axis Y (?).
747 sTA0 = new TGeoEltu("ITS SPD Cooling Tube TA0",
748 0.5* ksecCoolTubeFlatY, 0.5* ksecCoolTubeFlatX,ksecDz);
749 sTA1 = new TGeoEltu("ITS SPD Cooling Tube coolant TA1",
750 sTA0->GetA()-ksecCoolTubeThick,
751 sTA0->GetB()-ksecCoolTubeThick,ksecDz);
753 SPDsectorShape(ksecNRadii,secX2,secY2,secR2,secAngleStart2,secAngleEnd2,
754 ksecNPointsPerRadii,m,xp,yp);
756 sB0 = new TGeoXtru(2);
757 sB0->SetName("ITS SPD Carbon fiber support Sector End B0");
758 sB0->DefinePolygon(m,xpp,ypp);
759 sB0->DefineSection(0,ksecDz);
760 sB0->DefineSection(1,ksecDz+ksecZEndLen);
762 //printf("SectorB#%d ",0);
763 InsidePoint(xpp[m-1],ypp[m-1],xpp[0],ypp[0],xpp[1],ypp[1],
764 ksecCthick2,xpp2[0],ypp2[0]);
767 for(k=0;k<ksecNCoolingTubeDips;k++)
768 if((i/(ksecNPointsPerRadii+1))==ksecDipIndex[k])
769 if(!(ksecDipIndex[k]*(ksecNPointsPerRadii+1)==i ||
770 ksecDipIndex[k]*(ksecNPointsPerRadii+1)+
771 ksecNPointsPerRadii==i ))
772 t = ksecRCoolOut-ksecRCoolIn;
773 //printf("SectorB#%d ",i);
774 InsidePoint(xpp[i-1],ypp[i-1],xpp[i],ypp[i],xpp[i+1],ypp[i+1],
777 //printf("SectorB#%d ",m);
778 InsidePoint(xpp[m-2],ypp[m-2],xpp[m-1],ypp[m-1],xpp[0],ypp[0],
779 ksecCthick2,xpp2[m-1],ypp2[m-1]);
780 sB1 = new TGeoXtru(2);
781 sB1->SetName("ITS SPD Carbon fiber support Sector Air End B1");
782 sB1->DefinePolygon(m,xpp2,ypp2);
783 sB1->DefineSection(0,ksecDz);
784 sB1->DefineSection(1,ksecDz+ksecLen);
785 sTB0 = new TGeoTube("ITS SPD Cooling Tube End TB0",0.0,
786 0.5*ksecCoolTubeROuter,0.5*ksecLen);
787 sTB1 = new TGeoTube("ITS SPD Cooling Tube End coolant TB0",0.0,
788 sTB0->GetRmax()-ksecCoolTubeThick,0.5*ksecLen);
790 //sM0 = new TGeoTube("ITS SPD Sensitive Virutual Volume M0",0.0,8.0,
791 // sA0->GetZ(1)+sB0->GetZ(1));
794 if(medSPDcf) medSPDcf->Dump();
795 else printf("medSPDcf=0\n");
796 if(medSPDss) medSPDss->Dump();
797 else printf("medSPDss=0\n");
798 if(medSPDair) medSPDair->Dump();
799 else printf("medSPDAir=0\n");
800 if(medSPDcoolfl) medSPDcoolfl->Dump();
801 else printf("medSPDcoolfl=0\n");
802 //sM0->InspectShape();
809 TGeoVolume *vA0,*vA1,*vTA0,*vTA1,*vB0,*vB1,*vTB0,*vTB1;
810 TGeoVolumeAssembly *vM0;
811 vM0 = new TGeoVolumeAssembly("ITSSPDSensitiveVirtualvolumeM0");
812 //vM0 = new TGeoVolume("ITSSPDSensitiveVirtualvolumeM0",sM0,medSPDair);
813 //vM0->SetVisibility(kTRUE);
814 //vM0->SetLineColor(7); // light Blue
815 //vM0->SetLineWidth(1);
816 //vM0->SetFillColor(vM0->GetLineColor());
817 //vM0->SetFillStyle(4090); // 90% transparent
820 vA0 = new TGeoVolume("ITSSPDCarbonFiberSupportSectorA0",sA0,medSPDcf);
821 vA0->SetVisibility(kTRUE);
822 vA0->SetLineColor(4); // Blue
823 vA0->SetLineWidth(1);
824 vA0->SetFillColor(vA0->GetLineColor());
825 vA0->SetFillStyle(4010); // 10% transparent
826 vA1 = new TGeoVolume("ITSSPDCarbonFiberSupportSectorAirA1",sA1,medSPDair);
827 vA1->SetVisibility(kTRUE);
828 vA1->SetLineColor(7); // light Blue
829 vA1->SetLineWidth(1);
830 vA1->SetFillColor(vA1->GetLineColor());
831 vA1->SetFillStyle(4090); // 90% transparent
832 vTA0 = new TGeoVolume("ITSSPDCoolingTubeTA0",sTA0,medSPDss);
833 vTA0->SetVisibility(kTRUE);
834 vTA0->SetLineColor(1); // Black
835 vTA0->SetLineWidth(1);
836 vTA0->SetFillColor(vTA0->GetLineColor());
837 vTA0->SetFillStyle(4000); // 0% transparent
838 vTA1 = new TGeoVolume("ITSSPDCoolingTubeFluidTA1",sTA1,medSPDcoolfl);
839 vTA1->SetVisibility(kTRUE);
840 vTA1->SetLineColor(6); // Purple
841 vTA1->SetLineWidth(1);
842 vTA1->SetFillColor(vTA1->GetLineColor());
843 vTA1->SetFillStyle(4000); // 0% transparent
844 vB0 = new TGeoVolume("ITSSPDCarbonFiberSupportSectorEndB0",sB0,medSPDcf);
845 vB0->SetVisibility(kTRUE);
846 vB0->SetLineColor(4); // Blue
847 vB0->SetLineWidth(1);
848 vB0->SetFillColor(vB0->GetLineColor());
849 vB0->SetFillStyle(4010); // 10% transparent
850 vB1 = new TGeoVolume("ITSSPDCarbonFiberSupportSectorEndAirB1",
852 vB1->SetVisibility(kTRUE);
853 vB1->SetLineColor(7); // light Blue
854 vB1->SetLineWidth(1);
855 vB1->SetFillColor(vB1->GetLineColor());
856 vB1->SetFillStyle(4090); // 90% transparent
857 vTB0 = new TGeoVolume("ITSSPDCoolingTubeEndTB0",sTB0,medSPDss);
858 vTB0->SetVisibility(kTRUE);
859 vTB0->SetLineColor(1); // Black
860 vTB0->SetLineWidth(1);
861 vTB0->SetFillColor(vTB0->GetLineColor());
862 vTB0->SetFillStyle(4000); // 0% transparent
863 vTB1 = new TGeoVolume("ITSSPDCoolingTubeEndFluidTB1",sTB1,medSPDcoolfl);
864 vTB1->SetVisibility(kTRUE);
865 vTB1->SetLineColor(6); // Purple
866 vTB1->SetLineWidth(1);
867 vTB1->SetFillColor(vTB1->GetLineColor());
868 vTB1->SetFillStyle(4000); // 0% transparent
870 moth->AddNode(vM0,1,0); // Add virtual volume to mother
871 vA0->AddNode(vA1,1,0); // Put air inside carbon fiber.
872 vB0->AddNode(vB1,1,0); // Put air inside carbon fiber.
873 vTA0->AddNode(vTA1,1,0); // Put air inside carbon fiber.
874 vTB0->AddNode(vTB1,1,0); // Put air inside carbon fiber.
875 for(i=0;i<ksecNCoolingTubeDips;i++){
876 x0 = secX3[ksecDipIndex[i]];
877 y0 = secY3[ksecDipIndex[i]];
878 t = 90.0-secAngleTurbo[i];
879 trans = new TGeoTranslation("",x0,y0,0.5*(sB1->GetZ(0)+sB1->GetZ(1)));
880 vB1->AddNode(vTB0,i+1,trans);
881 rot = new TGeoRotation("",0.0,0.0,t);
882 rotrans = new TGeoCombiTrans("",x0,y0,0.0,rot);
883 vM0->AddNode(vTA0,i+1,rotrans);
884 //delete rot; // rot owned by AliITSv11GeometerySPD::CarbonFiberSector
886 vM0->AddNode(vA0,1,0);
887 vM0->AddNode(vB0,1,0);
889 vM0->AddNode(vB0,2,new TGeoRotation("",90.,0.,90.,90.,180.,0.));
903 //----------------------------------------------------------------------
904 void AliITSv11GeometrySPD::SPDsectorShape(Int_t n,const Double_t *xc,
905 const Double_t *yc,const Double_t *r,const Double_t *ths,const Double_t *the,
906 Int_t npr,Int_t &m,Double_t **xp,Double_t **yp){
907 // Code to compute the points that make up the shape of the SPD
908 // Carbon fiber support sections
910 // Int_t n Size of arrays xc,yc, and r.
911 // Double_t *xc Array of x values for radii centers.
912 // Double_t *yc Array of y values for radii centers.
913 // Double_t *r Array of signed radii values.
914 // Double_t *ths Array of starting angles [degrees].
915 // Double_t *the Array of ending angles [degrees].
916 // Int_t npr The number of lines segments to aproximate the arc.
918 // Int_t m The number of enetries in the arrays *xp[npr+1]
920 // Double_t **xp Array of x coordinate values of the line segments
921 // which make up the SPD support sector shape.
922 // Double_t **yp Array of y coordinate values of the line segments
923 // which make up the SPD support sector shape.
931 cout <<" X \t Y \t R \t S \t E"<< m <<endl;
933 cout <<"{"<< xc[i] <<",";
936 cout << ths[i] <<",";
937 cout << the[i] <<"},"<< endl;
941 if(GetDebug(3)) cout <<"Double_t sA0 = ["<< n*(npr+1)+1<<"][";
942 if(GetDebug(4)) cout <<"3]{";
943 else if(GetDebug(3)) cout <<"2]{";
946 t1 = (the[i]-ths[i])/t0;
947 if(GetDebug(5)) cout<<"t1="<< t1<<endl;
949 t=ths[i]+((Double_t)k)*t1;
950 xp[i][k] = TMath::Abs(r[i])*CosD(t)+xc[i];
951 yp[i][k] = TMath::Abs(r[i])*SinD(t)+yc[i];
953 cout << "{"<<xp[i][k]<<","<<yp[i][k];
954 if(GetDebug(4)) cout <<","<<t;
958 if(GetDebug(3)) cout << endl;
960 if(GetDebug(3)) cout<<"{"<<xp[0][0]<<","<<yp[0][0];
961 if(GetDebug(4)) cout<<","<< ths[0];
962 if(GetDebug(3)) cout<<"}}"<<endl;
966 //----------------------------------------------------------------------
967 void AliITSv11GeometrySPD::CreateFigure0(const Char_t *filepath,
970 // Creates Figure 0 for the documentation of this class. In this
971 // specific case, it creates the X,Y cross section of the SPD suport
972 // section, center and ends. The output is written to a standard
973 // file name to the path specificed.
975 // const Char_t *filepath Path where the figure is to be drawn
976 // const Char_t *type The type of file, default is gif.
977 // TGeoManager *mgr The TGeoManager default gGeoManager
982 TGeoXtru *sA0,*sA1,*sB0,*sB1;
983 //TPolyMarker *pmA,*pmB;
984 TPolyLine plA0,plA1,plB0,plB1;
987 Double_t x=0.0,y=0.0;
990 if(strcmp(filepath,"")){
991 Error("CreateFigure0","filepath=%s type=%s",filepath,type);
994 sA0 = (TGeoXtru*) mgr->GetVolume(
995 "ITSSPDCarbonFiberSupportSectorA0_1")->GetShape();
996 sA1 = (TGeoXtru*) mgr->GetVolume(
997 "ITSSPDCarbonFiberSupportSectorAirA1_1")->GetShape();
998 sB0 = (TGeoXtru*) mgr->GetVolume(
999 "ITSSPDCarbonFiberSupportSectorEndB0_1")->GetShape();
1000 sB1 = (TGeoXtru*) mgr->GetVolume(
1001 "ITSSPDCarbonFiberSupportSectorEndAirB1_1")->GetShape();
1002 //pmA = new TPolyMarker();
1003 //pmA.SetMarkerStyle(2); // +
1004 //pmA.SetMarkerColor(7); // light blue
1005 //pmB = new TPolyMarker();
1006 //pmB.SetMarkerStyle(5); // X
1007 //pmB.SetMarkerColor(6); // purple
1008 plA0.SetPolyLine(sA0->GetNvert());
1009 plA0.SetLineColor(1); // black
1010 plA0.SetLineStyle(1);
1011 plA1.SetPolyLine(sA1->GetNvert());
1012 plA1.SetLineColor(2); // red
1013 plA1.SetLineStyle(1);
1014 plB0.SetPolyLine(sB0->GetNvert());
1015 plB0.SetLineColor(3); // Green
1016 plB0.SetLineStyle(2);
1017 plB1.SetPolyLine(sB1->GetNvert());
1018 plB1.SetLineColor(4); // Blue
1019 plB1.SetLineStyle(2);
1020 //for(i=0;i<kNRadii;i++) pmA.SetPoint(i,xyB1p[i][0],xyB1p[i][1]);
1021 //for(i=0;i<kNRadii;i++) pmB.SetPoint(i,xyB1p[i][0],xyB1p[i][1]);
1022 for(i=0;i<sA0->GetNvert();i++) plA0.SetPoint(i,sA0->GetX(i),sA0->GetY(i));
1023 for(i=0;i<sA1->GetNvert();i++) plA1.SetPoint(i,sA1->GetX(i),sA1->GetY(i));
1024 for(i=0;i<sB0->GetNvert();i++) plB0.SetPoint(i,sB0->GetX(i),sB0->GetY(i));
1025 for(i=0;i<sB1->GetNvert();i++) plB1.SetPoint(i,sB1->GetX(i),sB1->GetY(i));
1026 canvas = new TCanvas("AliITSv11GeometrySPDFig0","",1000,1000);
1027 canvas->Range(-3.,-3.,3.,3.);
1028 txt.SetTextSize(0.05);
1029 txt.SetTextAlign(33);
1030 txt.SetTextColor(1);
1031 txt.DrawLatex(2.9,2.9,"Section A-A outer Carbon Fiber surface");
1032 txt.SetTextColor(2);
1033 txt.DrawLatex(2.9,2.5,"Section A-A Inner Carbon Fiber surface");
1034 txt.SetTextColor(3);
1035 txt.DrawLatex(2.9,2.1,"Section E-E outer Carbon Fiber surface");
1036 txt.SetTextColor(4);
1037 txt.DrawLatex(2.9,1.7,"Section E-E Inner Carbon Fiber surface");
1048 for(i=0;i<kNRadii;i++){
1049 sprintf(chr,"%2d",i);txt.DrawLatex(x-0.1,y,chr);
1050 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x,y,chr);
1051 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x+0.5,y,chr);
1052 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x+1.0,y,chr);
1053 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x+1.5,y,chr);
1054 sprintf(chr,"%8.4f",5.000);txt.DrawLatex(x+2.0,y,chr);
1055 if(kTRUE) txt.DrawLatex(x+2.5,y,"A-A/E-E");
1056 else txt.DrawLatex(x+2.5,y,"E-E");
1058 txt.DrawLatex(x,y,"x_{c} mm");
1059 txt.DrawLatex(x+0.5,y,"y_{c} mm");
1060 txt.DrawLatex(x+1.0,y,"R mm");
1061 txt.DrawLatex(x+1.5,y,"#theta_{start}^{#circle}");
1062 txt.DrawLatex(x+2.0,y,"#theta_{end}^{#circle}");
1063 txt.DrawLatex(x+2.5,y,"Section");
1067 //___________________________________________________________________________________________________________________
1068 TGeoVolume* AliITSv11GeometrySPD::CreateLadder
1069 (Int_t layer, Double_t &length, Double_t &width, Double_t &thickness, TGeoManager *mgr)
1072 // Creates the "ladder" = silicon sensor + 5 chips.
1073 // All parts are implemented as TGeoBBox and inserted
1074 // into a container which is the return value of this method.
1075 // This will allow to replicate this object many times, as required
1076 // for the implementation of half-staves.
1077 // The sizes of the components come from drawings
1078 // of the Technical office of INFN Padova
1081 // - the layer which will own this ladder (MUST be 1 or 2)
1082 // - the used TGeoManager
1085 // - the container TGeoBBox (return value)
1086 // - the size of the container box (arguments passed by reference)
1089 // Here and in the other methods which contribute to the stave definition
1090 // a convention is used for the naming of the three dimensions of the volumes:
1091 // - 'length' refers to the size in the Z direction of the ALICE reference frame
1092 // - 'width' refers to the "large" dimension orthogonal to Z axis in the local reference
1093 // frame of the object being implemented (e.g., 15.95 mm for the chips)
1094 // - 'thickness' refers to the "small" dimension orthogonal to Z axis, which is also
1095 // the direction along which the components are superimposed on each other
1098 // all sizes taken are expressed in mm in drawings, and this is kept as is, to avoid confusion
1099 // the conversion is made multiplying by the conversion factor
1102 // ** CRITICAL CHECK **
1103 // layer number can be ONLY 1 or 2
1104 if (layer != 1 && layer != 2) AliFatal("Required that layer number be 1 or 2");
1106 // instantiate all required media
1107 TGeoMedium *medVacuum = mgr->GetMedium("VACUUM");
1108 TGeoMedium *medSPDSiChip = mgr->GetMedium("SPD SI CHIP");
1109 TGeoMedium *medSi = mgr->GetMedium("SI");
1112 // they are expressed in mm in the drawings so they require conversion
1113 // 'widths' are in the direction of the detector length (Z axis)
1114 // 'thickness' is obvious
1115 // 'heights' are in the direction orthogonal to 'width' and 'thickness'
1116 Double_t chipThickness = fgkmm * 0.15;
1117 Double_t chipWidth = fgkmm * 15.95;
1118 Double_t chipLength = fgkmm * 13.60;
1119 Double_t chipSpacing = fgkmm * 0.40;
1120 Double_t chipBorder = fgkmm * 0.56;
1121 Double_t sensThickness = fgkmm * 0.20;
1122 Double_t sensWidth = fgkmm * 13.92;
1123 Double_t sensLength = fgkmm * 70.72;
1125 // create the container, bounded exactly around the limits of the ladder size
1126 // the 'thickness' is the sum of both thicknesses
1127 // the 'height' is the chip's one, which is larger
1128 // the 'width' is the one of the sensor, which contains all chips + a border
1129 // the name depends on the chosen layer number,
1130 // in order to respect ALICE sensitive volumes naming conventions
1131 thickness = sensThickness + chipThickness;
1133 length = sensLength;
1134 TGeoVolume *container = mgr->MakeBox(Form("LAY%d_LADDER", layer), medVacuum, 0.5*thickness, 0.5*width, 0.5*length);
1136 // create two volume boxes which describe the two involved objects:
1137 // - the sensor (large box, used once)
1138 // - the chip (small box, used 5 times)
1139 TGeoVolume *volSens = mgr->MakeBox("SENSOR", medSi, 0.5*sensThickness, 0.5*sensWidth, 0.5*sensLength);
1140 TGeoVolume *volChip = mgr->MakeBox("CHIP", medSPDSiChip, 0.5*chipThickness, 0.5*chipWidth, 0.5*chipLength);
1141 volSens->SetLineColor(kYellow + 1);
1142 volChip->SetLineColor(kGreen);
1144 // translation for the sensor box: direction of width (moved to edge of container) and thickness (moved up)
1145 Double_t x = 0.5 * (thickness - sensThickness);
1146 Double_t y = 0.5 * (width - sensWidth);
1148 TGeoTranslation *trSens = new TGeoTranslation(x, y, z);
1149 // translations for the chip box: direction of length and thickness (moved down)
1150 TGeoTranslation *trChip[5] = {0, 0, 0, 0, 0};
1151 x = 0.5 * (chipThickness - thickness);
1154 for (i = 0; i < 5; i++) {
1155 z = -0.5*length + chipBorder + (Double_t)i*chipSpacing + ((Double_t)(i) + 0.5)*chipLength;
1156 trChip[i] = new TGeoTranslation(x, y, z);
1159 // add nodes to container
1160 container->AddNode(volSens, 1, trSens);
1161 for (i = 0; i < 5; i++) container->AddNode(volChip, i + 2, trChip[i]);
1163 // return the container
1168 //___________________________________________________________________________________________________________________
1169 TGeoVolume* AliITSv11GeometrySPD::CreateGroundingFoilSingle
1170 (Bool_t kaptonLayer, Double_t &length, Double_t &width, Double_t &thickness, TGeoManager *mgr)
1173 // Creates the grounding foil layer made in Kapton.
1174 // Both layers of the grounding foil have the same shape, but with small
1175 // differences in the size of some parts (holes, overall size).
1176 // The Kapton layer is a little bit wider and has smaller holes.
1178 // The complete object is created as the superimposition of an XTRU with some holes
1180 // Whenever possible, the size of the parts is parameterized with
1181 // variable names, even if their value is fixed according
1182 // to the design parameters given by engineers' drawings.
1184 // Returns: a TGeoVolume object which contains all parts of this layer
1187 // The shape of the grounding foil is an irregular polygon, which can easily be implemented as
1188 // a TGeoXtru using the corners as reference points:
1191 // +---------------------------------------------------------------------------------------------------+
1193 // | +--------------+ +----------------+ 2
1195 // | 9 /-----+ 8 +------+ 4
1197 // | 11 /--------------/ 10
1198 // +------------------------------------/
1201 // in total: 14 points (X is just a referencem but is unused in the implementation.
1202 // The whole shape can be subdivided into sectors delimited by vertical lines passing
1203 // througth the points in the lower part of the shape. This convention is used to names
1204 // their length which is different for each one (the widths, instead, are common for some)
1206 // instantiate the media:
1207 // - kapton/aluminum for the pysical volumes
1208 TGeoMedium *material = kaptonLayer ? mgr->GetMedium("KAPTON") : mgr->GetMedium("AL");
1214 thickness = fgkmm * 0.05;
1218 thickness = fgkmm * 0.02;
1221 // define the length of all sectors (from leftmost to rightmost)
1223 Double_t sectorLength[] = { 140.71, 2.48, 26.78, 4.00, 10.00, 24.40, 10.00, 24.81 };
1225 sectorLength[0] -= 0.2;
1226 sectorLength[4] -= 0.2;
1227 sectorLength[5] += 0.4;
1228 sectorLength[6] -= 0.4;
1231 for (i = 0; i < 8; i++) {
1232 sectorLength[i] *= fgkmm;
1233 length += sectorLength[i];
1236 // as shown in the drawing, we have three different widths in this shape:
1237 Double_t widthMax = fgkmm * 15.95;
1238 Double_t widthMed1 = fgkmm * 15.00;
1239 Double_t widthMed2 = fgkmm * 11.00;
1240 Double_t widthMin = fgkmm * 4.40;
1242 widthMax -= fgkmm * 0.4;
1243 widthMed1 -= fgkmm * 0.4;
1244 widthMed2 -= fgkmm * 0.4;
1245 widthMin -= fgkmm * 0.4;
1249 // the vertices of the polygon are arrays correctly ordered in the counterclockwise direction:
1250 // initially we place the point 0 in the origin, and all others will be defined accordingly
1251 Double_t x[14], y[14];
1255 x[ 1] = x[0] + length;
1261 x[ 3] = x[2] - sectorLength[7];
1267 x[ 5] = x[4] - sectorLength[6];
1273 x[ 7] = x[6] - sectorLength[5];
1279 x[ 9] = x[8] - sectorLength[4];
1282 x[10] = x[9] - sectorLength[3];
1285 x[11] = x[10] - sectorLength[2];
1288 x[12] = x[11] - sectorLength[1];
1294 // then, we shift all points in such a way that the origin will be at the centers
1295 for (i = 0; i < 14; i++) {
1302 sprintf(shName, "SH_%sGFOIL_FULL", type);
1303 TGeoXtru *shGroundFull = new TGeoXtru(2);
1304 shGroundFull->SetName(shName);
1305 shGroundFull->DefinePolygon(14, x, y);
1306 shGroundFull->DefineSection(0, -0.5*thickness, 0., 0., 1.0);
1307 shGroundFull->DefineSection(1, 0.5*thickness, 0., 0., 1.0);
1309 // this volume contains some holes which are here implemented as simple boxes
1310 // of fixed size, which are displaced along the shape itself and then composed
1311 // using the facilities of the TGeo package
1313 Double_t holeLength = fgkmm * 10.00;
1314 Double_t holeWidth = fgkmm * 7.50;
1315 Double_t holeSepX0 = fgkmm * 7.05; // separation between center of first hole and left border
1316 Double_t holeSepXC = fgkmm * 14.00; // separation between the centers of two consecutive holes
1317 Double_t holeSepX1 = fgkmm * 15.42; // separation between centers of 5th and 6th hole
1318 Double_t holeSepX2 = fgkmm * 22.00; // separation between centers of 10th and 11th hole
1320 holeSepX0 -= fgkmm * 0.2;
1321 holeLength += fgkmm * 0.4;
1322 holeWidth += fgkmm * 0.4;
1325 // X position of hole center (will change for each hole)
1326 Double_t holeX = -0.5*length;
1327 // Y position of center of all holes (= 4.4 mm from upper border)
1328 Double_t holeY = 0.5*(width - holeWidth) - widthMin;
1329 //if (!kaptonLayer) holeY += 0.02;
1331 // create a shape for the holes (common)
1333 sprintf(holeName, "%sHOLE", type);
1334 TGeoBBox *shHole = 0;
1335 shHole = new TGeoBBox(holeName, 0.5*holeLength, 0.5*holeWidth, thickness);
1337 // insert the holes in the XTRU shape:
1338 // starting from the first value of X, they are simply shifted along this axis
1340 TGeoTranslation *transHole[11];
1341 TString strComposite(shName);
1342 strComposite.Append("-(");
1343 for (Int_t i = 0; i < 11; i++) {
1344 // set the position of the hole, depending on index
1360 sprintf(trName, "%sTR%d", type, i);
1361 transHole[i] = new TGeoTranslation(trName, holeX, holeY, 0.0);
1362 transHole[i]->RegisterYourself();
1363 strComposite.Append(holeName);
1364 strComposite.Append(":");
1365 strComposite.Append(trName);
1366 if (i < 10) strComposite.Append("+");
1367 cout << holeX << endl;
1369 strComposite.Append(")");
1370 cout << strComposite.Data() << endl;
1372 // create composite shape (with holes)
1373 TGeoCompositeShape *shGround = new TGeoCompositeShape(Form("SH_%sGFOIL", type), strComposite.Data());
1375 // create the volume
1376 TGeoVolume *vol = new TGeoVolume(Form("%sGFOIL", type), shGround, material);
1381 //___________________________________________________________________________________________________________________
1382 TGeoVolume* AliITSv11GeometrySPD::CreateGroundingFoilSingle
1383 (Bool_t kaptonLayer, Double_t &length, Double_t &width, Double_t &thickness, TGeoManager *mgr)
1386 // Creates the grounding foil layer made in Kapton.
1387 // Both layers of the grounding foil have the same shape, but with small
1388 // differences in the size of some parts (holes, overall size).
1389 // The Kapton layer is a little bit wider and has smaller holes.
1391 // The complete object is created as the sum of the following parts:
1392 // 1) the part which is connected to the chips, which is a
1393 // simple BOX with some box-shaped holes at regular intervals
1394 // 2) a trapezoidal connection where the Y size changes
1395 // 3) another box with a unique hole of the same shape and size as above
1396 // 4) another trapezoidal connection where the Y size changes
1397 // 5) a final part which is built as a sequence of 4 BOX volumes
1398 // where the first and the third are equal and the others have same size in Y.
1400 // Whenever possible, the size of the parts is parameterized with
1401 // variable names, even if their value is fixed according
1402 // to the design parameters given by engineers' drawings.
1404 // Returns: a TGeoVolume object which contanis all parts of this layer
1407 // instantiate the media:
1408 // - vacuum for the container volume
1409 // - kapton for the pysical volumes
1410 TGeoMedium *vacuum = mgr->GetMedium("VACUUM");
1411 TGeoMedium *material = mgr->GetMedium("KAPTON");
1413 // === Define size of all elements ===
1414 Double_t sizeZ = fgkmm * 0.05;
1416 Double_t part1X = fgkmm * 140.71;
1417 Double_t part2X = fgkmm * 2.48;
1418 Double_t part3X = fgkmm * 26.78;
1419 Double_t part4X = fgkmm * 4.00;
1420 Double_t part5X = fgkmm * 10.00;
1421 Double_t part6X = fgkmm * 24.40;
1422 Double_t part7X = fgkmm * 10.00;
1423 Double_t part8X = fgkmm * 24.81;
1425 Double_t sizeYMax = fgkmm * 15.95;
1426 Double_t sizeYMed1 = fgkmm * 15.00;
1427 Double_t sizeYMed2 = fgkmm * 11.00;
1428 Double_t sizeYMin = fgkmm * 4.40;
1430 Double_t holeX = fgkmm * 10.00;
1431 Double_t holeY = fgkmm * 7.50;
1432 Double_t holeSepX = fgkmm * 14.00; // separation between the centers of two consecutive holes
1433 Double_t holeSepX1 = fgkmm * 1.42; // to be added after 4th hole in volume 1
1434 Double_t holeFirstX = fgkmm * 7.05; // position of center of first hole
1435 Double_t holeSepY = fgkmm * 4.40; // dist between hole's and volume's upper border
1436 Double_t holeAloneX = fgkmm * 13.28; // position of hole center in box "part 3"
1438 // correct data in case we are on Aluminum foil
1440 material = mgr->GetMedium("AL");
1441 sizeZ = fgkmm * 0.02;
1442 part1X -= fgkmm * 0.2;
1443 part5X -= fgkmm * 0.2;
1444 part6X += fgkmm * 0.4;
1445 part7X -= fgkmm * 0.4;
1447 sizeYMax -= fgkmm * 0.4;
1448 sizeYMed1 -= fgkmm * 0.4;
1449 sizeYMed2 -= fgkmm * 0.4;
1450 sizeYMin -= fgkmm * 0.4;
1452 holeX += fgkmm * 0.4;
1453 holeY += fgkmm * 0.4;
1454 holeFirstX -= fgkmm * 0.2;
1455 holeSepY -= fgkmm * 0.4;
1458 // define names for the object
1460 if (kaptonLayer) strcpy(type, "KAP"); else strcpy(type, "ALU");
1462 // compute full length and width
1463 length = part1X + part2X + part3X + part4X + part5X + part6X + part7X + part8X;
1467 // grounding foil world, bounded exactly around the limits of the structure
1468 TGeoVolume *container = mgr->MakeBox(Form("GFOIL_%s", type), vacuum, 0.5*length, 0.5*sizeYMax, 0.5*sizeZ);
1470 // === PART 1: box with holes ===
1472 TGeoBBox *shBox1 = 0, *shHole = 0;
1473 shBox1 = new TGeoBBox(Form("GF%s_BOX1", type), 0.5*part1X, 0.5*sizeYMax, 0.5*sizeZ);
1474 shHole = new TGeoBBox(Form("GF%s_HOLE", type), 0.5*holeX, 0.5*holeY, 0.5*sizeZ + 0.01);
1476 // define the position of all holes and compose the expression
1477 // to define the composite shape (box - holes)
1478 Double_t firstX = -0.5*part1X + holeFirstX;
1479 Double_t transY = 0.5*sizeYMax - holeSepY - 0.5*holeY;
1481 TGeoTranslation *transHole[10];
1482 TString strComposite(Form("%s - (", shBox1->GetName()));
1483 for (Int_t i = 0; i < 10; i++) {
1484 transX = firstX + (Double_t)i * holeSepX;
1485 if (i > 4) transX += holeSepX1;
1486 transHole[i] = new TGeoTranslation(Form("TGF%s_HOLE%d", type, i), transX, transY, 0.0);
1487 transHole[i]->RegisterYourself();
1488 strComposite.Append(Form("%s:%s", shHole->GetName(), transHole[i]->GetName()));
1489 if (i < 9) strComposite.Append("+"); else strComposite.Append(")");
1491 // create composite shape
1492 TGeoCompositeShape *shPart1 = new TGeoCompositeShape(Form("GF%s_PART1_SHAPE", type), strComposite.Data());
1493 // create the volume
1494 TGeoVolume *volPart1 = new TGeoVolume(Form("GF%s_PART1", type), shPart1, material);
1496 // === PART 2: first trapezoidal connection
1498 TGeoArb8 *shTrap1 = new TGeoArb8(0.5*sizeZ);
1499 shTrap1->SetVertex(0, -0.5*part2X, 0.5*sizeYMax);
1500 shTrap1->SetVertex(1, 0.5*part2X, 0.5*sizeYMax);
1501 shTrap1->SetVertex(2, 0.5*part2X, 0.5*sizeYMax - sizeYMed1);
1502 shTrap1->SetVertex(3, -0.5*part2X, -0.5*sizeYMax);
1503 shTrap1->SetVertex(4, -0.5*part2X, 0.5*sizeYMax);
1504 shTrap1->SetVertex(5, 0.5*part2X, 0.5*sizeYMax);
1505 shTrap1->SetVertex(6, 0.5*part2X, 0.5*sizeYMax - sizeYMed1);
1506 shTrap1->SetVertex(7, -0.5*part2X, -0.5*sizeYMax);
1507 TGeoVolume *volPart2 = new TGeoVolume(Form("GF%s_PART2", type), shTrap1, material);
1509 // === PART 3: other box with one hole
1511 TGeoBBox *shBox2 = 0;
1512 shBox2 = new TGeoBBox(Form("GF%s_BOX2", type), 0.5*part3X, 0.5*sizeYMed1, 0.5*sizeZ);
1514 // define the position of the hole
1515 transX = holeAloneX - 0.5*part3X;
1516 TGeoTranslation *transHoleAlone = new TGeoTranslation(Form("TGF%s_HOLE_ALONE", type), transX, transY, 0.0);
1517 transHoleAlone->RegisterYourself();
1518 // create composite shape
1519 TGeoCompositeShape *shPart3 = new TGeoCompositeShape(Form("GF%sPART3_SHAPE", type), Form("%s - %s:%s", shBox2->GetName(), shHole->GetName(), transHoleAlone->GetName()));
1520 // create the volume
1521 TGeoVolume *volPart3 = new TGeoVolume(Form("GF%s_PART3", type), shPart3, material);
1523 // === PART 4: second trapezoidal connection
1525 TGeoArb8 *shTrap2 = new TGeoArb8(0.5*sizeZ);
1526 shTrap2->SetVertex(0, -0.5*part4X, 0.5*sizeYMed1);
1527 shTrap2->SetVertex(1, 0.5*part4X, 0.5*sizeYMed1);
1528 shTrap2->SetVertex(2, 0.5*part4X, 0.5*sizeYMed1 - sizeYMed2);
1529 shTrap2->SetVertex(3, -0.5*part4X, -0.5*sizeYMed1);
1530 shTrap2->SetVertex(4, -0.5*part4X, 0.5*sizeYMed1);
1531 shTrap2->SetVertex(5, 0.5*part4X, 0.5*sizeYMed1);
1532 shTrap2->SetVertex(6, 0.5*part4X, 0.5*sizeYMed1 - sizeYMed2);
1533 shTrap2->SetVertex(7, -0.5*part4X, -0.5*sizeYMed1);
1534 TGeoVolume *volPart4 = new TGeoVolume(Form("GF%s_PART4", type), shTrap2, material);
1536 // === PART 5 --> 8: sequence of boxes ===
1538 TGeoVolume *volPart5 = mgr->MakeBox(Form("GF%s_BOX3", type), material, 0.5*part5X, 0.5*sizeYMed2, 0.5*sizeZ);
1539 TGeoVolume *volPart6 = mgr->MakeBox(Form("GF%s_BOX4", type), material, 0.5*part6X, 0.5*sizeYMin , 0.5*sizeZ);
1540 TGeoVolume *volPart7 = mgr->MakeBox(Form("GF%s_BOX5", type), material, 0.5*part7X, 0.5*sizeYMed2, 0.5*sizeZ);
1541 TGeoVolume *volPart8 = mgr->MakeBox(Form("GF%s_BOX6", type), material, 0.5*part8X, 0.5*sizeYMin , 0.5*sizeZ);
1543 // === SET COLOR ===
1545 volPart1->SetLineColor(kRed + 3);
1546 volPart2->SetLineColor(kRed + 3);
1547 volPart3->SetLineColor(kRed + 3);
1548 volPart4->SetLineColor(kRed + 3);
1549 volPart5->SetLineColor(kRed + 3);
1550 volPart6->SetLineColor(kRed + 3);
1551 volPart7->SetLineColor(kRed + 3);
1552 volPart8->SetLineColor(kRed + 3);
1555 volPart1->SetLineColor(kGreen);
1556 volPart2->SetLineColor(kGreen);
1557 volPart3->SetLineColor(kGreen);
1558 volPart4->SetLineColor(kGreen);
1559 volPart5->SetLineColor(kGreen);
1560 volPart6->SetLineColor(kGreen);
1561 volPart7->SetLineColor(kGreen);
1562 volPart8->SetLineColor(kGreen);
1565 // === TRANSLATION OF ALL PARTS ===
1567 transX = 0.5*(part1X - length);
1568 TGeoTranslation *transPart1 = new TGeoTranslation(transX, 0.0, 0.0);
1569 transX += 0.5*(part1X + part2X);
1570 TGeoTranslation *transPart2 = new TGeoTranslation(transX, 0.0, 0.0);
1571 transX += 0.5*(part2X + part3X);
1572 transY = 0.5*(sizeYMax - sizeYMed1);
1573 TGeoTranslation *transPart3 = new TGeoTranslation(transX, transY, 0.0);
1574 transX += 0.5*(part3X + part4X);
1575 TGeoTranslation *transPart4 = new TGeoTranslation(transX, transY, 0.0);
1576 transX += 0.5*(part4X + part5X);
1577 transY = 0.5*(sizeYMax - sizeYMed2);
1578 TGeoTranslation *transPart5 = new TGeoTranslation(transX, transY, 0.0);
1579 transX += 0.5*(part5X + part6X);
1580 transY = 0.5*(sizeYMax - sizeYMin);
1581 TGeoTranslation *transPart6 = new TGeoTranslation(transX, transY, 0.0);
1582 transX += 0.5*(part6X + part7X);
1583 transY = 0.5*(sizeYMax - sizeYMed2);
1584 TGeoTranslation *transPart7 = new TGeoTranslation(transX, transY, 0.0);
1585 transX += 0.5*(part7X + part8X);
1586 transY = 0.5*(sizeYMax - sizeYMin);
1587 TGeoTranslation *transPart8 = new TGeoTranslation(transX, transY, 0.0);
1589 // add the partial volumes to the container
1590 container->AddNode(volPart1, 1, transPart1);
1591 container->AddNode(volPart2, 2, transPart2);
1592 container->AddNode(volPart3, 3, transPart3);
1593 container->AddNode(volPart4, 4, transPart4);
1594 container->AddNode(volPart5, 5, transPart5);
1595 container->AddNode(volPart6, 6, transPart6);
1596 container->AddNode(volPart7, 7, transPart7);
1597 container->AddNode(volPart8, 8, transPart8);
1602 //___________________________________________________________________________________________________________________
1603 TGeoVolume* AliITSv11GeometrySPD::CreateGroundingFoil(Double_t &thickness, TGeoManager *mgr)
1606 // Joins two Kapton and two Aluminum layers of the grounding foil
1607 // in order to create the complete grounding foil for a whole stave.
1608 // into a unique container volume, which is returned as output.
1609 // The use of the TGeoXtru shape requires that in the separate foils, the Z axis
1610 // lies perpendicularly to the polygonal basis of this shape; this caused the components
1611 // to have their Z axis corresponding to the X axis of the ALICE reference frame and
1612 // vieceversa; to correct this, a rotation is necessary around their middle axis,
1613 // to exchange X and Z axes and displace the object correctly in the ALICE frame.
1616 // - the sizes of the container box (passed by reference and filled here)
1617 // - the TGeoManager
1620 // - the container TGeoBBox (return value)
1621 // - the size of the container (reference variables)
1624 // sizes of the added volumes, which are filled by passing them
1625 // to the volume creation methods
1626 Double_t kpLength, kpWidth, kpThick;
1627 Double_t alLength, alWidth, alThick;
1628 Double_t separation = fgkmm * 1.42; // separation between left and right volumes
1630 // create the two component volumes (each one will be replicated twice)
1631 // this gives also the size of their virtual container boxes (just a reference, not a volume)
1632 TGeoVolume *kVol = CreateGroundingFoilSingle(kTRUE, kpLength, kpWidth, kpThick, mgr);
1633 TGeoVolume *aVol = CreateGroundingFoilSingle(kFALSE, alLength, alWidth, alThick, mgr);
1634 kVol->SetLineColor(kRed);
1635 aVol->SetLineColor(kGray);
1637 // kapton leads the total size of the foil (including spagcing of 1.42 mm between them in the center)
1638 Double_t length, width;
1639 length = 2.0 * kpLength + separation;
1641 thickness = kpThick + alThick;
1643 // create the container
1644 TGeoMedium *vacuum = mgr->GetMedium("VACUUM");
1645 TGeoVolume *container = mgr->MakeBox("GFOIL", vacuum, 0.5*thickness, 0.5*width, 0.5*length);
1647 // create the common correction rotations
1648 TGeoRotation *rotCorr1 = new TGeoRotation(*gGeoIdentity);
1649 TGeoRotation *rotCorr2 = new TGeoRotation(*gGeoIdentity);
1650 rotCorr1->RotateY(-90.0);
1651 rotCorr2->RotateY( 90.0);
1653 // compute the translations to place the objects at the edges of the volume
1654 // the kapton foils are also shifted down, and the aluminum foils are shifted up
1655 // with respect to the thickness direction
1656 TGeoTranslation *kTrans1 = new TGeoTranslation(0.5*(-thickness + kpThick), 0.0, 0.5*( length - kpLength));
1657 TGeoTranslation *kTrans2 = new TGeoTranslation(0.5*(-thickness + kpThick), 0.0, 0.5*(-length + kpLength));
1658 TGeoTranslation *aTrans1 = new TGeoTranslation(0.5*( thickness - alThick), 0.0, 0.5*( length - alLength) - 0.02);
1659 TGeoTranslation *aTrans2 = new TGeoTranslation(0.5*( thickness - alThick), 0.0, 0.5*(-length + alLength) + 0.02);
1661 // combine translations and rotations
1662 TGeoCombiTrans *kCombi1 = new TGeoCombiTrans(*kTrans1, *rotCorr1);
1663 TGeoCombiTrans *kCombi2 = new TGeoCombiTrans(*kTrans2, *rotCorr2);
1664 TGeoCombiTrans *aCombi1 = new TGeoCombiTrans(*aTrans1, *rotCorr1);
1665 TGeoCombiTrans *aCombi2 = new TGeoCombiTrans(*aTrans2, *rotCorr2);
1668 container->AddNode(kVol, 0, kCombi1);
1669 container->AddNode(kVol, 1, kCombi2);
1670 container->AddNode(aVol, 0, aCombi1);
1671 container->AddNode(aVol, 1, aCombi2);
1676 //______________________________________________________________________
1677 TGeoVolume* AliITSv11GeometrySPD::CreateMCMBase(TGeoManager *geom)
1680 // Creates the MCM basis volume.
1681 // It is a little bit more complicated because this is a plain base
1682 // with a poly shape similar to the one of grounding foil but there are also
1683 // some chips glued to its base and covered with a cave cap.
1685 // The complete MCM object is created as the sum of the following parts:
1686 // 1) a planar basis shaped according to the MCM typical shape
1687 // 2) some boxes which represent the chips and devices mounted on this base
1688 // 3) a cave cap which covers the portion of MCM containing these chips
1690 // Due to the different widths of MCM, it is implemented in a more complicated way:
1691 // - cap and chips will define a sub-volume of this structure, which can be bounded
1692 // by a complete box
1693 // - base of MCM will be a separate volume
1694 // - these two objects will need to be glued together into an upper-level volume
1696 // This metod creates only the thin base (point 1 in the list)
1700 TGeoMedium *medBase = geom->GetMedium("MCM BASE");
1702 // parameterize the interesting sizes of MCM
1703 // it is divided into 3 sectors which have different size in X and Y and
1704 // are connected by trapezoidal-based shapes, where the oblique angle
1705 // makes a 45 degrees angle with the vertical, so that the X size and Y size
1706 // of these "intermezzo"'s is the same
1707 // +--------------------------------+
1709 // | sect 1 --------------------+
1711 Double_t sizeZ = fgkmm * 0.35;
1712 Double_t sizeXtot = fgkmm * 105.6;
1713 Double_t sizeXsector[3] = {fgkmm * 28.4, fgkmm * 41.4, fgkmm * 28.8};
1714 Double_t sizeYsector[3] = {fgkmm * 15.0, fgkmm * 11.0, fgkmm * 8.0};
1715 Double_t sizeSep01 = fgkmm * 4.0, sizeSep12 = fgkmm * 3.0;
1716 Double_t sizeHole = fgkmm * 1.0;
1717 Double_t posHoleX = fgkmm * -0.5*sizeXtot + 26.7 + 0.5*sizeHole;
1718 Double_t posHoleY = fgkmm * -0.5*sizeYsector[0] + 0.5*sizeHole;
1720 // define the shape of base volume as an XTRU with two identical faces
1721 // distantiated by the width of the itself
1722 Double_t x[8], y[8];
1723 x[0] = -0.5*sizeXtot;
1724 y[0] = 0.5*sizeYsector[0];
1728 y[2] = y[1] - sizeYsector[2];
1729 x[3] = x[2] - sizeXsector[2];
1731 x[4] = x[3] - sizeSep12;
1732 y[4] = y[3] - sizeSep12;
1733 x[5] = x[4] - sizeXsector[1];
1735 x[6] = x[5] - sizeSep01;
1736 y[6] = y[5] - sizeSep01;
1741 TGeoXtru *shPoly = new TGeoXtru(2);
1742 shPoly->SetName("SH_MCMBASE_POLY");
1743 shPoly->DefinePolygon(8, x, y);
1744 shPoly->DefineSection(0, -0.5*sizeZ, 0., 0., 1.0);
1745 shPoly->DefineSection(1, 0.5*sizeZ, 0., 0., 1.0);
1747 // create small hole
1748 TGeoBBox *shHole = 0;
1749 shHole = new TGeoBBox("SH_MCMBASE_HOLE", 0.5*sizeHole, 0.5*sizeHole, 0.5*sizeZ+0.01);
1750 TGeoTranslation *transHole = new TGeoTranslation("TR_MCMBASE_HOLE", posHoleX, posHoleY, 0.0);
1751 transHole->RegisterYourself();
1753 // create shape intersection
1754 TGeoCompositeShape *shBase = new TGeoCompositeShape("SH_MCMBASE", "SH_MCMBASE_POLY - SH_MCMBASE_HOLE:TR_MCMBASE_HOLE");
1757 TGeoVolume *volBase = new TGeoVolume("VOL_MCMBASE", shBase, medBase);
1758 volBase->SetLineColor(kRed);
1764 //______________________________________________________________________
1765 TGeoVolume* AliITSv11GeometrySPD::CreateMCMCoverBorder(TGeoManager *geom)
1768 // Creates the MCM basis volume.
1769 // It is a little bit more complicated because this is a plain base
1770 // with a poly shape similar to the one of grounding foil but there are also
1771 // some chips glued to its base and covered with a cave cap.
1773 // The complete MCM object is created as the sum of the following parts:
1774 // 1) a planar basis shaped according to the MCM typical shape
1775 // 2) some boxes which represent the chips and devices mounted on this base
1776 // 3) a cave cap which covers the portion of MCM containing these chips
1778 // Due to the different widths of MCM, it is implemented in a more complicated way:
1779 // - cap and chips will define a sub-volume of this structure, which can be bounded
1780 // by a complete box
1781 // - base of MCM will be a separate volume
1782 // - these two objects will need to be glued together into an upper-level volume
1784 // This metod creates the thicker cap and its contents (points 2-3 in the list).
1785 // Since it covers only two of the three sectors of the MCM base with different width
1786 // the computations and variables related to the largest sector are removed, while
1787 // the other are the same as the other part of the MCM.
1791 TGeoMedium *medCap = geom->GetMedium("MCM COVER");
1793 // parameterize the interesting sizes of MCM
1794 // it is divided into 3 sectors which have different size in X and Y and
1795 // are connected by trapezoidal-based shapes, where the oblique angle
1796 // makes a 45 degrees angle with the vertical, so that the X size and Y size
1797 // of these "intermezzo"'s is the same
1798 // +--------------------------------+
1800 // | sect 1 --------------------+
1802 Double_t sizeZ = fgkmm * 0.3;
1803 Double_t capHeight = fgkmm * 1.7 - sizeZ;
1804 Double_t sizeXtot = fgkmm * 73.2;
1805 Double_t sizeXsector[2] = {fgkmm * 41.4, fgkmm * 28.8};
1806 Double_t sizeYsector[2] = {fgkmm * 11.0, fgkmm * 8.0};
1807 Double_t sizeSep = fgkmm * 3.0;
1809 // === PART 1: border ===
1811 // define the shape of base volume as an XTRU with two identical faces
1812 // distantiated by the width of the itself
1813 Double_t x[6], y[6];
1814 x[0] = -0.5*sizeXtot;
1815 y[0] = 0.5*sizeYsector[0];
1819 y[2] = y[1] - sizeYsector[1];
1820 x[3] = x[2] - sizeXsector[1];
1822 x[4] = x[3] - sizeSep;
1823 y[4] = y[3] - sizeSep;
1827 // create outer border shape with above coordinates
1828 TGeoXtru *capOut = new TGeoXtru(2);
1829 capOut->SetName("SH_MCMCAPOUT");
1830 capOut->DefinePolygon(6, x, y);
1831 capOut->DefineSection(0, -0.5*capHeight, 0., 0., 1.0);
1832 capOut->DefineSection(1, 0.5*capHeight, 0., 0., 1.0);
1834 // the inner border is built similarly but subtracting the thickness
1835 Double_t angle = 45.0;
1836 Double_t cs = TMath::Cos( 0.5*(TMath::Pi() - angle*TMath::DegToRad()) );
1837 Double_t xin[6], yin[6];
1838 xin[0] = x[0] + sizeZ;
1839 yin[0] = y[0] - sizeZ;
1840 xin[1] = x[1] - sizeZ;
1843 yin[2] = y[2] + sizeZ;
1844 xin[3] = x[3] - sizeZ*cs;
1846 xin[4] = xin[3] - sizeSep;
1847 yin[4] = y[4] + sizeZ;
1851 // create inner border shape
1852 TGeoXtru *capIn = new TGeoXtru(2);
1853 capIn->SetName("SH_MCMCAPIN");
1854 capIn->DefinePolygon(6, xin, yin);
1855 capIn->DefineSection(0, -0.5*capHeight-0.01, 0., 0., 1.0);
1856 capIn->DefineSection(1, 0.5*capHeight+0.01, 0., 0., 1.0);
1859 TGeoCompositeShape *shBorder = new TGeoCompositeShape("SH_MCMCAPBORDER", "SH_MCMCAPOUT-SH_MCMCAPIN");
1862 TGeoVolume *volBorder = new TGeoVolume("VOL_MCMCAPBORDER", shBorder, medCap);
1863 volBorder->SetLineColor(kGreen);
1868 //______________________________________________________________________
1869 TGeoVolume* AliITSv11GeometrySPD::CreateMCMCoverTop(TGeoManager *geom)
1872 // Creates the MCM basis volume.
1873 // It is a little bit more complicated because this is a plain base
1874 // with a poly shape similar to the one of grounding foil but there are also
1875 // some chips glued to its base and covered with a cave cap.
1877 // The complete MCM object is created as the sum of the following parts:
1878 // 1) a planar basis shaped according to the MCM typical shape
1879 // 2) some boxes which represent the chips and devices mounted on this base
1880 // 3) a cave cap which covers the portion of MCM containing these chips
1882 // Due to the different widths of MCM, it is implemented in a more complicated way:
1883 // - cap and chips will define a sub-volume of this structure, which can be bounded
1884 // by a complete box
1885 // - base of MCM will be a separate volume
1886 // - these two objects will need to be glued together into an upper-level volume
1888 // This metod creates the thicker cap and its contents (points 2-3 in the list).
1889 // Since it covers only two of the three sectors of the MCM base with different width
1890 // the computations and variables related to the largest sector are removed, while
1891 // the other are the same as the other part of the MCM.
1895 TGeoMedium *medCap = geom->GetMedium("MCM COVER");
1897 // parameterize the interesting sizes of MCM
1898 // it is divided into 3 sectors which have different size in X and Y and
1899 // are connected by trapezoidal-based shapes, where the oblique angle
1900 // makes a 45 degrees angle with the vertical, so that the X size and Y size
1901 // of these "intermezzo"'s is the same
1902 // +--------------------------------+
1904 // | sect 1 --------------------+
1906 Double_t sizeZ = fgkmm * 0.3;
1907 Double_t sizeXtot = fgkmm * 73.2;
1908 Double_t sizeXsector[2] = {fgkmm * 41.4, fgkmm * 28.8};
1909 Double_t sizeYsector[2] = {fgkmm * 11.0, fgkmm * 8.0};
1910 Double_t sizeSep = fgkmm * 3.0;
1912 // === PART 1: border ===
1914 // define the shape of base volume as an XTRU with two identical faces
1915 // distantiated by the width of the itself
1916 Double_t x[6], y[6];
1917 x[0] = -0.5*sizeXtot;
1918 y[0] = 0.5*sizeYsector[0];
1922 y[2] = y[1] - sizeYsector[1];
1923 x[3] = x[2] - sizeXsector[1];
1925 x[4] = x[3] - sizeSep;
1926 y[4] = y[3] - sizeSep;
1930 // create outer border shape with above coordinates
1931 TGeoXtru *capOut = new TGeoXtru(2);
1932 capOut->SetName("SH_MCMCAPOUT");
1933 capOut->DefinePolygon(6, x, y);
1934 capOut->DefineSection(0, -0.5*sizeZ, 0., 0., 1.0);
1935 capOut->DefineSection(1, 0.5*sizeZ, 0., 0., 1.0);
1937 // the inner border is built similarly but subtracting the thickness
1938 Double_t angle = 45.0;
1939 Double_t cs = TMath::Cos( 0.5*(TMath::Pi() - angle*TMath::DegToRad()) );
1940 Double_t xin[6], yin[6];
1941 xin[0] = x[0] + sizeZ;
1942 yin[0] = y[0] - sizeZ;
1943 xin[1] = x[1] - sizeZ;
1946 yin[2] = y[2] + sizeZ;
1947 xin[3] = x[3] - sizeZ*cs;
1949 xin[4] = xin[3] - sizeSep;
1950 yin[4] = y[4] + sizeZ;
1954 // coverage of upper part (equal to external border, but full)
1955 TGeoXtru *shCover = new TGeoXtru(2);
1956 shCover->SetName("SH_MCMCAPCOVER");
1957 shCover->DefinePolygon(6, x, y);
1958 shCover->DefineSection(0, -0.5*sizeZ, 0., 0., 1.0);
1959 shCover->DefineSection(1, 0.5*sizeZ, 0., 0., 1.0);
1962 TGeoVolume *volCover = new TGeoVolume("VOL_MCMCAPCOVER", shCover, medCap);
1963 volCover->SetLineColor(kBlue);
1968 //______________________________________________________________________
1969 TGeoVolumeAssembly* AliITSv11GeometrySPD::CreateStave
1970 (Int_t layer, Double_t &fullThickness, TGeoManager *mgr)
1973 // Creates the complete stave as an assembly which contains all the stuff defined
1974 // in the "CreateStaveBase" method (which are the thin part of the structure)
1975 // and adds to this the thick cover of the MCM and the Pixel bus.
1976 // This is done as an assembly to avoid the problem of a "ghost" overlap which occurs
1977 // when putting the stave on the carbon fiber sector, in the case that we define it
1978 // as a volume container.
1981 // - the layer where the stave has to be put (hard check on this)
1982 // - the geometry manager
1985 // ** CRITICAL CHECK **
1986 // layer number can be ONLY 1 or 2
1987 if (layer != 1 && layer != 2) AliFatal("Required that layer number be 1 or 2");
1989 // sizes regarding the components
1990 Double_t baseWidth, baseHeight, baseThickness;
1991 Double_t mcmCapBorderThickness = fgkmm * 0.3;
1992 Double_t mcmCapThickness = fgkmm * 1.7 - mcmCapBorderThickness;
1993 Double_t mcmCapHeight = fgkmm * 11.0;
1994 Double_t mcmCapWidth = fgkmm * 73.2;
1997 TGeoVolumeAssembly *container = new TGeoVolumeAssembly(Form("LAY%d_FULLSTAVE", layer));
1999 // create subvolumes
2000 TGeoVolume *staveBase = CreateStaveBase(layer, baseWidth, baseHeight, baseThickness, mgr);
2001 TGeoVolume *mcmCapBorder = CreateMCMCoverBorder(mgr);
2002 TGeoVolume *mcmCapTop = CreateMCMCoverTop(mgr);
2003 TGeoVolumeAssembly *bus0 = CreatePixelBusAndExtensions(kTRUE, mgr); // bus in z > 0
2004 TGeoVolumeAssembly *bus1 = CreatePixelBusAndExtensions(kFALSE, mgr); // bus in z < 0
2006 // the full width and height of the area which contains all components
2007 // corresponds to the one of the stave base built with the "CreateStaveBase" method
2008 // while the thickness must be computed as the sum of this base + the cover
2009 fullThickness = baseThickness + mcmCapThickness + mcmCapBorderThickness;
2013 // translations (in the X direction, MCM is at the same level as ladder)
2014 Double_t xBase = -0.5*fullThickness + 0.5*baseThickness;
2015 TGeoTranslation *trBase = new TGeoTranslation(xBase, 0.0, 0.0);
2016 Double_t xMCMCapB = xBase + 0.5*baseThickness + 0.5*mcmCapThickness;
2017 Double_t xMCMCapT = xMCMCapB + 0.5*mcmCapThickness + 0.5*mcmCapBorderThickness;
2018 Double_t yMCMCap = 0.5*(baseHeight - mcmCapHeight);
2019 Double_t zMCMCap1 = 0.5*baseWidth - 0.5*mcmCapWidth;
2020 Double_t zMCMCap0 = -zMCMCap1;
2021 // correction rotations
2022 TGeoRotation *rotCorr0 = new TGeoRotation(*gGeoIdentity);
2023 TGeoRotation *rotCorr1 = new TGeoRotation(*gGeoIdentity);
2024 rotCorr0->RotateY( 90.0);
2025 rotCorr1->RotateY(-90.0);
2026 TGeoCombiTrans *trMCMCapBorder0 = new TGeoCombiTrans(xMCMCapB, yMCMCap, zMCMCap0, rotCorr0);
2027 TGeoCombiTrans *trMCMCapBorder1 = new TGeoCombiTrans(xMCMCapB, yMCMCap, zMCMCap1, rotCorr1);
2028 TGeoCombiTrans *trMCMCapTop0 = new TGeoCombiTrans(xMCMCapT, yMCMCap, zMCMCap0, rotCorr0);
2029 TGeoCombiTrans *trMCMCapTop1 = new TGeoCombiTrans(xMCMCapT, yMCMCap, zMCMCap1, rotCorr1);
2031 container->AddNode(staveBase, 0, trBase);
2032 container->AddNode(mcmCapBorder, 0, trMCMCapBorder0);
2033 container->AddNode(mcmCapBorder, 1, trMCMCapBorder1);
2034 container->AddNode(mcmCapTop, 0, trMCMCapTop0);
2035 container->AddNode(mcmCapTop, 1, trMCMCapTop1);
2040 // for the moment, a correction amount of 0.04 is required to place correctly the object in X
2041 // and another correction of 0.015 in Z
2042 Double_t busHeight = fgkmm * 13.8;
2043 Double_t xPixelBus = xBase + baseThickness + 0.04;
2044 Double_t yPixelBus1 = 0.5*baseHeight - 0.5*busHeight + 0.5*(baseHeight - busHeight);
2045 Double_t zPixelBus0 = -0.25*baseWidth + 0.015 - 0.03;
2046 //Double_t zPixelBus0 = -0.5*(0.5*baseWidth - 0.04);
2047 Double_t zPixelBus1 = -zPixelBus0;
2048 // correction rotations
2049 TGeoRotation *rotCorrBus1 = new TGeoRotation(*gGeoIdentity);
2050 rotCorrBus1->RotateX(180.0);
2051 //TGeoCombiTrans *trBus0 = new TGeoCombiTrans(xPixelBus, 0.0, zPixelBus0, rotCorrBus);
2052 TGeoTranslation *trBus0 = new TGeoTranslation(xPixelBus, 0.0, zPixelBus0);
2053 //TGeoTranslation *trBus1 = new TGeoTranslation(xPixelBus, 0.0, zPixelBus1);
2054 TGeoCombiTrans *trBus1 = new TGeoCombiTrans(xPixelBus, yPixelBus1, zPixelBus1, rotCorrBus1);
2057 container->AddNode(bus0, 0, trBus0);
2058 container->AddNode(bus1, 1, trBus1);
2063 //______________________________________________________________________
2064 TGeoVolumeAssembly* AliITSv11GeometrySPD::CreatePixelBusAndExtensions(Bool_t zpos, TGeoManager *mgr)
2067 // Creates an assembly which contains the pixel bus and its extension
2068 // and the extension of the MCM.
2069 // By: Renaud Vernet
2070 // NOTE: to be defined its material and its extension in the outside direction
2073 // ==== constants =====
2076 TGeoMedium *medPixelBus = mgr->GetMedium("PIXEL BUS") ;
2077 TGeoMedium *medPBExtender = mgr->GetMedium("PIXEL BUS EXTENDER") ;
2078 TGeoMedium *medMCMExtender = mgr->GetMedium("MCM EXTENDER") ;
2080 //geometrical constants
2081 const Double_t groundingThickness = 0.07 * fgkmm ;
2082 const Double_t grounding2pixelBusDz = 0.625 * fgkmm ;
2083 const Double_t pixelBusThickness = 0.28 * fgkmm ;
2084 const Double_t groundingWidthX = 170.501 * fgkmm ;
2085 const Double_t pixelBusContactDx = 1.099 * fgkmm ;
2086 const Double_t pixelBusWidthY = 13.8 * fgkmm ;
2087 const Double_t pixelBusContactPhi = 20.0 * TMath::Pi()/180. ; //design=20 deg.
2088 const Double_t pbExtenderPsi = 70.0 * TMath::Pi()/180. ; //design=?? 70 deg. seems OK
2089 const Double_t pbExtenderWidthY = 11.0 * fgkmm ;
2090 const Double_t pbExtenderTopZ = 2.72 * fgkmm ;
2091 const Double_t mcmThickness = 0.35 * fgkmm ;
2092 const Double_t mcmExtenderThickness = 0.20 * fgkmm ;
2093 const Double_t deltaMcmMcmextender = 1.6 * fgkmm ;
2094 const Double_t halfStaveTotalLength = 247.64 * fgkmm ;
2095 const Double_t deltaYOrigin = 15.95/2.* fgkmm ;
2096 const Double_t deltaXOrigin = 1.1 * fgkmm ;
2097 const Double_t deltaZOrigin = halfStaveTotalLength / 2. ;
2099 const Double_t grounding2pixelBusDz2 = grounding2pixelBusDz+groundingThickness/2. + pixelBusThickness/2. ;
2100 const Double_t pixelBusWidthX = groundingWidthX ;
2101 const Double_t pixelBusRaiseLength = (pixelBusContactDx-pixelBusThickness*TMath::Sin(pixelBusContactPhi))/TMath::Cos(pixelBusContactPhi) ;
2102 const Double_t pbExtenderBaseZ = grounding2pixelBusDz2 + pixelBusRaiseLength*TMath::Sin(pixelBusContactPhi) + 2*pixelBusThickness*TMath::Sin(pixelBusContactPhi)*TMath::Tan(pixelBusContactPhi) ;
2103 const Double_t pbExtenderDeltaZ = pbExtenderTopZ-pbExtenderBaseZ ;
2105 const Double_t pbExtenderEndPointX = 2*deltaZOrigin - groundingWidthX - 2*pixelBusThickness*TMath::Sin(pixelBusContactPhi) ;
2106 const Double_t mcmextenderEndPointX = deltaZOrigin - 48.2 * fgkmm ;
2107 const Double_t mcmExtenderWidthY = pbExtenderWidthY ;
2109 //===== end constants =====
2113 // ----------------- CREATE THE PIXEL BUS --------------------------
2114 // At the end of the pixel bus, a small piece is added for the contact
2115 // with the pixel bus extender.
2116 // The whole piece is made with an extrusion, using 7 points
2121 // +-----------------------------+ /
2123 // +-----------------------------+--+
2126 // The length of the pixel bus is defined (170.501mm) by the technical design
2127 // this length corresponds to distance [0-1] and [6-5]
2131 TGeoVolumeAssembly *pixelBus = new TGeoVolumeAssembly("PIXEL BUS");
2133 // definition of the 7 points for the extrusion
2134 Double_t pixelBusXtruX[7] = {
2135 -pixelBusWidthX/2. ,
2137 pixelBusWidthX/2. + pixelBusThickness * TMath::Sin(pixelBusContactPhi) ,
2138 pixelBusWidthX/2. + pixelBusThickness * TMath::Sin(pixelBusContactPhi) + pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) ,
2139 pixelBusWidthX/2. + pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) ,
2143 Double_t pixelBusXtruY[7] = {
2144 -pixelBusThickness/2. ,
2145 -pixelBusThickness/2. ,
2146 -pixelBusThickness/2. + pixelBusThickness * (1 - TMath::Cos(pixelBusContactPhi)) ,
2147 -pixelBusThickness/2. + pixelBusThickness * (1 - TMath::Cos(pixelBusContactPhi)) + pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) ,
2148 pixelBusThickness/2. + pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) ,
2149 pixelBusThickness/2. ,
2150 pixelBusThickness/2.
2153 // creation of the volume
2154 TGeoXtru *pixelBusXtru = new TGeoXtru(2);
2155 TGeoVolume* pixelBusXtruVol = new TGeoVolume("pixelBusXtru",pixelBusXtru,medPixelBus) ;
2156 pixelBusXtru->DefinePolygon(7,pixelBusXtruX,pixelBusXtruY);
2157 pixelBusXtru->DefineSection(0,-pixelBusWidthY/2.);
2158 pixelBusXtru->DefineSection(1, pixelBusWidthY/2.);
2159 // --------------- END PIXEL BUS ----------------------------------------------------
2162 // ------------------------- CREATE THE PIXEL BUS EXTENDER --------------------------
2163 // The geometry of the extender is a bit complicated sinceit is constrained
2164 // to be in contact with the pixel bus.
2165 // It consists of an extrusion using 13 points as shows the scheme below :
2168 // +---+---------------------+
2171 // / +---------------------+
2175 // +---+-----------+ /
2178 // / +-----------+---+
2187 // ==== constants =====
2188 const Double_t pbExtenderXtru3L = 1.5 * fgkmm ; //arbitrary ?
2189 const Double_t pbExtenderXtru4L = (pbExtenderDeltaZ + pixelBusThickness*(TMath::Cos(pbExtenderPsi)-2))/TMath::Sin(pbExtenderPsi) ;
2190 //===== end constants =====
2192 TGeoVolumeAssembly *pbExtender = new TGeoVolumeAssembly("PIXEL BUS EXTENDER");
2194 Double_t pbExtenderXtruX[13] = {
2196 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) ,
2197 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) + pbExtenderXtru3L ,
2198 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) + pbExtenderXtru3L + pixelBusThickness * TMath::Sin(pbExtenderPsi) ,
2199 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) + pbExtenderXtru3L + pixelBusThickness * TMath::Sin(pbExtenderPsi) + pbExtenderXtru4L * TMath::Cos(pbExtenderPsi) ,
2200 pbExtenderEndPointX ,
2201 pbExtenderEndPointX ,
2202 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) + pbExtenderXtru3L + pixelBusThickness * TMath::Sin(pbExtenderPsi) + pbExtenderXtru4L * TMath::Cos(pbExtenderPsi) ,
2203 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) + pbExtenderXtru3L + pixelBusThickness * TMath::Sin(pbExtenderPsi) + pbExtenderXtru4L * TMath::Cos(pbExtenderPsi) - pixelBusThickness * TMath::Sin(pbExtenderPsi),
2204 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) + pbExtenderXtru3L ,
2205 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) ,
2206 pixelBusRaiseLength * TMath::Cos(pixelBusContactPhi) - pixelBusThickness*TMath::Sin(pixelBusContactPhi) ,
2207 -pixelBusThickness * TMath::Sin(pixelBusContactPhi)
2209 Double_t pbExtenderXtruY[13] = {
2211 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) ,
2212 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) ,
2213 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness * (1-TMath::Cos(pbExtenderPsi)) ,
2214 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness * (1-TMath::Cos(pbExtenderPsi)) + pbExtenderXtru4L * TMath::Sin(pbExtenderPsi) ,
2215 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness * (1-TMath::Cos(pbExtenderPsi)) + pbExtenderXtru4L * TMath::Sin(pbExtenderPsi) ,
2216 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness * (1-TMath::Cos(pbExtenderPsi)) + pbExtenderXtru4L * TMath::Sin(pbExtenderPsi) + pixelBusThickness ,
2217 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness * (1-TMath::Cos(pbExtenderPsi)) + pbExtenderXtru4L * TMath::Sin(pbExtenderPsi) + pixelBusThickness ,
2218 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness + pbExtenderXtru4L * TMath::Sin(pbExtenderPsi)
2220 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness ,
2221 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness ,
2222 pixelBusRaiseLength * TMath::Sin(pixelBusContactPhi) + pixelBusThickness*TMath::Cos(pixelBusContactPhi) ,
2223 pixelBusThickness * TMath::Cos(pixelBusContactPhi)
2226 // creation of the volume
2227 TGeoXtru *pbExtenderXtru = new TGeoXtru(2);
2228 TGeoVolume *pbExtenderXtruVol = new TGeoVolume("pbExtenderXtru",pbExtenderXtru,medPBExtender) ;
2229 pbExtenderXtru->DefinePolygon(13,pbExtenderXtruX,pbExtenderXtruY);
2230 pbExtenderXtru->DefineSection(0,-pbExtenderWidthY/2.);
2231 pbExtenderXtru->DefineSection(1, pbExtenderWidthY/2.);
2232 // -------------- END PIXEL BUS EXTENDER -------------------------------------------------
2235 // ------------------ CREATE THE MCM EXTENDER ------------------------------------
2237 // The MCM extender is located betwen the MCM and the Pixel Bus Extender
2238 // It consists of an extrusion using 10 points as shows the scheme below :
2241 // +---+---------------------+
2244 // / +---------------------+
2251 // +-----------+---+
2257 const Double_t mcmExtenderXtru3L = 1.5 * fgkmm ;
2260 TGeoVolumeAssembly *mcmExtender = new TGeoVolumeAssembly("MCM EXTENDER");
2261 Double_t mcmExtenderXtruX[10] = {
2264 mcmExtenderXtru3L + mcmExtenderThickness * TMath::Sin(pbExtenderPsi) ,
2265 mcmExtenderXtru3L + mcmExtenderThickness * TMath::Sin(pbExtenderPsi) + deltaMcmMcmextender / TMath::Tan(pbExtenderPsi) ,
2266 mcmextenderEndPointX ,
2267 mcmextenderEndPointX ,
2268 mcmExtenderXtru3L + mcmExtenderThickness * TMath::Sin(pbExtenderPsi) + deltaMcmMcmextender / TMath::Tan(pbExtenderPsi) ,
2269 mcmExtenderXtru3L + deltaMcmMcmextender / TMath::Tan(pbExtenderPsi) ,
2274 Double_t mcmExtenderXtruY[10] = {
2277 mcmExtenderThickness * (1-TMath::Cos(pbExtenderPsi)) ,
2278 mcmExtenderThickness * (1-TMath::Cos(pbExtenderPsi)) + deltaMcmMcmextender ,
2279 mcmExtenderThickness * (1-TMath::Cos(pbExtenderPsi)) + deltaMcmMcmextender ,
2280 mcmExtenderThickness * (2-TMath::Cos(pbExtenderPsi)) + deltaMcmMcmextender ,
2281 mcmExtenderThickness * (2-TMath::Cos(pbExtenderPsi)) + deltaMcmMcmextender ,
2282 mcmExtenderThickness + deltaMcmMcmextender ,
2283 mcmExtenderThickness ,
2284 mcmExtenderThickness ,
2287 // creation of the volume
2288 TGeoXtru *mcmExtenderXtru = new TGeoXtru(2);
2289 TGeoVolume *mcmExtenderXtruVol = new TGeoVolume("mcmExtenderXtru",mcmExtenderXtru,medMCMExtender) ;
2290 mcmExtenderXtru->DefinePolygon(10,mcmExtenderXtruX,mcmExtenderXtruY);
2291 mcmExtenderXtru->DefineSection(0,-mcmExtenderWidthY/2.);
2292 mcmExtenderXtru->DefineSection(1, mcmExtenderWidthY/2.);
2295 //-------------- DEFINITION OF GEOMETRICAL TRANSFORMATIONS -------------------
2296 TGeoRotation * commonRot = new TGeoRotation("commonRot",0,90,0);
2297 commonRot->MultiplyBy(new TGeoRotation("rot",-90,0,0)) ;
2298 TGeoTranslation * pixelBusTrans = new TGeoTranslation(pixelBusThickness/2. - deltaXOrigin + 0.52*fgkmm ,
2299 -pixelBusWidthY/2. + deltaYOrigin ,
2300 -groundingWidthX/2. + deltaZOrigin) ;
2301 TGeoRotation * pixelBusRot = new TGeoRotation(*commonRot);
2302 TGeoTranslation * pbExtenderTrans = new TGeoTranslation(*pixelBusTrans) ;
2303 TGeoRotation * pbExtenderRot = new TGeoRotation(*pixelBusRot) ;
2304 pbExtenderTrans->SetDz(*(pbExtenderTrans->GetTranslation()+2) - pixelBusWidthX/2. - 2*pixelBusThickness*TMath::Sin(pixelBusContactPhi)) ;
2306 pbExtenderTrans->SetDy(*(pbExtenderTrans->GetTranslation()+1) - (pixelBusWidthY - pbExtenderWidthY)/2.);
2309 pbExtenderTrans->SetDy(*(pbExtenderTrans->GetTranslation()+1) + (pixelBusWidthY - pbExtenderWidthY)/2.);
2311 pbExtenderTrans->SetDx(*(pbExtenderTrans->GetTranslation()) + pixelBusThickness/2 + 2*pixelBusThickness*TMath::Sin(pixelBusContactPhi)*TMath::Tan(pixelBusContactPhi)) ;
2312 TGeoTranslation * mcmExtenderTrans = new TGeoTranslation(0.12*fgkmm + mcmThickness - deltaXOrigin,
2313 pbExtenderTrans->GetTranslation()[1],
2315 TGeoRotation * mcmExtenderRot = new TGeoRotation(*pbExtenderRot);
2318 //ADD NODES TO ASSEMBLIES
2319 pixelBus ->AddNode((TGeoVolume*)pixelBusXtruVol,0);
2320 pbExtender ->AddNode((TGeoVolume*)pbExtenderXtruVol,0);
2321 mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtruVol,0);
2322 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru3Vol,0);
2323 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru3PrimVol,1);
2324 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru4Vol,2);
2325 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru4PrimVol,3);
2326 // mcmExtender ->AddNode((TGeoVolume*)mcmExtenderXtru5Vol,4);
2329 //CREATE FINAL VOLUME ASSEMBLY AND ROTATE IT
2330 TGeoVolumeAssembly *assembly = new TGeoVolumeAssembly("EXTENDERS");
2331 assembly->AddNode((TGeoVolume*)pixelBus ,0, new TGeoCombiTrans(*pixelBusTrans,*pixelBusRot));
2332 assembly->AddNode((TGeoVolume*)pbExtender ,0, new TGeoCombiTrans(*pbExtenderTrans,*pbExtenderRot));
2333 assembly->AddNode((TGeoVolume*)mcmExtender ,0, new TGeoCombiTrans(*mcmExtenderTrans,*mcmExtenderRot));
2334 assembly->SetTransparency(50);
2338 //______________________________________________________________________
2339 TGeoVolume* AliITSv11GeometrySPD::CreateStaveBase
2340 (Int_t layer, Double_t &fullWidth, Double_t &fullHeight, Double_t &fullThickness, TGeoManager *mgr)
2343 // Creates a box which contains the followin parts of the whole stave:
2344 // - the two layers of grounding foil
2346 // - the thin base of the MCM (except its thick cover)
2349 // Since it is required by detector numbering conventions,
2350 // it is required as argument the layer which owns this stave.
2351 // This number will be used to define the name of the ladder volume,
2352 // which must be different for layer1 and layer2 objects.
2355 // - layer number (will be checked to be 1 or 2)
2356 // - geometry manager
2359 // - a TGeoBBox volume containing all this stuff
2360 // - the size of the container box are stored in the reference-passed variables
2363 // sizes of all objects to be inserted
2364 // these values are used to compute the total volume of the container
2365 // and to compute parametrically the position of each piece, instead
2366 // of putting hard-coded number (this helps in eventually modifying everything)
2367 Double_t mcmThickness = fgkmm * 0.35;
2368 Double_t grndThickness = fgkmm * 0.07; // = 0.05 + 0.02
2369 Double_t sepThickness = fgkmm * 0.05;
2371 Double_t ladderWidth = fgkmm * 70.72;
2372 Double_t mcmWidth = fgkmm * 105.60;
2373 Double_t sepLaddersWidth = fgkmm * 0.20;
2374 Double_t sepMCMWidth = fgkmm * 0.30;
2375 Double_t sepLaddersCtr = fgkmm * 0.40; // separations between central ladders in the two half-staves
2377 Double_t mcmHeight = fgkmm * 15.00;
2379 // compute the size of the container
2380 fullWidth = 2.0*sepLaddersCtr + 4.0*ladderWidth + 2.0*sepMCMWidth + 2.0*sepLaddersWidth + 2.0*mcmWidth;
2381 fullHeight = fgkmm * 15.95;
2382 fullThickness = grndThickness + sepThickness + mcmThickness;
2384 // create the container
2385 TGeoVolume *container = mgr->MakeBox(Form("LAY%d_STAVE", layer), mgr->GetMedium("VACUUM"), 0.5*fullThickness, 0.5*fullHeight, 0.5*fullWidth);
2387 // fill the container going from bottom to top
2388 // with respect to the thickness direction
2390 // 1 - Grounding foil
2392 TGeoVolume *grndVol = CreateGroundingFoil(grndThickness);
2394 Double_t xGrnd = -0.5*fullThickness + 0.5*grndThickness;
2395 TGeoTranslation *grndTrans = new TGeoTranslation(xGrnd, 0.0, 0.0);
2397 container->AddNode(grndVol, 1, grndTrans);
2400 // volume (will be replicated 4 times)
2401 Double_t ladderLength, ladderThickness;
2402 TGeoVolume *ladder = CreateLadder(layer, ladderLength, ladderWidth, ladderThickness, mgr);
2403 // translations (in thickness direction, the MCM thickness is used)
2404 // layers are sorted going from the one at largest Z to the one at smallest Z:
2405 // -|Zmax| ------> |Zmax|
2407 // but it is more comfortable to start defining their Z position from center
2408 Double_t xLad = xGrnd + 0.5*grndThickness + 0.5*mcmThickness + sepThickness;
2409 Double_t zLad1 = -0.5*ladderWidth - sepLaddersCtr;
2410 Double_t zLad0 = zLad1 - ladderWidth - sepLaddersWidth;
2411 Double_t zLad2 = -zLad1;
2412 Double_t zLad3 = -zLad0;
2413 TGeoRotation *rotLad = new TGeoRotation(*gGeoIdentity);// rotLad->RotateZ(180.0);
2414 TGeoCombiTrans *trLad0 = new TGeoCombiTrans(xLad, 0.0, zLad0, rotLad);
2415 TGeoCombiTrans *trLad1 = new TGeoCombiTrans(xLad, 0.0, zLad1, rotLad);
2416 TGeoCombiTrans *trLad2 = new TGeoCombiTrans(xLad, 0.0, zLad2, rotLad);
2417 TGeoCombiTrans *trLad3 = new TGeoCombiTrans(xLad, 0.0, zLad3, rotLad);
2419 container->AddNode(ladder, 0, trLad0);
2420 container->AddNode(ladder, 1, trLad1);
2421 container->AddNode(ladder, 2, trLad2);
2422 container->AddNode(ladder, 3, trLad3);
2424 // 3 - MCM (only the base, the cover is added as a separate volume in a more global 'stave' assembly
2425 // volume (will be replicated twice)
2426 TGeoVolume *mcm = CreateMCMBase(mgr);
2427 // translations (in the X direction, MCM is at the same level as ladder)
2428 // the two copies of the MCM are placed at the same distance from the center, on both sides
2429 // and their sorting is the same as ladders' one (MCM0 is at Z < 0, MCM1 at Z > 0);
2430 Double_t xMCM = xLad;
2431 Double_t yMCM = 0.5*(fullHeight - mcmHeight);
2432 Double_t zMCM1 = zLad3 + 0.5*ladderWidth + 0.5*mcmWidth + sepMCMWidth;
2433 Double_t zMCM0 = -zMCM1;
2434 // create the common correction rotations
2435 TGeoRotation *rotCorr0 = new TGeoRotation(*gGeoIdentity);
2436 TGeoRotation *rotCorr1 = new TGeoRotation(*gGeoIdentity);
2437 rotCorr0->RotateY( 90.0);
2438 rotCorr1->RotateY(-90.0);
2439 TGeoCombiTrans *trMCM0 = new TGeoCombiTrans(xMCM, yMCM, zMCM0, rotCorr0);
2440 TGeoCombiTrans *trMCM1 = new TGeoCombiTrans(xMCM, yMCM, zMCM1, rotCorr1);
2442 container->AddNode(mcm, 0, trMCM0);
2443 container->AddNode(mcm, 1, trMCM1);
2448 //______________________________________________________________________
2449 void AliITSv11GeometrySPD::StavesInSector(TGeoVolume *moth, TGeoManager *mgr)
2452 // Unification of essentially two methods:
2453 // - the one which creates the sector structure
2454 // - the one which returns the complete stave
2456 // For compatibility, this method requires the same arguments
2457 // asked by "CarbonFiberSector" method, which is recalled here.
2458 // Like this cited method, this one does not return any value,
2459 // but it inserts in the mother volume (argument 'moth') all the stuff
2460 // which composes the complete SPD sector.
2462 // Arguments: see description of "CarbonFiberSector" method.
2465 // This service class is useful to this method only
2466 // to store in a meaningful way the data about the
2467 // rounded corners of the support, and some computations
2468 // which could turn out to be useful for stave placement
2469 // 'left' and 'right' (L/R) here are considered looking the support
2470 // from the positive Z side.
2471 // The sign of the radius is used to know what kind of tangent
2472 // must be found for the two circles which describe the rounded angles.
2473 class clsSupportPlane {
2475 Double_t xL, yL, rL, sL; // curvature center and radius (with sign) of left corner
2476 Double_t xR, yR, rR, sR; // curvature center and radius (with sign) of right corner
2477 Double_t shift; // shift from the innermost position (where the stave edge is
2478 // in the point where the rounded corner begins
2480 // Constructor with arguments which allow to set directly everything
2481 // since the values are given in millimiters from drawings, they must be converted to cm
2483 (Double_t xLin, Double_t yLin, Double_t rLin, Double_t sLin,
2484 Double_t xRin, Double_t yRin, Double_t rRin, Double_t sRin, Double_t shiftin) :
2485 xL(xLin), yL(yLin), rL(rLin), sL(sLin), xR(xRin), yR(yRin), rR(rRin), sR(sRin), shift(shiftin)
2496 // Computation of the line tangent to both circles defined here
2497 // which is taken above or below the center according to the radius sign.
2498 // This method returns:
2499 // - the mid-popint of the segment between the two points where the tangent touches the two circles,
2500 // - the inclination of this segment
2501 // - the half-length of this segment
2502 Double_t TangentSegment(Double_t &midX, Double_t &midY, Double_t &phi)
2504 // compute the straight line which is tangent to the two circles
2505 // and extract its inclination 'phi' w.r. to X axis
2506 Double_t dx = xL - xR;
2507 Double_t dy = yL - yR;
2508 Double_t R = rL*sL + rR*sR;
2509 Double_t delta = dy*dy + dx*dx - R*R;
2510 Double_t tan05phi = (-dy + TMath::Sqrt(delta)) / (R - dx);
2511 phi = 2.0 * TMath::ATan(tan05phi);
2512 // compute the points where this line touchs the two circles
2513 Double_t leftX = xL + sL*rL*TMath::Cos(phi);
2514 Double_t leftY = yL + sL*rL*TMath::Sin(phi);
2515 Double_t rightX = xR + sR*rR*TMath::Cos(phi);
2516 Double_t rightY = yR + sR*rR*TMath::Sin(phi);
2517 // compute the mid point
2518 midX = 0.5 * (leftX + rightX);
2519 midY = 0.5 * (leftY + rightY);
2520 // compute angular coefficient for the line joining
2521 // the two points found using the above method
2522 dx = rightX - leftX;
2523 dy = rightY - leftY;
2524 phi = TMath::ATan2(dy, dx);
2525 // compute the half-length of this segment
2526 Double_t len = 0.5*TMath::Sqrt((rightX-leftX)*(rightX-leftX) + (rightY-leftY)*(rightY-leftY));
2527 cout << 2.0*len << endl;
2532 // instantiate this class for each layer1 and layer2 corners
2533 clsSupportPlane *plane[6] = {0, 0, 0, 0, 0, 0};
2536 plane[0] = new clsSupportPlane( 10.830, 16.858, 0.60, 1., 19.544, 10.961, 0.8, 1., 1.816);
2537 plane[1] = new clsSupportPlane(- 0.733, 17.486, 0.60, 1., 11.581, 13.371, 0.6, -1., -0.610);
2538 plane[2] = new clsSupportPlane(-12.252, 16.298, 0.60, 1., 0.562, 14.107, 0.6, -1., -0.610);
2539 plane[3] = new clsSupportPlane(-22.276, 12.948, 0.85, 1., -10.445, 13.162, 0.6, -1., -0.610);
2541 plane[4] = new clsSupportPlane(- 3.123, -14.618, 0.50, 1., 11.280, -14.473, 0.9, -1., -0.691);
2542 plane[5] = new clsSupportPlane(-13.187, -19.964, 0.50, -1., - 3.833, -17.805, 0.6, -1., 1.300);
2544 // put the sector in the container
2545 //CarbonFiberSector(moth, xAAtubeCenter0, yAAtubeCenter0, mgr);
2547 // create stave volume
2548 Double_t staveHeight = 1.595, staveThickness;
2549 TGeoVolume *stave1 = CreateStave(1, staveThickness, gGeoManager);
2550 TGeoVolume *stave2 = CreateStave(2, staveThickness, gGeoManager);
2552 // compute positions and rotation angles
2553 Double_t xm, ym, halfPlaneHeight, heightDiff, position, phi, xPos, yPos;
2554 for (Int_t i = 0; i < 6; i++) {
2555 // recall the geometry computations defined for the classe
2556 halfPlaneHeight = plane[i]->TangentSegment(xm, ym, phi);
2557 // compute the difference between plane and stave heights
2558 heightDiff = halfPlaneHeight - 0.5*staveHeight;
2559 // It is necessary to shift the stave by at least
2560 // an amount equal to this difference
2561 // to avoid overlaps.
2562 // Moreover, some more shift is done for building reasons,
2563 // and it depends on the single plane (data-member 'shift')
2564 position = heightDiff + plane[i]->shift;
2565 // taking into account this shift plus another in the direction
2566 // normal to the support plane, due to the stave thickness,
2567 // the final position of the stave is computed in a temporary reference frame
2568 // where the mid-point of the support plane is in the origin
2570 ParallelPosition(0.5*staveThickness, position, phi, xPos, yPos);
2573 ParallelPosition(-0.5*staveThickness, -position, phi, xPos, yPos);
2576 ParallelPosition(-0.5*staveThickness, -position, phi, xPos, yPos);
2578 // then we go into the true reference frame
2583 TGeoVolume *tubeTemp1 = mgr->MakeTube("tubeTemp1", NULL, 0.0, 0.01, 50.0);
2584 TGeoTranslation *trTemp1 = new TGeoTranslation(xm, ym, 0.0);
2585 tubeTemp1->SetLineColor(kRed);
2586 moth->AddNode(tubeTemp1, i + 1, trTemp1);
2587 TGeoVolume *tubeTemp2 = mgr->MakeTube("tubeTemp2", NULL, 0.0, 0.01, 50.0);
2588 TGeoTranslation *trTemp2 = new TGeoTranslation(xPos, yPos, 0.0);
2589 tubeTemp2->SetLineColor(kBlue);
2590 moth->AddNode(tubeTemp2, i + 1, trTemp2);
2593 // using the parameters found here, compute the
2594 // translation and rotation of this stave:
2595 TGeoRotation *rot = new TGeoRotation(*gGeoIdentity);
2596 if (i >= 4) rot->RotateY(180.0);
2597 rot->RotateZ(90.0 + phi * TMath::RadToDeg());
2598 TGeoCombiTrans *trans = new TGeoCombiTrans(xPos, yPos, 0.0, rot);
2600 moth->AddNode(stave2, i, trans);
2603 moth->AddNode(stave1, i - 4, trans);
2608 //______________________________________________________________________
2609 void AliITSv11GeometrySPD::ParallelPosition(Double_t dist1, Double_t dist2, Double_t phi, Double_t &x, Double_t &y)
2612 // Performs the following steps:
2613 // 1 - finds a straight line parallel to the one passing through the origin and with angle 'phi' with X axis
2614 // (phi in RADIANS);
2615 // 2 - finds another line parallel to the previous one, with a distance 'dist1' from it
2616 // 3 - takes a reference point in the second line in the intersection between the normal to both lines
2617 // passing through the origin
2618 // 4 - finds a point whith has distance 'dist2' from this reference, in the second line (point 2)
2620 // According to the signs given to dist1 and dist2, the point is found in different position w.r. to the origin
2623 // compute the point
2624 Double_t cs = TMath::Cos(phi);
2625 Double_t sn = TMath::Sin(phi);
2627 x = dist2*cs - dist1*sn;
2628 y = dist1*cs + dist2*sn;