EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MapsGeoParData.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MapsGeoParData.cxx
1 //
2 // AYK (ayk@bnl.gov), 2014/08/07
3 //
4 // MAPS geometry description file;
5 //
6 
7 #include <iostream>
8 using namespace std;
9 
10 #include <assert.h>
11 
12 #include <MapsGeoParData.h>
13 
14 #include <TMath.h>
15 #include <TGeoTrd1.h>
16 #include <TGeoArb8.h>
17 #include <TGeoTube.h>
18 #include <TGeoTorus.h>
19 #include <TGeoCompositeShape.h>
20 
21 #include <EtmOrphans.h>
22 #include <MapsGeoParData.h>
23 #include <MapsMimosaAssembly.h>
24 
25 // ---------------------------------------------------------------------------------------
26 
27 MapsGeoParData::MapsGeoParData(const char *detName, int version, int subVersion):
28  EicGeoParData(detName, version, subVersion),
29  // For now assume these variables will not be needed -> no EicPOD inheritance;
30  mMountingRingBeamLineThickness ( 5.00 * etm::mm),
31  mMountingRingRadialThickness ( 5.00 * etm::mm),
32  mWaterPipeExtensionLength ( 4.00 * etm::mm),
33  mEnforcementBracketThickness ( 1.00 * etm::mm),
34  mUseTriangularAssemblies (true),
35  mWithMountingRings (false),
36  mWithEnforcementBrackets (false),
37  mWithExternalPipes (false),
38  mCarbonFiberMaterial ("MapsCarbonFiber"),
39  mKaptonMaterial ("MapsKapton")
40 {
42 
43  // Transient variables;
46 } // MapsGeoParData::MapsGeoParData()
47 
48 // ---------------------------------------------------------------------------------------
49 
50 TGeoVolume *MapsGeoParData::ConstructMimosaCell(MapsMimosaAssembly *mcell, unsigned id)
51 {
52  const char *detName = mDetName->Name().Data();
53 
54  // Do not mind to create different names for each layer, even if some layers
55  // have the same building blocks;
56  char flexName[128], aluStripName[128], flatRoofName[128], roofSideBeamName[128];
57  char waterPipeName[128], waterName[128], apexEnforcementBeamName[128];
58  char coldPlateName[128], sideWallName[128], baseEnforcementBeamName[128];
59 
60  snprintf(flexName, 128-1, "%sCellFlexLayer%02d", detName, id);
61  snprintf(aluStripName, 128-1, "%sAluStrips%02d", detName, id);
62  snprintf(coldPlateName, 128-1, "%sColdPlate%02d", detName, id);
63  snprintf(mMimosaShellName, 128-1, "%sMimosaShell%02d", detName, id);
64  snprintf(mMimosaCoreName, 128-1, "%sMimosaCore%02d", detName, id);
65  snprintf(waterPipeName, 128-1, "%sWaterPipe%02d", detName, id);
66  snprintf(waterName, 128-1, "%sWater%02d", detName, id);
67  snprintf(apexEnforcementBeamName, 128-1, "%sEnforcementBeamApex%02d", detName, id);
68  snprintf(baseEnforcementBeamName, 128-1, "%sEnforcementBeamBase%02d", detName, id);
69  snprintf(sideWallName, 128-1, "%sSideWall%02d", detName, id);
70  snprintf(flatRoofName, 128-1, "%sFlatRoof%02d", detName, id);
71  snprintf(roofSideBeamName, 128-1, "%sRoofSideBeam%02d", detName, id);
72  snprintf(mCellAssemblyName, 128-1, "%sChipAssembly%02d", detName, id);
73 
74  // Used throughout the code;
77 
78  // Compose elementary cell volume with the Mimosa 34 chip inside;
79  TGeoVolume *vcell;
80  if (mUseTriangularAssemblies) {//UseTriangularAssemblies()) {
81  // This is fine for the VST;
82  TGeoTrd1 *trd1 = new TGeoTrd1(mCellAssemblyName,
83  mcell->mAssemblyBaseWidth/2,
84  0.0,
86  mAssemblyHeight/2);
87 
88  vcell = new TGeoVolume(mCellAssemblyName, trd1, GetMedium(_AIR_));
89  }
90  else {
91  char tmp1Name[128], tmp2Name[128];
92 
93  snprintf(tmp1Name, 128-1, "%sTmp1Volume%02d", detName, id);
94  snprintf(tmp2Name, 128-1, "%sTmp2Volume%02d", detName, id);
95 
96  // FIXME: re-activate this code back (if it is supported by VGM and G4 graphics of course);
97  assert(0);
98  // For FST/BST have to cut triangular cell edges, otherwise can not come close enough
99  // to the beam pipe; TGeoCompositeShape has problems with drawing of course, but
100  // I set it invisible in eventDisplay.C anyway; NB: one could arrange Arb8 shape with
101  // only one edge cut, but then I'd have to re-orient all the subvolumes because Z axis
102  // would be oriented differently -> forget it;
103 #if _DISABLED_ANYWAY_
104  TGeoTrd1 *tmp1 = new TGeoTrd1(tmp1Name,
105  0.1 * mcell->mAssemblyBaseWidth/2,
106  0.0,
107  0.1 * mAssemblyLength/2,
108  0.1 * mAssemblyHeight/2);
109  TGeoBBox *tmp2 = new TGeoBBox(tmp2Name,
110  0.1 * mcell->mAssemblyBaseWidth/2,
111  //0.1 * mcell->mAssemblyDeadMaterialWidth/2,
112  0.1 * mAssemblyLength/2,
113  0.1 * mAssemblyHeight/2);
114  TGeoCompositeShape *cs = new TGeoCompositeShape(mCellAssemblyName, TString(tmp1Name) + "*" + TString(tmp2Name));
115 
116  vcell = new TGeoVolume(mCellAssemblyName, cs, GetMedium(_AIR_));
117 #endif
118  } //if
119 
120  double aluThickness = 0.0, kaptonThickness = 0.0, carbonThickness = 0.0, waterThickness = 0.0;
121 
122  // A running variable (accumulated offset);
123  double zOffset = -mAssemblyHeight/2;// + 1E-6;
124 
125  // Create internal chip assembly cell structure;
126  {
127  //
128  // FIXME: make a routine to add a single Z-layer;
129  //
130 
131  // Flex Printed Circuit;
132  {
133 
135  kaptonThickness += mcell->mFlexCableKaptonThickness;
136  else {
137  TGeoBBox *flex = new TGeoBBox(flexName,
139  mAssemblyLength/2,
140  mcell->mFlexCableKaptonThickness/2);
141  TGeoVolume *vflex = new TGeoVolume(flexName, flex, GetMedium(mKaptonMaterial));
142 
143  vcell->AddNode(vflex, 0, new TGeoCombiTrans(0.0, 0.0, (zOffset + mcell->mFlexCableKaptonThickness/2), 0));
144  } //if
145 
146  // Yes, want to keep precise track on the silicon chip final offset, so it is the same in
147  // all three "fs", "ss", "ns" geometries;
148  zOffset += mcell->mFlexCableKaptonThickness;
149  }
150 
151  // Alu strips;
152  {
154  aluThickness += mcell->mFlexCableAluThickness;
155  else {
156  TGeoBBox *alu = new TGeoBBox(aluStripName,
158  mAssemblyLength/2,
159  mcell->mFlexCableAluThickness/2);
160  TGeoVolume *valu = new TGeoVolume(aluStripName, alu, GetMedium(_ALUMINUM_));
161 
162  vcell->AddNode(valu, 0, new TGeoCombiTrans(0.0, 0.0, (zOffset + mcell->mFlexCableAluThickness/2), 0));
163  } //if
164 
165  zOffset += mcell->mFlexCableAluThickness;
166  }
167 
168  // Mimosa chips; keep this structure in all theree geometry versions;
169  {
170  TGeoBBox *mimosa = new TGeoBBox(mMimosaShellName,
171  mcell->mChipWidth/2,
172  mcell->mChipLength/2,
173  mcell->mChipThickness/2);
174  TGeoVolume *vmimosa = new TGeoVolume(mMimosaShellName, mimosa, GetMedium(_SILICON_));
175 
176  mMimosaOffset = zOffset;
177  vcell->AddNode(vmimosa, 0, new TGeoCombiTrans(0.0, 0.0, (zOffset + mcell->mChipThickness/2), 0));
178 
179  zOffset += mcell->mChipThickness;
180 
181  // Mimosa chips sensitive layer;
182  {
183  TGeoBBox *micore = new TGeoBBox(mMimosaCoreName,
184  (mcell->mChipWidth - mcell->mChipDeadAreaWidth)/2,
185  mcell->mChipLength/2,
186  mcell->mChipActiveZoneThickness/2);
187  TGeoVolume *vmicore = new TGeoVolume(mMimosaCoreName, micore, GetMedium(_SILICON_));
188 
189  // NB: shift active area to the side in local X direction; NB: don't change '-' here,
190  // otherwise will need to modify rotations in FST/BST in order to bring chips more close
191  // to the beam line;
192  vmimosa->AddNode(vmicore, 0, new TGeoCombiTrans((-mcell->mChipDeadAreaWidth/2), 0.0, 0.0, 0));
193  }
194  }
195 
196  // Cold plate;
197  {
199  carbonThickness += mcell->mColdPlateThickness;
200  else {
201  TGeoBBox *cold = new TGeoBBox(coldPlateName,
203  mAssemblyLength/2,
204  mcell->mColdPlateThickness/2);
205  TGeoVolume *vcold = new TGeoVolume(coldPlateName, cold, GetMedium(mCarbonFiberMaterial));
206 
207  vcell->AddNode(vcold, 0, new TGeoCombiTrans(0.0, 0.0, (zOffset + mcell->mColdPlateThickness/2), 0));
208  } //if
209 
210  zOffset += mcell->mColdPlateThickness;
211  }
212 
213  // Water pipes;
214  {
215  double waterPipeOuterDiameter = mcell->mWaterPipeInnerDiameter + 2*mcell->mWaterPipeWallThickness;
216 
218  {
219  // FIXME: make a function call;
220  double effectiveWaterThickness =
221  (TMath::Pi()*(mcell->mWaterPipeInnerDiameter * mcell->mWaterPipeInnerDiameter)/4.)/
223 
224  // NB: 2 pipes ...;
225  waterThickness += 2*effectiveWaterThickness;
226 
227  double effectiveKaptonThickness =
228  (TMath::Pi()*(waterPipeOuterDiameter * waterPipeOuterDiameter)/4.)/
230  // NB: 2 pipes ...;
231  kaptonThickness += 2*(effectiveKaptonThickness - effectiveWaterThickness);
232  }
233  else {
234  TGeoTube *wpipe = new TGeoTube(waterPipeName,
235  mcell->mWaterPipeInnerDiameter/2,
236  waterPipeOuterDiameter/2,
237  mAssemblyLength/2);
238  TGeoVolume *vwpipe = new TGeoVolume(waterPipeName, wpipe, GetMedium(mKaptonMaterial));
239 
240  // Water itself;
241  TGeoTube *water = new TGeoTube(waterName,
242  0.0,
243  mcell->mWaterPipeInnerDiameter/2,
244  mAssemblyLength/2);
245  TGeoVolume *vwater = new TGeoVolume(waterName, water, GetMedium(_WATER_));
246 
247  TGeoRotation *rw = new TGeoRotation();
248  rw->RotateX(90);
249 
250  // Yes, 15mm split in 5+5+5mm distances according to ALICE TRD;
251  mWaterPipeXoffset = mcell->mChipWidth/(2*3);
252  mWaterPipeZoffset = zOffset + waterPipeOuterDiameter/2;
253 
254  for(unsigned lr=0; lr<2; lr++) {
255  double xOffset = (lr ? -1.0 : 1.0)*mWaterPipeXoffset;
256 
257  vcell->AddNode(vwpipe, lr, new TGeoCombiTrans(xOffset, 0.0, mWaterPipeZoffset, rw));
258  vcell->AddNode(vwater, lr, new TGeoCombiTrans(xOffset, 0.0, mWaterPipeZoffset, rw));
259  } //for lr
260  } //if
261  }
262 
263  // Base and apex enforcement beams;
265  {
266  double slope = mcell->mAssemblySideSlope*TMath::Pi()/180.;
267 
268  carbonThickness +=
269  // Apex beam (as two halves);
270  (TMath::Pi()*(mcell->mApexEnforcementBeamDiameter * mcell->mApexEnforcementBeamDiameter)/4. +
271  // 2x base triangular beams;
272  2*(mcell->mBaseEnforcementBeamWidth*mcell->mBaseEnforcementBeamWidth*tan(slope)/2))/
274  }
275  else
276  {
277  double slope = mcell->mAssemblySideSlope*TMath::Pi()/180.;
278 
279  // Apex beam;
280  TGeoTube *abeam = new TGeoTube(apexEnforcementBeamName,
281  0.0,
283  mAssemblyLength/2);
284  TGeoVolume *vabeam = new TGeoVolume(apexEnforcementBeamName, abeam, GetMedium(mCarbonFiberMaterial));
285 
286  TGeoRotation *rw = new TGeoRotation();
287  rw->RotateX(90);
288 
289  {
290  double hOffset = zOffset +
291  (mcell->mAssemblyDeadMaterialWidth/2)*tan(slope) - (mcell->mApexEnforcementBeamDiameter/2)/cos(slope);
292  vcell->AddNode(vabeam, 0, new TGeoCombiTrans(0.0, 0.0, hOffset, rw));
293  }
294 
295  // Base beams; have to resort to Arb8 shape, sorry;
296  double width = mcell->mBaseEnforcementBeamWidth;
297  double length = mAssemblyLength;
298 
299  double vert[8][2] = {
300  {-width, -length/2},
301  {-width, length/2},
302  { 0, length/2},
303  { 0, -length/2},
304  { 0, -length/2},
305  { 0, length/2},
306  { 0, length/2},
307  { 0, -length/2}
308  };
309 
310  double baseBeamHeight = mcell->mBaseEnforcementBeamWidth*tan(slope);
311  TGeoArb8 *bbeam = new TGeoArb8(baseEnforcementBeamName, baseBeamHeight/2, (double*)vert);
312  TGeoVolume *vbbeam = new TGeoVolume(baseEnforcementBeamName, bbeam, GetMedium(mCarbonFiberMaterial));
313  {
314  double hOffset = zOffset + baseBeamHeight/2;
315 
316  for(unsigned lr=0; lr<2; lr++) {
317  double xOffset = (lr ? 1.0 : -1.0)*(mcell->mAssemblyDeadMaterialWidth/2 - mcell->mBaseEnforcementBeamWidth);
318 
319  TGeoRotation *rw = new TGeoRotation();
320  if (lr) rw->RotateZ(180);
321 
322  vcell->AddNode(vbbeam, lr, new TGeoCombiTrans(xOffset, 0.0, hOffset, rw));
323  } //for lr
324  }
325  } //if
326 
327  // Side walls; it looks like those are present in ALICE design;
328  {
329  double radangle = mcell->mAssemblySideSlope*TMath::Pi()/180.;
330 
331  double sideWallWidth = (mcell->mAssemblyDeadMaterialWidth/2)/cos(mcell->mAssemblySideSlope*TMath::Pi()/180.);
332 
333  // Do not be pedantic, finally; place rectangular beams; assume, that 1) available width
334  // in any of those 4 slots is "1/4 of the total cell length - beam width" and beam is
335  // aligned along the diagonal of this space;
336  double slotWidth = mAssemblyLength/4 - mcell->mEnforcementStripWidth;
337  double slotHeight = sideWallWidth;
338 
339  double radSlope = atan(slotWidth/slotHeight);
340  double degSlope = radSlope*180./TMath::Pi();
341 
342  double beamLength = sqrt(slotWidth*slotWidth + slotHeight*slotHeight) -
343  2*(mcell->mEnforcementStripWidth/2)/tan(radSlope);
344 
345  double fullThickness;
347  fullThickness = mcell->mSideWallThickness + mcell->mEnforcementStripThickness;
348  else
349  fullThickness = mcell->mSideWallThickness +
350  mcell->mEnforcementStripThickness*(4*beamLength*mcell->mEnforcementStripWidth)/(mAssemblyLength*sideWallWidth);
351 
353  // NB: 2 sides ...;
354  carbonThickness += fullThickness*(2*sideWallWidth/mcell->mAssemblyDeadMaterialWidth);
355  else {
356  // Side wall volume; air container in case of full geometry; a single thin carbon layer
357  // in case of beam-line-uniform geometry;
358  TGeoBBox *side = new TGeoBBox(sideWallName,
359  sideWallWidth/2,
360  mAssemblyLength/2,
361  fullThickness/2);
362  TGeoVolume *vside;
364  vside = new TGeoVolume(sideWallName, side, GetMedium(mCarbonFiberMaterial));
365  else {
366  vside = new TGeoVolume(sideWallName, side, GetMedium(_AIR_));
367 
368  // Side wall solid thin layer (roof);
369  {
370  TGeoBBox *flat = new TGeoBBox(flatRoofName,
371  sideWallWidth/2,
372  mAssemblyLength/2,
373  mcell->mSideWallThickness/2);
374  TGeoVolume *vflat = new TGeoVolume(flatRoofName, flat, GetMedium(mCarbonFiberMaterial));
375 
376  vside->AddNode(vflat, 2, new TGeoCombiTrans(0.0, 0.0, mcell->mEnforcementStripThickness/2, 0));
377  }
378 
379  // 4x roof enforcement beams;
380  {
381 
382  TGeoBBox *beam = new TGeoBBox(roofSideBeamName,
383  beamLength/2,
384  mcell->mEnforcementStripWidth/2,
385  mcell->mEnforcementStripThickness/2);
386  TGeoVolume *vbeam = new TGeoVolume(roofSideBeamName, beam, GetMedium(mCarbonFiberMaterial));
387 
388  for(unsigned iq=0; iq<4; iq++) {
389  double qOffset = (mAssemblyLength/4)*(iq - 1.5);
390 
391  TGeoRotation *rw = new TGeoRotation();
392  rw->RotateZ((iq%2 ? -1. : 1.)*degSlope);
393 
394  //vside->AddNode(vbeam, iq, new TGeoCombiTrans(0.0, 0.1 * qOffset, -0.1 * mcell->mSideWallThickness/2, rw));
395  vside->AddNode(vbeam, iq, new TGeoCombiTrans(0.0, qOffset, -mcell->mSideWallThickness/2, rw));
396  } //for iq
397  }
398  } //if
399 
400  // Place both side walls into the assembly;
401  {
402  double hOffset = zOffset + (fullThickness/2)*cos(radangle) + (sideWallWidth/2)*sin(radangle);
403 
404  for(unsigned lr=0; lr<2; lr++) {
405  double xOffset = (lr ? -1.0 : 1.0)*(mcell->mAssemblyDeadMaterialWidth/2 +
406  (fullThickness/2)*sin(radangle) -
407  (sideWallWidth/2)*cos(radangle));
408 
409  TGeoRotation *rw = new TGeoRotation();
410  if (lr)
411  rw->SetAngles(90.0 + mcell->mAssemblySideSlope, 0.0 + 180.0, 90.0, 90.0 + 180.0, 0.0 - mcell->mAssemblySideSlope, 0.0);
412  else
413  rw->SetAngles(90.0 + mcell->mAssemblySideSlope, 0.0, 90.0, 90.0, 0.0 + mcell->mAssemblySideSlope, 0.0);
414 
415  vcell->AddNode(vside, lr, new TGeoCombiTrans(xOffset, 0.0, hOffset, rw));
416  } //for lr
417  }
418  } //if
419  }
420  }
421 
422  //cout << GetMedium(mCarbonFiberMaterial)->GetMaterial()->GetRadLen() << endl; exit(0);
423 
424  // Place a single equivalent thickness layer parallel to the assembly base;
426  {
427  // FIXME: may want to re-write this stuff in a better way once get rid of CINT (so that
428  // at least std::vector is available);
429  double aluRadLen, kaptonRadLen, carbonRadLen, waterRadLen;
430 
431  //printf("%f %f %f %f\n", aluThickness, kaptonThickness, carbonThickness, waterThickness);
432 
433  aluRadLen = aluThickness / GetMedium(_ALUMINUM_)->GetMaterial()->GetRadLen();
434  kaptonRadLen = kaptonThickness / GetMedium(mKaptonMaterial)->GetMaterial()->GetRadLen();
435  carbonRadLen = carbonThickness / GetMedium(mCarbonFiberMaterial)->GetMaterial()->GetRadLen();
436  waterRadLen = waterThickness / GetMedium(_WATER_)->GetMaterial()->GetRadLen();
437  //printf("%f %f %f %f\n", 100*aluRadLen, 100*kaptonRadLen, 100*carbonRadLen, 100*waterRadLen);
438 
439  // Effective carbon fiber layer thickness;
440  double equivalentCarbonThickness = /*10. **/ (aluRadLen + kaptonRadLen + carbonRadLen + waterRadLen)*
441  GetMedium(mCarbonFiberMaterial)->GetMaterial()->GetRadLen();
442  //printf("%f\n", equivalentCarbonThickness);
443 
444  // NB: full thickness may not fit into the triangular profile above the silicon chip layer ->
445  // split into two; first layer goes below silicon chip, second one (if needed) - above it;
446  {
447  double offsetFromBottomSide = mMimosaOffset + mAssemblyHeight/2;
448  // Let first layer mask itself as a flex cable;
449  double equivalentFlexThickness =
450  equivalentCarbonThickness < offsetFromBottomSide ? equivalentCarbonThickness : offsetFromBottomSide;
451 
452  TGeoBBox *flex = new TGeoBBox(flexName,
454  mAssemblyLength/2,
455  equivalentFlexThickness/2);
456  TGeoVolume *vflex = new TGeoVolume(flexName, flex, GetMedium(mCarbonFiberMaterial));
457 
458  vcell->AddNode(vflex, 0, new TGeoCombiTrans(0.0, 0.0, (equivalentFlexThickness - mAssemblyHeight)/2, 0));
459 
460  double equivalentColdThickness = equivalentCarbonThickness - equivalentFlexThickness;
461 
462  if (equivalentColdThickness > 0.0) {
463  // Let it be called cold plate;
464  TGeoBBox *cold = new TGeoBBox(coldPlateName,
466  mAssemblyLength/2,
467  equivalentColdThickness/2);
468  TGeoVolume *vcold = new TGeoVolume(coldPlateName, cold, GetMedium(mCarbonFiberMaterial));
469 
470  // Yes, zOffset is still a valid current variable here; there will be a gap because of
471  // missing pipes; ignore;
472  vcell->AddNode(vcold, 0, new TGeoCombiTrans(0.0, 0.0, (zOffset + equivalentColdThickness/2), 0));
473  } //if
474  }
475  } //if
476 
477  return vcell;
478 } // MapsGeoParData::ConstructMimosaCell()
479 
480 // ---------------------------------------------------------------------------------------
481 
482 MapsStave *MapsGeoParData::ConstructStave(unsigned chipNum, unsigned id,
483  MapsMimosaAssembly *mcell)
484 {
485  const char *detName = mDetName->Name().Data();
486 
487  TGeoVolume *vcell = ConstructMimosaCell(mcell, id);
488 
489  char staveName[128], waterPipeName[128], waterName[128];
490  char bracketName[128], waterTorusPipeName[128], waterTorusName[128];
491 
492  snprintf(staveName, 128-1, "%sStave%02d", detName, id);
493  snprintf(bracketName, 128-1, "%sStaveBracket%02d", detName, id);
494  snprintf(waterTorusPipeName, 128-1, "%sStaveWaterPipeTorus%02d", detName, id);
495  snprintf(waterTorusName, 128-1, "%sStaveWaterTorus%02d", detName, id);
496  snprintf(waterPipeName, 128-1, "%sStaveWaterPipe%02d", detName, id);
497  snprintf(waterName, 128-1, "%sStaveWater%02d", detName, id);
498 
499  MapsStave *stave = new MapsStave(staveName);
500  //stave->SetName(staveName);
501 
502  //
503  // Compose stave volume; yes, for VST they are simple TRD1 volumes; for now just
504  // take it of exactly N time chip assembly size + a bracket and pipes;
505  //
506 
507  // NB: for now do not mind to do stave setup front/back symmetric
508  // in terms of elementary cell location;
509  stave->mLength = GetExpectedStaveLength(chipNum, mcell);
510 
512  TGeoTrd1 *qstave = new TGeoTrd1(staveName,
513  mcell->mAssemblyBaseWidth/2,
514  0.0,
515  stave->mLength/2,
516  mAssemblyHeight/2);
517  stave->mVolume = new TGeoVolume(staveName, qstave, GetMedium(_AIR_));
518  }
519  else {
520  char tmp1Name[128], tmp2Name[128];
521 
522  snprintf(tmp1Name, 128-1, "%sTmp1Volume%02d", detName, id);
523  snprintf(tmp2Name, 128-1, "%sTmp2Volume%02d", detName, id);
524 
525  // FIXME: may need this code back for FST;
526  assert(0);
527  // Same stuff as in MapsGeoParData::ConstructMimosaCell();
528 #if _DISABLED_ANYWAY_
529  TGeoTrd1 *tmp1 = new TGeoTrd1(tmp1Name,
530  0.1 * mcell->mAssemblyBaseWidth/2,
531  0.0,
532  0.1 * stave->mLength/2,
533  0.1 * mAssemblyHeight/2);
534  TGeoBBox *tmp2 = new TGeoBBox(tmp2Name,
535  0.1 * mcell->mAssemblyBaseWidth/2,
536  //0.1 * mcell->mAssemblyDeadMaterialWidth/2,
537  0.1 * stave->mLength/2,
538  0.1 * mAssemblyHeight/2);
539  TGeoCompositeShape *cs = new TGeoCompositeShape(staveName, TString(tmp1Name) + "*" + TString(tmp2Name));
540 
541  stave->mVolume = new TGeoVolume(staveName, cs, GetMedium(_AIR_));
542 #endif
543  } //if
544 
545  // Place chip assemblies into the stave volume;
546  for(unsigned nn=0; nn<chipNum; nn++) {
547  double yOffset = (nn - 0.5*(chipNum-1))*mAssemblyLength;
548 
549  stave->mVolume->AddNode(vcell, nn, new TGeoCombiTrans(0.0, yOffset, 0.0, 0));
550  } //for nn
551 
552  // Place two brackets at the end of assembly; let them be always present, for all geometry types;
554  TGeoTrd1 *bracket = new TGeoTrd1(bracketName,
556  0.0,
558  mAssemblyHeight/2);
559  TGeoVolume *vbracket = new TGeoVolume(bracketName, bracket, GetMedium(mCarbonFiberMaterial));
560 
561  for(unsigned ud=0; ud<2; ud++) {
562  double yOffset = (ud ? -1.0 : 1.0)*(chipNum * mAssemblyLength + mEnforcementBracketThickness)/2;
563 
564  stave->mVolume->AddNode(vbracket, ud, new TGeoCombiTrans(0.0, yOffset, 0.0, 0));
565  } //for ud
566  } //if
567 
568  if (mWithExternalPipes &&
570  double waterPipeOuterDiameter = mcell->mWaterPipeInnerDiameter + 2*mcell->mWaterPipeWallThickness;
571 
572  // Place straight water pipe pieces at the upstream end; FIXME: unify with maps-lib.C later;
573  {
574  TGeoTube *wpipe = new TGeoTube(waterPipeName,
575  mcell->mWaterPipeInnerDiameter/2,
576  waterPipeOuterDiameter/2,
578  TGeoVolume *vwpipe = new TGeoVolume(waterPipeName, wpipe, GetMedium(mKaptonMaterial));
579 
580  // Water itself;
581  TGeoTube *water = new TGeoTube(waterName,
582  0.0,
583  mcell->mWaterPipeInnerDiameter/2,
585  TGeoVolume *vwater = new TGeoVolume(waterName, water, GetMedium(_WATER_));
586 
587  TGeoRotation *rw = new TGeoRotation();
588  rw->RotateX(90);
589 
590  for(unsigned lr=0; lr<2; lr++) {
591  double xOffset = (lr ? -1.0 : 1.0)*mWaterPipeXoffset;
592  double yOffset = (stave->mLength - mWaterPipeExtensionLength)/2;
593 
594  stave->mVolume->AddNode(vwpipe, lr, new TGeoCombiTrans(xOffset, yOffset, mWaterPipeZoffset, rw));
595  stave->mVolume->AddNode(vwater, lr, new TGeoCombiTrans(xOffset, yOffset, mWaterPipeZoffset, rw));
596  } //for lr
597  }
598 
599  // Place round U-pieces at the downstream end;
600  {
601  TGeoTorus *wtpipe = new TGeoTorus(waterTorusPipeName,
603  mcell->mWaterPipeInnerDiameter/2,
604  waterPipeOuterDiameter/2,
605  180.0, 180.);
606  TGeoVolume *vwtpipe = new TGeoVolume(waterTorusPipeName, wtpipe, GetMedium(mKaptonMaterial));
607 
608 
609  // Water itself;
610  TGeoTorus *twater = new TGeoTorus(waterTorusName,
612  0.0,
613  mcell->mWaterPipeInnerDiameter/2,
614  180.0, 180.);
615  TGeoVolume *vtwater = new TGeoVolume(waterTorusName, twater, GetMedium(_WATER_));
616 
617  double qyOffset = chipNum * mAssemblyLength/2 +
619  stave->mVolume->AddNode(vwtpipe, 0, new TGeoCombiTrans(0.0, -qyOffset, mWaterPipeZoffset, 0));
620  stave->mVolume->AddNode(vtwater, 0, new TGeoCombiTrans(0.0, -qyOffset, mWaterPipeZoffset, 0));
621  }
622  } //if
623 
624  return stave;
625 } // MapsGeoParData::ConstructStave()
626 
627 // ---------------------------------------------------------------------------------------
628 
629 MapsStave *MapsGeoParData::ConstructStaveWithMapping(unsigned chipNum, unsigned id,
630  MapsMimosaAssembly *mcell)
631 {
632  MapsStave *stave = ConstructStave(chipNum, id, mcell);
633 
634  // Well, disks can be rotated, so does not make sense to assume, that chips are
635  // numbered in vertical (Y) direction -> just use the first available index (X);
636  AddLogicalVolumeGroup(chipNum);
637 
638  // NB: this implementation is really dumb and does not give anything like XY-location
639  // of chips in a disk; so just help the simulation code to identify chips and
640  // reconstruction code to get access to 3D transformation matrices;
641  EicGeoMap *fgmap = CreateNewMap();
644  fgmap->AddGeantVolumeLevel(mCellAssemblyName, chipNum);
645  // Right, all the staves are unique for now;
646  fgmap->AddGeantVolumeLevel(stave->GetName(), 0);
647 
649 
650  for(unsigned nn=0; nn<chipNum; nn++) {
651  UInt_t geant[4] = {0, 0, nn, 0}, logical[1] = {nn};
652 
653  if (SetMappingTableEntry(fgmap, geant, id, logical)) {
654  cout << "Failed to set mapping table entry!" << endl;
655  exit(0);
656  } //if
657  } //for nn
658 
659  return stave;
660 } // MapsGeoParData::ConstructStaveWithMapping()
661 
662 // ---------------------------------------------------------------------------------------
663