EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
femc.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file femc.C
1 
2 // Meaningless number for now; fine;
3 #define _VERSION_ 1
4 #define _SUBVERSION_ 0
5 
6 #define _NO_STRUCTURE_GEOMETRY_
7 
8 // Full geometry seems to be impractical for purposes other than small test
9 // setup like 4x4 matrix; may want to represent the tower just as a single
10 // WEpoxyMix layer of a proper thickness inbetween two thin epoxy endcaps;
11 //#define _IGNORE_BRASS_LAYERS_
12 
13 #include <./femc-lib.C>
14 
15 static double offsets[2] = {-1650., 2800.};//3400.+1130., 3400.};
16 
18 {
19  // Load basic libraries;
20  gROOT->Macro("$VMCWORKDIR/gconfig/rootlogon.C");
21 
22  //
23  // Prefer to think in [mm] and convert to [cm] when calling ROOT shape
24  // definition routines only;
25  //
26 
27  for(unsigned fb=0; fb<2; fb++) {
29  const TString& cname = emcal->GetDetName()->Name();
30 
31  FiberParData *fptr = emcal->mFiber;
32  TowerParData *tptr = emcal->mTower;
33 
34  // "No structure", "simple structure" & "full structure" configurations;
35 #ifdef _NO_STRUCTURE_GEOMETRY_
37 #else
38 #ifdef _IGNORE_BRASS_LAYERS_
40 #else
42 #endif
43 #endif
44 
45  //
46  // Declare basic parameters;
47  //
48 
49 
50  // Endcap is shifted along H+ direction as a whole;
51  double beamLineOffset = offsets[fb];//-1650.0;//2800.;//2700.0;
52 
53  // Pick up whatever parameters for now;
54  emcal->mEndcapMinR = 20.0;
55  emcal->mEndcapMaxTheta = 40.0;
56  // Do not allow subunits to protrude towards too small and too large radii;
57  emcal->mSafetyVolume = 10.0;
58 
59  // Well, assume no-gap packing?;
60  emcal->mInterQuadrantGap = 0.0;
61 
62  const Double_t endcapMaxR =
63  fabs(beamLineOffset) * tan(emcal->mEndcapMaxTheta * TMath::Pi() / 180.);
64 
65  const Double_t envelopeWidth = emcal->mCellFaceSizeX + emcal->mInterCellGap;
66 
67  // Estimate an absolutely max number of rows;
68  const Int_t rowsNumMax = (int)floor(endcapMaxR / envelopeWidth);
69  //cout << rowsNumMax << endl;
70  // Do not mind to use just this number in order to calculate XY-dimensions;
71  // if the actual matrix will be a bit smaller, this does not really matter;
72  // emcal->SetDimX(2*rowsNumMax); emcal->SetDimY(2*rowsNumMax);
73  //emcal->SetLogicalDimensions(0, 2*rowsNumMax, 2*rowsNumMax);
74  emcal->AddLogicalVolumeGroup(2*rowsNumMax, 2*rowsNumMax);
75  struct FemcRow {
76  Double_t yc;
77  } *rows = calloc(rowsNumMax, sizeof(FemcRow));
78 
79  for(int iq=0; iq<rowsNumMax; iq++)
80  {
81  FemcRow *row = rows + iq;
82 
83  row->yc = envelopeWidth * (iq + 0.5);
84  } //for iq
85 
86  // Construct a single tower; this part is the same for T1018 and
87  // EIC model detector geometry;
88  TGeoVolume *vtower = make_single_tower(emcal);
89 
90  // Assume the 4 quadrants are identical (like in PANDA); one quadrant is a
91  // 90 degree TUBS volume of known parameters;
92  {
93  // Yes, seems to be the easiest way to define them :-); NB: used in two places;
94  TGeoRotation *_qquad[4];
95  for(int ixy=0; ixy<4; ixy++)
96  _qquad[ixy] = new TGeoRotation();
97  // NB: want [X][Y]-ordering among quadrants and 2x2 subunit crystals and no
98  // coordinate swapping -> reflections in favor of 90-degree rotations;
99  _qquad[0]->RotateZ(180);
100  _qquad[1]->ReflectX(kTRUE);
101  _qquad[2]->ReflectY(kTRUE);
102 
103  TGeoTubeSeg *quadrant = new TGeoTubeSeg(cname + "Quadrant",
104  0.1 * emcal->mEndcapMinR,
105  0.1 * endcapMaxR,
106  0.1 * tptr->mTowerShellLength/2 ,
107  0.0, 90.0);
108  TGeoVolume *vquadrant = new TGeoVolume(cname + "Quadrant", quadrant, emcal->GetMedium("air"));
109 
110 #ifdef _NO_STRUCTURE_GEOMETRY_
111  EicGeoMap *fgmap = emcal->CreateNewMap();
112  fgmap->AddGeantVolumeLevel(cname + "Tower", 0);
113  fgmap->AddGeantVolumeLevel(cname + "TowerShell", rowsNumMax*rowsNumMax);
114  fgmap->AddGeantVolumeLevel(cname + "Quadrant", 4);
115 
116  fgmap->SetSingleSensorContainerVolume(cname + "Tower");
117 #else
118  for(unsigned iqq=0; iqq<fptr->GetLayerNum(); iqq++) {
119  FiberTowerLayer *layer = fptr->GetLayer(iqq);
120  EicGeoMap *fgmap = emcal->CreateNewMap();
121 
122  fgmap->AddGeantVolumeLevel(layer->mFiberCoreName, 0);
123  fgmap->AddGeantVolumeLevel(layer->mFiberCladdingName, 0);
124  fgmap->AddGeantVolumeLevel(layer->mLayerName, 0);
125  fgmap->AddGeantVolumeLevel(cname + "Tower", 0);
126  fgmap->AddGeantVolumeLevel(cname + "TowerShell", rowsNumMax*rowsNumMax);
127  fgmap->AddGeantVolumeLevel(cname + "Quadrant", 4);
128 
129  fgmap->SetSingleSensorContainerVolume(cname + "Tower");
130  } //for iqq
131 #endif
132 
133  emcal->AddBlackHoleVolume(cname + "TowerShell");
134 
135  // Populate quadrant volume with towers;
136  unsigned tcounter = 0;
137  for(int ix=0; ix<rowsNumMax; ix++) {
138  FemcRow *brx = rows + ix;
139  // Yes, coordinates are remapped here; Z-coordinate will be just a focal distance;
140  double xx = brx->yc;
141 
142  for(int iy=0; iy<rowsNumMax; iy++) {
143  FemcRow *bry = rows + iy;
144  double yy = bry->yc;
145 
146  // Calculate radial distance from (0,0); at the inner edge assume that can
147  // take center coordinates and give subunit diagonal dimension with some safety
148  // margin as a reference;
149  double rr = sqrt(xx*xx + yy*yy);
150  if (rr - emcal->mCellFaceSizeX/sqrt(2.) - emcal->mSafetyVolume < emcal->mEndcapMinR) continue;
151  if (rr + emcal->mCellFaceSizeX/sqrt(2.) + emcal->mSafetyVolume > endcapMaxR) continue;
152 
153  // Loop through 2x2 quadrants and add the 4 tower entries into the mapping table;
154  for(int iqx=0; iqx<2; iqx++)
155  for(int iqy=0; iqy<2; iqy++) {
156  int XX = iqx ? rowsNumMax + ix : rowsNumMax - ix - 1;
157  int YY = iqy ? rowsNumMax + iy : rowsNumMax - iy - 1;
158 
159  // Determine 1D index in the mapping table; if fibers are not wanted, just
160  // use the same array with an offset of 1;
161  UInt_t geant[6] = {0, 0, 0, 0, tcounter, 2*iqx + iqy}, group = 0, logical[2] = {XX, YY};
162 #ifdef _NO_STRUCTURE_GEOMETRY_
163  //if (fgmap->SetMappingTableEntry(id + 3, UGeo_t((XX << 16) | YY))) {
164  if (emcal->SetMappingTableEntry(fgmap, geant + 3, group, logical)) {
165  cout << "Failed to set mapping table entry!" << endl;
166  exit(0);
167  } //if
168 #else
169  for(unsigned iqq=0; iqq<fptr->GetLayerNum(); iqq++) {
170  EicGeoMap *fgmap = emcal->GetMapPtrViaMapID(iqq);
171 
172  //if (fgmap->SetMappingTableEntry(id, UGeo_t((XX << 16) | YY))) {
173  if (emcal->SetMappingTableEntry(fgmap, geant, group, logical)) {
174  cout << "Failed to set mapping table entry!" << endl;
175  exit(0);
176  } //if
177  } //for iqq
178 #endif
179  } //for iqx..iqy
180 
181  {
182  TGeoRotation *rt = new TGeoRotation();
183  // Want to mimic 2x1 tower assembly layout of fibers; so "swap" all towers with
184  // odd X-direction index; actually 180 degree Z-rotation of "new" tower layout
185  // should not make any effect;
186 #ifdef _ASSUME_TWO_TOWER_ASSEMBLIES_
187  if (ix%2) rt->RotateZ(180);
188 #endif
189 
190  vquadrant->AddNode(vtower, tcounter++,
191  new TGeoCombiTrans(0.1 * xx, 0.1 * yy, 0.0, rt));
192  }
193  } //for iy
194  } //for ix
195 
196  printf("%5d towers per quadrant\n", tcounter);
197 
198  // Locate 4 quadrant copies in the "FEMC" volume;
199  for(int ixy=0; ixy<4; ixy++) {
200  Double_t local[4] = {emcal->mInterQuadrantGap/2, emcal->mInterQuadrantGap/2, 0, 0}, master[4];
201 
202  _qquad[ixy]->LocalToMaster(local, master);
203 
204  emcal->GetTopVolume()->AddNode(vquadrant, ixy,
205  new TGeoCombiTrans(0.1 * master[0], 0.1 * master[1], 0.0, _qquad[ixy]));
206  } //for ixy
207  }
208 
209  // And put this stuff as a whole into the top volume; account Z-shift;
210  {
211  TGeoRotation *rw = new TGeoRotation();
212 
213  if (beamLineOffset < 0.0) rw->RotateY(180);
214 
215  //emcal->FinalizeOutput(new TGeoCombiTrans(0., 0., 0.1 * emcal->mBeamLineOffset, rw));
216  emcal->SetTopVolumeTransformation(new TGeoCombiTrans(0.0, 0.0, 0.1 * beamLineOffset, rw));
217  }
218 
219  //emcal->GetColorTable()->AddPatternMatch(cname + "Tower", kBlue);
220  emcal->GetColorTable()->AddPatternMatch(cname + "Quadrant", kBlue);
221 
222  emcal->FinalizeOutput();
223  } //for fb
224 
225  // Yes, always exit;
226  exit(0);
227 }
228