EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hcal.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file hcal.C
1 
2 // Meaningless number for now; fine;
3 #define _VERSION_ 1
4 #define _SUBVERSION_ 0
5 
6 // Just rectangular PbSciMix volumes with no structure; useful for drawing purposes
7 // as well as for fast simulation (FIXME: should be adapted); NB: this definition
8 // should be *before* hcal-lib.C include below;
9 #define _NO_STRUCTURE_GEOMETRY_
10 
11 // Yes, keep it simple; assume this library file is in the same directory;
12 #include <./hcal-lib.C>
13 
14 #if 0
15 struct {
16  char *name;
17  double offset;
18 } dets[] = {
19  {"fhac", 3400.},
20  {"bhac", -3400.+1130.}
21 };
22 #endif
23 static double offsets[2] = {-3400.+1130., 3400.};
24 
26 {
27  // Load basic libraries;
28  gROOT->Macro("$VMCWORKDIR/gconfig/rootlogon.C");
29 
30  // Loop over forward/backward parts;
31  for(unsigned fb=0; fb<2; fb++) {
33  //(HcalGeoParData *)define_basic_parameters(fb ? "BHAC" : "FHAC", _VERSION_, _SUBVERSION_);
35  const TString& cname = hcal->GetDetName()->Name();
36 
37  // Forward calorimeter only, for now;
38 #ifdef _NO_STRUCTURE_GEOMETRY_
40  //TString filename = lname + "-ns.root";
41 #else
42  //TString filename = lname + "-fs.root";
44 #endif
45 
46  //
47  // Prefer to think in [mm] and convert to [cm] when calling ROOT shape
48  // definition routines only;
49  //
50 
51  // Endcap is shifted along H+ direction as a whole;
52  double beamLineOffset = offsets[fb];//dets[fb].offset;
53 
54  // Pick up whatever parameters for now;
55  hcal->mEndcapMinR = 20.0;
56  hcal->mEndcapMaxTheta = 40.;
57  // Do not allow subunits to protrude towards too small and too large radii;
58  hcal->mSafetyVolume = 10.0;
59 
60  // Well, assume no-gap packing?;
61  hcal->mInterQuadrantGap = 0.0;
62 
63  // This part of the script can be shared between various calorimeter types;
64  const Double_t endcapMaxR =
65  fabs(beamLineOffset) * tan(hcal->mEndcapMaxTheta * TMath::Pi() / 180.);
66 
67  const Double_t envelopeWidth = hcal->mCellFaceSizeX + hcal->mInterCellGap;
68 
69  // Estimate an absolutely max number of rows;
70  const Int_t rowsNumMax = (int)floor(endcapMaxR / envelopeWidth);
71  //cout << rowsNumMax << endl;
72  // Do not mind to use just this number in order to calculate XY-dimensions;
73  // if the actual matrix will be a bit smaller, this does not really matter;
74  //hcal->SetDimX(2*rowsNumMax); hcal->SetDimY(2*rowsNumMax);
75  hcal->AddLogicalVolumeGroup(2*rowsNumMax, 2*rowsNumMax);
76  struct FemcRow {
77  Double_t yc;
78  } *rows = calloc(rowsNumMax, sizeof(FemcRow));
79 
80  for(int iq=0; iq<rowsNumMax; iq++) {
81  FemcRow *row = rows + iq;
82 
83  row->yc = envelopeWidth * (iq + 0.5);
84  } //for iq
85 
86  // Assume the 4 quadrants are identical (like in PANDA); one quadrant is a
87  // 90 degree TUBS volume of known parameters;
88  {
89  // Yes, seems to be the easiest way to define them :-); NB: used in two places;
90  TGeoRotation *_qquad[4];
91  for(int ixy=0; ixy<4; ixy++)
92  _qquad[ixy] = new TGeoRotation();
93  // NB: want [X][Y]-ordering among quadrants and 2x2 subunit crystals and no
94  // coordinate swapping -> reflections in favor of 90-degree rotations;
95  _qquad[0]->RotateZ(180);
96  _qquad[1]->ReflectX(kTRUE);
97  _qquad[2]->ReflectY(kTRUE);
98 
99  TGeoTubeSeg *quadrant = new TGeoTubeSeg(cname + "Quadrant",
100  0.1 * hcal->mEndcapMinR,
101  0.1 * endcapMaxR,
102  0.1 * hcal->mCellLength/2.,
103  0.0, 90.0);
104  TGeoVolume *vquadrant = new TGeoVolume(cname + "Quadrant", quadrant, hcal->GetMedium("air"));
105 
106  // _DUMMY_ definition can be interpreted correctly there;
107  TGeoVolume *vtower = make_single_tower(hcal);
108 
109  // Configure tower map;
110  EicGeoMap *gmap = hcal->CreateNewMap();
111 #ifndef _NO_STRUCTURE_GEOMETRY_
112  gmap->AddGeantVolumeLevel(cname + "ScintillatorPlate", 0);
113 #endif
114  gmap->AddGeantVolumeLevel(cname + "Tower", rowsNumMax*rowsNumMax);
115  gmap->AddGeantVolumeLevel(cname + "Quadrant", 4);
116 
117  gmap->SetSingleSensorContainerVolume(cname + "Tower");
118 
119  hcal->AddBlackHoleVolume(cname + "Quadrant");
120  hcal->AddBlackHoleVolume(cname + "FrontPlate");
121 
122  // Populate quadrant volume with towers; FIXME: later there should be some construction
123  // material as well; for now do NOT put something like front steel plate into
124  // either quadrant separately or a single tower;
125  unsigned tcounter = 0;
126  for(int ix=0; ix<rowsNumMax; ix++) {
127  FemcRow *brx = rows + ix;
128  // Yes, coordinates are remapped here; Z-coordinate will be just a focal distance;
129  double xx = brx->yc;
130 
131  for(int iy=0; iy<rowsNumMax; iy++) {
132  FemcRow *bry = rows + iy;
133  double yy = bry->yc;
134 
135  // Calculate radial distance from (0,0); at the inner edge assume that can
136  // take center coordinates and give subunit diagonal dimension with some safety
137  // margin as a reference;
138  double rr = sqrt(xx*xx + yy*yy);
139  if (rr - hcal->mCellFaceSizeX/sqrt(2.) - hcal->mSafetyVolume < hcal->mEndcapMinR) continue;
140  if (rr + hcal->mCellFaceSizeX/sqrt(2.) + hcal->mSafetyVolume > endcapMaxR) continue;
141 
142  // Loop through 2x2 quadrants and add the 4 tower entries into the mapping table;
143  for(int iqx=0; iqx<2; iqx++)
144  for(int iqy=0; iqy<2; iqy++) {
145  int XX = iqx ? rowsNumMax + ix : rowsNumMax - ix - 1;
146  int YY = iqy ? rowsNumMax + iy : rowsNumMax - iy - 1;
147 
148  // Determine 1D index in the mapping table;
149 #ifdef _NO_STRUCTURE_GEOMETRY_
150  UInt_t geant[2] = { tcounter, 2*iqx + iqy};
151 #else
152  UInt_t geant[3] = {0, tcounter, 2*iqx + iqy};
153 #endif
154  unsigned group = 0, logical[2] = {XX, YY};
155  //if (gmap->SetMappingTableEntry(id, UGeo_t((XX << 16) | YY))) {
156  if (hcal->SetMappingTableEntry(gmap, geant, group, logical)) {
157  cout << "Failed to set mapping table entry!" << endl;
158  exit(0);
159  } //if
160  } //for iqx..iqy
161 
162  {
163  TGeoRotation *rt = new TGeoRotation();
164 
165  vquadrant->AddNode(vtower, tcounter++,
166  new TGeoCombiTrans(0.1 * xx, 0.1 * yy, 0.0, rt));
167  }
168  } //for iy
169  } //for ix
170 
171  printf("%5d towers per quadrant\n", tcounter);
172 
173  // Locate 4 quadrant copies in the "main" volume;
174  for(int ixy=0; ixy<4; ixy++) {
175  Double_t local[4] = {hcal->mInterQuadrantGap/2, hcal->mInterQuadrantGap/2, 0, 0}, master[4];
176 
177  _qquad[ixy]->LocalToMaster(local, master);
178 
179  hcal->GetTopVolume()->AddNode(vquadrant, ixy,
180  new TGeoCombiTrans(0.1 * master[0], 0.1 * master[1], 0.0, _qquad[ixy]));
181  }
182  }
183 
184  // And put this stuff as a whole into the top volume; account Z-shift;
185  {
186  TGeoRotation *rw = 0;
187 
188  if (beamLineOffset < 0.0) {
189  rw = new TGeoRotation();
190 
191  rw->RotateY(180);
192  } //if
193 
194  hcal->SetTopVolumeTransformation(new TGeoCombiTrans(0.0, 0.0, 0.1 * beamLineOffset, rw));
195  }
196 
197  // Let them be green;
198  hcal->GetColorTable()->AddPatternMatch(cname + "Tower", kGreen+1);
199  //hcal->GetColorTable()->AddPatternMatch(cname + "Quadrant", kGreen+1);
200 
201  hcal->FinalizeOutput();
202  } //for fb
203 
204  // Yes, always exit;
205  exit(0);
206 }
207