EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MuMegasGeoParData.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MuMegasGeoParData.cxx
1 //
2 // AYK (ayk@bnl.gov), 2015/01/28
3 //
4 // MuMegas geometry description file;
5 //
6 
7 #include <iostream>
8 using namespace std;
9 
10 #include <TGeoTube.h>
11 #include <TGeoVolume.h>
12 
13 #include <MuMegasGeoParData.h>
14 
15 // ---------------------------------------------------------------------------------------
16 
17 int MuMegasGeoParData::ConstructGeometry(bool root, bool gdml, bool check)
18 {
19  const char *detName = mDetName->Name().Data();
20 
21  // Loop through all wheels (or perhaps single modules) independently;
22  for(unsigned bl=0; bl<mBarrels.size(); bl++) {
23  MuMegasBarrel *barrel = mBarrels[bl];
24  MuMegasLayer *layer = barrel->mLayer;
25 
26  // Figure out thickness of the sector gas container volume;
27  double gasSectorThickness = layer->mReadoutPcbThickness + layer->mCopperStripThickness +
29  layer->mExitWindowThickness;
30 
31  // Figure out thickness of the overall air container volume;
32  double airContainerThickness = gasSectorThickness < layer->mInnerFrameThickness ?
33  layer->mInnerFrameThickness : gasSectorThickness;
34  if (airContainerThickness < layer->mOuterFrameThickness)
35  airContainerThickness = layer->mOuterFrameThickness;
36 
37  // Define air container volume and place it into the top volume;
38  char barrelContainerVolumeName[128];
39  snprintf(barrelContainerVolumeName, 128-1, "%sBarrelContainerVolume%02d", detName, bl);
40 
41  TGeoTube *bcontainer = new TGeoTube(barrelContainerVolumeName,
42  0.1 * barrel->mRadius,
43  0.1 * (barrel->mRadius + airContainerThickness),
44  0.1 * barrel->mLength/2);
45  TGeoVolume *vbcontainer = new TGeoVolume(barrelContainerVolumeName, bcontainer, GetMedium(_AIR_));
46 
47  GetTopVolume()->AddNode(vbcontainer, 0, barrel->mTransformation);
48 
49  // Define and place a pair of outer frame rings;
50  char outerFrameVolumeName[128];
51  snprintf(outerFrameVolumeName, 128-1, "%sOuterFrameVolume%02d", detName, bl);
52 
53  TGeoTube *oframe = new TGeoTube(outerFrameVolumeName,
54  0.1 * barrel->mRadius,
55  0.1 * (barrel->mRadius + layer->mOuterFrameThickness),
56  0.1 * layer->mOuterFrameWidth/2);
57  TGeoVolume *voframe = new TGeoVolume(outerFrameVolumeName, oframe, GetMedium("MuMegasCarbonFiber"));
58  double zOffset = (barrel->mLength - layer->mOuterFrameWidth)/2;
59  for(unsigned fb=0; fb<2; fb++)
60  vbcontainer->AddNode(voframe, fb, new TGeoCombiTrans(0.0, 0.0, 0.1 * (fb ? -1.0 : 1.0)*zOffset, 0));
61 
62  // Figure out sector length;
63  double singleSectorLength =
64  (barrel->mLength - 2.0 * layer->mOuterFrameWidth -
65  (barrel->mBeamLineSectionNum-1)*layer->mInnerFrameWidth)/barrel->mBeamLineSectionNum;
66  double singleSectorZspacing = singleSectorLength + layer->mInnerFrameWidth;
67 
68  // Then inner frame rings (in case more than 1 section);
69  {
70  char innerFrameVolumeName[128];
71  snprintf(innerFrameVolumeName, 128-1, "%sInnerFrameVolume%02d", detName, bl);
72 
73  TGeoTube *iframe = new TGeoTube(innerFrameVolumeName,
74  0.1 * barrel->mRadius,
75  0.1 * (barrel->mRadius + layer->mInnerFrameThickness),
76  0.1 * layer->mInnerFrameWidth/2);
77  TGeoVolume *viframe = new TGeoVolume(innerFrameVolumeName, iframe, GetMedium("MuMegasCarbonFiber"));
78 
79  for(unsigned iz=0; iz<barrel->mBeamLineSectionNum-1; iz++) {
80  double zOffset = singleSectorZspacing*(iz - (barrel->mBeamLineSectionNum-2)/2.);
81 
82  vbcontainer->AddNode(viframe, iz, new TGeoCombiTrans(0.0, 0.0, 0.1*zOffset, 0));
83  } //for iz
84  }
85 
86  // Figure out asimuthal "clear acceptance" angular range occupied by each sector;
87  double circumference = 2.0 * TMath::Pi() * barrel->mRadius;
88  double clearAcceptanceFraction =
89  (circumference - barrel->mAsimuthalSectorNum*layer->mInnerFrameWidth)/circumference;
90  double singleSectorAngle = 360.0 * clearAcceptanceFraction / barrel->mAsimuthalSectorNum;
91 
92  // Define single sector gas container volume;
93  char sectorContainerVolumeName[128];
94  snprintf(sectorContainerVolumeName, 128-1, "%sSectorContainerVolume%02d", detName, bl);
95  {
96  // Funny enough, it looks like TGeoTubs has a bug in the navigation methods; but
97  // TGeoCtub, which is more generic, works; see also MuMegasGeoParData::PlaceMaterialLayer();
98  TGeoCtub *sector = new TGeoCtub(sectorContainerVolumeName,
99  0.1 * barrel->mRadius,
100  0.1 * (barrel->mRadius + gasSectorThickness),
101  0.1 * singleSectorLength/2,
102  0.0, singleSectorAngle,
103  0, 0, -1, 0, 0, 1);
104  TGeoVolume *vsector = new TGeoVolume(sectorContainerVolumeName, sector, GetMedium(layer->mGasMixture));
105 
106  // Place them all into the air container volume;
107  for(unsigned ir=0; ir<barrel->mAsimuthalSectorNum; ir++) {
108  TGeoRotation *rw = 0;
109  if (ir) {
110  rw = new TGeoRotation();
111  rw->RotateZ(ir*360./barrel->mAsimuthalSectorNum);
112  } //if
113 
114  for(unsigned iz=0; iz<barrel->mBeamLineSectionNum; iz++) {
115  double zOffset = singleSectorZspacing*(iz - (barrel->mBeamLineSectionNum-1)/2.);
116 
117  vbcontainer->AddNode(vsector, ir*barrel->mBeamLineSectionNum+iz,
118  new TGeoCombiTrans(0.0, 0.0, 0.1 * zOffset, rw));
119  } //for iz
120  } //for ir
121 
122  // Populate gas sector with essential material layers;
123  {
124  double rOffset = barrel->mRadius;
125 
126  PlaceMaterialLayer(detName, "ReadoutPcb", bl, vsector,
127  layer->mReadoutPcbMaterial.Data(),
128  singleSectorLength, singleSectorAngle,
129  layer->mReadoutPcbThickness,
130  &rOffset);
131 
132  PlaceMaterialLayer(detName, "ReadoutStrips", bl, vsector,
133  "copper",
134  singleSectorLength, singleSectorAngle,
135  layer->mCopperStripThickness,
136  &rOffset);
137 
138  PlaceMaterialLayer(detName, "AmplificationRegion", bl, vsector,
139  layer->mGasMixture.Data(),
140  singleSectorLength, singleSectorAngle,
142  &rOffset);
143 
144  PlaceMaterialLayer(detName, "SteelMesh", bl, vsector,
145  "iron",
146  singleSectorLength, singleSectorAngle,
147  layer->mSteelMeshThickness,
148  &rOffset);
149 
150  PlaceMaterialLayer(detName, "ConversionRegion", bl, vsector,
151  layer->mGasMixture.Data(),
152  singleSectorLength, singleSectorAngle - 1.0,
154  &rOffset);
155 
156  PlaceMaterialLayer(detName, "ExitWindow", bl, vsector,
157  layer->mExitWindowMaterial.Data(),
158  singleSectorLength, singleSectorAngle,
159  layer->mExitWindowThickness,
160  &rOffset);
161  }
162  }
163 
164  // Define and place beam-aligned pieces of support frames;
165  {
166  char sectorFrameVolumeName[128];
167  snprintf(sectorFrameVolumeName, 128-1, "%sSectorFrameVolume%02d", detName, bl);
168  double singleSectorFrameAngle = 360./barrel->mAsimuthalSectorNum - singleSectorAngle;
169  TGeoCtub *sframe = new TGeoCtub(sectorFrameVolumeName,
170  0.1 * barrel->mRadius,
171  0.1 * (barrel->mRadius + layer->mInnerFrameThickness),
172  0.1 * singleSectorLength/2,
173  0.0,
174  singleSectorFrameAngle,
175  0, 0, -1, 0, 0, 1);
176  TGeoVolume *vsframe = new TGeoVolume(sectorFrameVolumeName, sframe, GetMedium("MuMegasCarbonFiber"));
177 
178  for(unsigned ir=0; ir<barrel->mAsimuthalSectorNum; ir++) {
179  TGeoRotation *rw = new TGeoRotation();
180  rw->RotateZ(ir*360./barrel->mAsimuthalSectorNum + singleSectorAngle);
181 
182  for(unsigned iz=0; iz<barrel->mBeamLineSectionNum; iz++) {
183  double zOffset = singleSectorZspacing*(iz - (barrel->mBeamLineSectionNum-1)/2.);
184 
185  vbcontainer->AddNode(vsframe, ir*barrel->mBeamLineSectionNum+iz,
186  new TGeoCombiTrans(0.0, 0.0, 0.1 * zOffset, rw));
187  } //for iz
188  } //for ir
189  }
190 
191  // Yes, one map per layer; FIXME: conversion volume name should be calculated once;
192  // also may want to unify with the other [ir..iz] loop;
193  {
195 
196  EicGeoMap *fgmap = CreateNewMap();
197 
198  char conversionVolumeName[128];
199  snprintf(conversionVolumeName, 128-1, "%s%s%02d", detName, "ConversionRegion", bl);
200 
201  fgmap->AddGeantVolumeLevel(conversionVolumeName, 0);
202  fgmap->AddGeantVolumeLevel(sectorContainerVolumeName, barrel->mAsimuthalSectorNum * barrel->mBeamLineSectionNum);
203 
204  fgmap->SetSingleSensorContainerVolume(conversionVolumeName);
205 
206  for(unsigned ir=0; ir<barrel->mAsimuthalSectorNum; ir++)
207  for(unsigned iz=0; iz<barrel->mBeamLineSectionNum; iz++) {
208  UInt_t geant[2] = {0, ir*barrel->mBeamLineSectionNum+iz}, logical[3] = {ir, 0, iz};
209 
210  if (SetMappingTableEntry(fgmap, geant, bl, logical)) {
211  cout << "Failed to set mapping table entry!" << endl;
212  exit(0);
213  } //if
214  } //for ir..iz
215  }
216  } //for bl
217 
218  // Place this stuff as a whole into the top volume and write out;
219  FinalizeOutput(root, gdml, check);
220 
221  return 0;
222 } // MuMegasGeoParData::ConstructGeometry()
223 
224 // ---------------------------------------------------------------------------------------
225 
226 void MuMegasGeoParData::PlaceMaterialLayer(const char *detName, const char *volumeNamePrefix,
227  unsigned barrelID,
228  TGeoVolume *sectorContainer, const char *material,
229  double length, double angle,
230  double thickness, double *rOffset)
231 {
232  char volumeName[128];
233 
234  snprintf(volumeName, 128-1, "%s%s%02d", detName, volumeNamePrefix, barrelID);
235  TGeoCtub *shape = new TGeoCtub(volumeName,
236  0.1 * (*rOffset),
237  0.1 * (*rOffset + thickness),
238  0.1 * length/2,
239  0.0,
240  angle,
241  0, 0, -1, 0, 0, 1);
242  TGeoVolume *vshape = new TGeoVolume(volumeName, shape, GetMedium(material));
243 
244  sectorContainer->AddNode(vshape, 0, new TGeoCombiTrans(0.0, 0.0, 0.0, 0));
245 
246  *rOffset += thickness;
247 } // MuMegasGeoParData::PlaceMaterialLayer()
248 
249 // ---------------------------------------------------------------------------------------
250