EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cemc.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file cemc.C
1 
2 // Meaningless numbers for now; fine;
3 #define _VERSION_ 1
4 #define _SUBVERSION_ 0
5 
6 //
7 // FIXME: rather arbitrary tower construction; will have to fix later;
8 //
9 
10 
11 #define _NO_STRUCTURE_GEOMETRY_
12 
13 //
14 // -> for now it is "ideal" for narrow side fiber-to-fiber spacing, but
15 // no "safety" correction; prefer not to mess up with ../FEMC/femc-lib.C;
16 // once geometry gets well defined, unify similar parts;
17 //
18 
19 {
20  // Load basic libraries;
21  gROOT->Macro("$VMCWORKDIR/gconfig/rootlogon.C");
22 
23  //
24  // Prefer to think in [mm] and convert to [cm] when calling ROOT shape
25  // definition routines only;
26  //
27 
28  // Allocate as many logical mapping tables as needed;
30 
31  // "No structure" & "simple structure" configurations (compared to FEMC,
32  // so so brass meshes, etc);
33 #ifdef _NO_STRUCTURE_GEOMETRY_
35 #else
37 #endif
38 
39  //
40  // Declare basic parameters;
41  //
42 
44 
45  cemc->mCellFaceSizeX = 1.049 * 25.4;
46  // Well, at present force XY-sizes to be equal;
47  double cellFaceSize = cemc->mCellFaceSizeY = cemc->mCellFaceSizeX;
48  cemc->mCellLength = 200.0;//166.0;
49  // Well, assume no-gap packing;
50  cemc->mInterCellGap = 0.0;
51 
52  // No shift along the beam line for now;
53  double beamLineOffset = 1.049 * 25.4 * 2;//0.0;
54 
55  // Default is kFALSE (no fibers, so tower material is a sensitive volume);
56 #ifndef _NO_STRUCTURE_GEOMETRY_
57  FiberParData *fptr = cemc->mFiber = new FiberParData();
58 
59  // Triangular honeycomb grid;
60  fptr->mFiberNumPerRow = 26;
61  fptr->mFiberRowNum = 30;
62  // Fiber parameters; 470um core diameter;
63  fptr->mFiberCoreDiameter = 0.47;
64  fptr->mFiberCladdingThickness = 0.03/2;
65  double outerDiameter = fptr->mFiberCoreDiameter + 2*fptr->mFiberCladdingThickness;
66 
67  // Define fiber X-spacing;
68 #ifdef _FIBER_X_SPACING_
70 #endif
71  // Yes, this is the "ideal" number; use it only if not assigned yet;
72  if (!fptr->mFiberSpacingX)
73  fptr->mFiberSpacingX = cemc->mCellFaceSizeX / fptr->mFiberNumPerRow;
74 
75  // NB: want a ~honeycomb structure -> even and odd rows fill be offset
76  // by fptr->mFiberSpacingX/2;
77  double fiberX0offset = -cemc->mCellFaceSizeX/2 +
78  (cemc->mCellFaceSizeX - (fptr->mFiberSpacingX/2)*(2*fptr->mFiberNumPerRow - 1))/2;
79 
80  // Define fiber Y-spacing; also tricky;
81 #ifdef _FIBER_Y_SPACING_
83 #endif
84  // Unless predefined, calculate as ideal honeycomb;
85  if (!fptr->mFiberSpacingY)
86  fptr->mFiberSpacingY = fptr->mFiberSpacingX*sqrt(3.)/2;
87  //cout << fptr->mFiberSpacingY / 25.4 << " " << fptr->mFiberSpacingY << endl;
88  double fiberY0offset = -cemc->mCellFaceSizeY/2 +
89  (cemc->mCellFaceSizeY - fptr->mFiberSpacingY*(fptr->mFiberRowNum - 1))/2;
90 
91  // Fibers will be a bit rotated inside tower volumes in order to follow
92  // tower wedge shape; want to avoid idiotic problems with few um overlapping
93  // volumes; so make fibers shorter; in fact ideally would need to have CTUB
94  // volumes of a bit different length (inclination-dependent); think later;
95  double fiberLength = sqrt(cemc->mCellLength*cemc->mCellLength - outerDiameter*outerDiameter/4);
96 #endif
97 
98  // Tune this number in such a way that the whole calorimeter fit in the radial
99  // distance range [1120..1320]mm or so; assume one tower per sector for now (no grouping);
100  // may want to change later;
101  double sectorNum = 268;//192;
102  // Tune this number to cover a certain length along the beam line;
103  double sliceNum = 120-4;// 92;
104  // Prefer to work with sectorNum and sliceNum variables; so just define the
105  // XZ-dimensions and forget about them;
106  //cemc->SetDimX(sectorNum); cemc->SetDimZ(sliceNum);
107  //cemc->SetLogicalDimensions(0, sectorNum, 0, sliceNum);//2*rowsNumMax, 2*rowsNumMax);
108  cemc->AddLogicalVolumeGroup(sectorNum, 0, sliceNum);
109 
110  // Calculate the inner radius of sector container volume;
111  const Double_t sectorAlpha = 360. / sectorNum;
112  const Double_t sectorMinR = ((cellFaceSize + cemc->mInterCellGap)/2) *
113  tan((90 - sectorAlpha / 2) * TMath::Pi() / 180.);
114  cout << sectorMinR << endl;
115  // Outer radius of sector container volume;
116  const Double_t sectorMaxR = (sectorMinR + cemc->mCellLength) /
117  cos((sectorAlpha / 2) * TMath::Pi() / 180.);
118  cout << sectorMaxR << endl;
119 
120  // Sector length along the beam line;
121  const Double_t sliceStep = cellFaceSize + cemc->mInterCellGap;
122  const Double_t sectorLength = sliceNum * sliceStep;
123 
124  // Tower rear side length in azimuthal direction; assume side slope is
125  // just alfa/2, for simplicity; NB: dimension in Z-direction is of course
126  // equal to cemc->mCellFaceSize (non-projective geometry, no tricks for now);
127  const Double_t towerRearSideSize = cellFaceSize + 2.*cemc->mCellLength*
128  tan((sectorAlpha / 2) * TMath::Pi() / 180.);
129  cout << towerRearSideSize << endl;
130 #ifndef _NO_STRUCTURE_GEOMETRY_
131  // Otherwise this variable is of no use; fiber XY-coordinates will be
132  // calculated on a short (26x26mm^2) front side; one of these coordinates
133  // need to be stretched a bit in order to account for wedge tower shape;
134  double scalingFactor = (towerRearSideSize + cellFaceSize)/(2*cellFaceSize);
135  cout << scalingFactor << endl;
136 #endif
137 
138  // Air container volume; will hold one slice in "phi" with the full Z-length;
139  TGeoTubeSeg *tubs = new TGeoTubeSeg("CemcSector",
140  0.1 * sectorMinR,
141  0.1 * sectorMaxR,
142  0.1 * sectorLength/2.,
143  -sectorAlpha/2., sectorAlpha/2.);
144  TGeoVolume *vtubs = new TGeoVolume("CemcSector", tubs, cemc->GetMedium("air"));
145 
146  // A single tower; prefer the easiest (TRD1) shape and GEANT3 rot.matrix declaration;
147  {
148  TGeoTrd1 *tower = new TGeoTrd1("CemcTower",
149  0.1 * cellFaceSize/2,
150  0.1 * towerRearSideSize/2,
151  0.1 * cellFaceSize/2,
152  0.1 * cemc->mCellLength/2);
153  TGeoVolume *vtower =
154  new TGeoVolume("CemcTower", tower, cemc->GetMedium(cemc->mFiber ? "WEpoxyMix" : "WEpoxySciMix"));
155  TGeoRotation *rr = new TGeoRotation();
156  rr->SetAngles(90., 90., 0., 0., 90., 0.);
157  for(int tw=0; tw<sliceNum; tw++)
158  vtubs->AddNode(vtower, tw,
159  new TGeoCombiTrans(0.1 * (sectorMinR + cemc->mCellLength/2), 0.,
160  0.1 * sliceStep * (tw - (sliceNum-1)/2.), rr));
161 
162 #ifndef _NO_STRUCTURE_GEOMETRY_
163  // Populate tower with fibers; assume they can all be taken with the same length
164  // for simplicity (which would mean some are few hundred um short); fix later if needed;
165  // eventually will have to take individual fiber slopes;
166  TGeoTube *fiber = new TGeoTube("CemcFiberCladding", 0.0, 0.1 * outerDiameter/2, 0.1 * fiberLength/2);
167  TGeoVolume *vfiber = new TGeoVolume("CemcFiberCladding", fiber, cemc->GetMedium("PMMA"));
168 
169  for(int ix=0; ix<fptr->mFiberNumPerRow; ix++)
170  //for(int ix=1; ix<cemc->mFiberNumPerRow-1; ix++)
171  for(int iy=0; iy<fptr->mFiberRowNum; iy++)
172  {
173  //printf("%02d, %02d -> %7.2f %7.2f\n", ix, iy,
174  // fiberX0offset + (ix+(iy%2)/2.)*cemc->mFiberSpacing, fiberY0offset + iy*fiberYpitch);
175 
176  // Calculate the rotation angle wrt the Y axis;
177  TGeoRotation *frr = new TGeoRotation();
178  double x0 = fiberX0offset + (ix+(iy%2)/2.)*fptr->mFiberSpacingX;
179  double angle = atan(x0*(scalingFactor-1.)/(fiberLength/2.)) * 180. / TMath::Pi();
180  //cout << angle << endl;
181  frr->SetAngles(90.+angle, 0., 90., 90., angle, 0.);
182 
183  vtower->AddNode(vfiber, ix*fptr->mFiberRowNum + iy,
184  new TGeoCombiTrans(0.1 * x0 * scalingFactor,
185  0.1 * (fiberY0offset + iy*fptr->mFiberSpacingY),
186  0.0, frr));
187  } //for ix..iy
188 
189  TGeoTube *fcore = new TGeoTube("CemcFiberCore", 0.0, 0.1 * fptr->mFiberCoreDiameter/2,
190  0.1 * fiberLength/2);
191  TGeoVolume *vfcore = new TGeoVolume("CemcFiberCore", fcore, cemc->GetMedium("polystyrene"));
192  vfiber->AddNode(vfcore, 0, new TGeoCombiTrans(0.0, 0.0, 0.0, new TGeoRotation()));
193 #endif
194  }
195 
196  // Configure tower map;
197  EicGeoMap *fgmap = cemc->CreateNewMap();
198 #ifndef _NO_STRUCTURE_GEOMETRY_
199  fgmap->AddGeantVolumeLevel("CemcFiberCore", 0);
200  fgmap->AddGeantVolumeLevel("CemcFiberCladding", 0);
201 #endif
202  fgmap->AddGeantVolumeLevel("CemcTower", sliceNum);
203  fgmap->AddGeantVolumeLevel("CemcSector", sectorNum);
204 
205  fgmap->SetSingleSensorContainerVolume("CemcTower");
206  cemc->AddBlackHoleVolume("CemcSector");
207 
208  for(UInt_t sc=0; sc<sectorNum; sc++)
209  for(UInt_t iz=0; iz<sliceNum; iz++)
210  {
211  // Yes, in this order (iz,sc);
212  UInt_t geant[4] = {0, 0, iz, sc}, group = 0, logical[3] = {sc, 0, iz};
213 
214  if (cemc->SetMappingTableEntry(fgmap, geant + (cemc->mFiber ? 0 : 2), group, logical))
215  {
216  cout << "Failed to set mapping table entry!" << endl;
217  exit(0);
218  } //if
219  } //for ix..iz
220 
221  // Put all sector copies;
222  for(UInt_t sc=0; sc<sectorNum; sc++)
223  {
224  TGeoRotation *qr = new TGeoRotation();
225  qr->SetAngles(sc * sectorAlpha, 0., 0.);
226 
227  cemc->GetTopVolume()->AddNode(vtubs, sc, new TGeoCombiTrans(0., 0., 0., qr));
228  } //for sc
229 
230  cemc->SetTopVolumeTransformation(new TGeoTranslation(0.0, 0.0, 0.1 * beamLineOffset));
231 
232  //cemc->GetColorTable()->AddPatternMatch("CemcTower", kBlue);
233  cemc->GetColorTable()->AddPatternMatch("CemcSector", kBlue);
234 
235  // And put this stuff as a whole into the top volume; account Z-shift;
236  cemc->FinalizeOutput();
237 
238  // Yes, always exit;
239  exit(0);
240 }