EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EicBeamLineElementMap.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EicBeamLineElementMap.cxx
1 // AYK (ayk@bnl.gov), 2014/09/03
2 //
3 // EIC IR Beam line element magnetic field map handler;
4 //
5 
6 //
7 // CHECK: XY-orientation (well, and Z-sign as well); A[][] -> transpose or not?;
8 //
9 
10 #include <stdlib.h>
11 #include <assert.h>
12 #include <math.h>
13 
14 #include <TGeoBBox.h>
15 #include <TGeoVolume.h>
16 
17 // FIXME: clean up these dependencies later;
18 //#include <htclib.h>
19 //extern char XYZ[3];
20 static char XYZ[3] = {'X', 'Y', 'Z'};
21 #include <Mgrid.h>
22 
23 #include <EicLibrary.h>
24 #include <EicBeamLineElementMap.h>
25 
26 // =======================================================================================
27 
28 //
29 // FIXME: check against the latest EicHtcTask codes and modify accordingly;
30 //
31 
33 {
34  // Figure out the actual file name;
35  TString fileName = ExpandedFileName("input/", GetFileName());
36 
37  FILE *fin = fopen(fileName.Data(), "r");
38  if (!fin) {
39  printf("-E- EicBeamLineElementMap::Initialize() -> fail to open '%s' file!\n", fileName.Data());
40  return -1;
41  } //if
42 
43  char buffer[1024];
44 
45  // Skip 1-st line (a comment);
46  fgets(buffer, 1024-1, fin);
47 
48  // Import A[3][3] and b[3] 3D transformation parameters; prefer to encode them in
49  // mTransformation rather than in Mgrid internally;
50  {
51  double A[9], b[3];
52 
53  // Files have comma-separated field (and no spaces); and LF they do have too -> "\n"; rely on this;
54  if (fscanf(fin, "%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf\n",
55  A+0, A+1, A+2, A+3, A+4, A+5, A+6, A+7, A+8, b+0, b+1, b+2) != 12) {
56  printf("-E- EicBeamLineElementMap::Initialize() -> file '%s': wrong input format!\n", fileName.Data());
57  return -1;
58  } //if
59 
60  printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f %15.10f %15.10f %15.10f ... %15.10f %15.10f %15.10f\n",
61  A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[8], b[0], b[1], b[2]);
62 
63  // Assume matrix A[][] does not require transposition here; FIXME: check on that!;
64  TGeoRotation *rw = new TGeoRotation();
65  rw->SetMatrix(A);
66  // Convert [m] -> [cm];
67  mTransformation = new TGeoCombiTrans(100.0 * b[0], 100.0 * b[1], 100.0 * b[2], rw);
68  }
69 
70  // Skip 3-rd line (a comment);
71  fgets(buffer, 1024-1, fin);
72 
73  // Import grid parameters;
74  {
75  // Follow Stephen's notation;
76  unsigned Nx, Ny, Nz;
77  double x0, x1, dx, y0, y1, dy, z0, z1, dz;
78 
79  if (fscanf(fin, "%lf,%lf,%d,%lf,%lf,%lf,%d,%lf,%lf,%lf,%d,%lf\n",
80  &x0, &x1, &Nx, &dx, &y0, &y1, &Ny, &dy, &z0, &z1, &Nz, &dz) != 12) {
81  printf("-E- EicBeamLineElementMap::Initialize() -> file '%s': wrong input format!\n", fileName.Data());
82  return -1;
83  } //if
84 
85  // Well, in this particular case have to resort to using fOrigin[] in TGeoBBox definition;
86  // also convert [m] to [cm] units here; NB: consider to cut the box right at the edge point
87  // location in TGeoBBox declaration (so that Contains() call selects this area only); however
88  // the imported grid will be extended by half-cell in all directions according to HTC-style map
89  // conventions (so defined grid points will become cubic cell centers); FIXME: clarify the
90  // idea with Stephen at some point;
91  double origin[3] = {100.0 * (x0+x1)/2, 100.0 * (y0+y1)/2, 100.0 * (z0+z1)/2};
92  mShape = dynamic_cast<TGeoShape*>(TGeoBBox(100.0 * (x1-x0)/2, 100.0 * (y1-y0)/2,
93  100.0 * (z1-z0)/2, origin).Clone());
94 
95  // Now can define HTC-style grid array; could have probably used import_ascii_field_map()
96  // with some modifications; prefer to do everything by hand though, especially since step
97  // is declared in the ASCII file header anyway; follow the logic of
98  // EicHtcTask::initializeMgridSlice() call;
99  {
100  // Create empty mgrid;
101  int dim[3] = {Nx, Ny, Nz};
102  // So add half-cell on all sides;
103  double min[3] = {x0 - dx/2, y0 - dy/2, z0 - dz/2}, max[3] = {x1 + dx/2, y1 + dy/2, z1 + dz/2};
104 
105  MgridDirection *fdir[3];
106  CoordSystem *csystem = new CoordSystem(_CARTESIAN_, 3, XYZ);
107  CoordSystem *fsystem = new CoordSystem(_CARTESIAN_, 3, XYZ);
108  assert(csystem && fsystem);
109 
110  // Create direction frames; NB: NO fake Z!;
111  for(int ik=0; ik<3; ik++) {
112  // Rescale [m] -> [cm];
113  min[ik] *= 100.0;
114  max[ik] *= 100.0;
115 
116  fdir[ik] = new MgridDirection(dim[ik], min[ik], max[ik]);
117  } //for ik
118 
119  // Eventually create and initialize mgrid;
120  mGrid = create_single_mgrid_header((char*)"DUMMY", csystem, fsystem,
122  if (!mGrid || mGrid->initializeAsSingleMgrid(0)) {
123  printf("-E- EicBeamLineElementMap::Initialize(): !!! most likely you ran out of memory !!!\n\n");
124  return -1;
125  } /*if*/
126 
127  // Set desired interpolation mode; FIXME: no interpolation for now;
128  //if (slice->mgrid->setHtcInterpolationMode(&RK_htci)) return NULL;
129  assert(!mGrid->turnInterpolationOff());
130  }
131 
132  // Skip 5-th line (a comment);
133  fgets(buffer, 1024-1, fin);
134 
135  // Import all the expected Nx*Ny*Nz lines with the real data;
136  {
137  unsigned dim3D = Nx*Ny*Nz;
138 
139  //
140  // FIXME: check these codes after HTC re-import;
141  //
142 
143  for(unsigned lc=0; lc<dim3D; lc++) {
144  //t_3d_vector xx, BB;
145  double xx[3], BB[3];
146 
147  if (fscanf(fin, "%lf,%lf,%lf,%lf,%lf,%lf\n",
148  xx+0, xx+1, xx+2, BB+0, BB+1, BB+2) != 6) {
149  printf("-E- EicBeamLineElementMap::Initialize() -> file '%s': wrong input format!\n", fileName.Data());
150  return -1;
151  } //if
152 
153  // Convert [m] -> [cm];
154  for(unsigned iq=0; iq<3; iq++)
155  xx[iq] *= 100.;
156 
157  MgridCell *cell = mGrid->coordToCellPtr(xx); assert(cell);
158  for(unsigned iq=0; iq<3; iq++)
159  // Convert [T] -> [kGs];
160  cell->B[iq] = 10.0 * BB[iq] * mScale;
161 
162  unsigned linear = mGrid->cellPtrToLinear(cell);
163  //assert(linear < dim3D);
164  mGrid->markCellAsSafe(linear);
165  } //for iq
166 
167  //for(unsigned lc=0; lc<dim3D; lc++)
168  //assert(mGrid->GetCellProperty(lc) == _SAFE_CELL_);
169  }
170  }
171 
172  // Import bore parameters;
173  if (fscanf(fin, "Length,%lf\n", &mLength) != 1 ||
174  fscanf(fin, "Angle,%lf\n", &mAngle) != 1 ||
175  fscanf(fin, "Bore,%lf\n", &mBore) != 1) {
176  printf("-E- EicBeamLineElementMap::Initialize() -> file '%s': bore information missing!\n", fileName.Data());
177  return -1;
178  } //if
179  //printf("%f %f %f\n", mLength, mAngle, mBore); exit(0);
180 
181  fclose(fin);
182 
184 } // EicBeamLineElementMap::Initialize()
185 
186 
187 void EicBeamLineElementMap::SetFieldScale(const double fieldScaler)
188 {
189  mScale = fieldScaler;
190 }
191 
192 
193 // ---------------------------------------------------------------------------------------
194 
195 //
196 // NB: can not move to the header file because then would need to include Mgrid headers;
197 //
198 
199 int EicBeamLineElementMap::GetFieldValue(const double xx[], double B[]) const
200 {
201 #if 0
202  {
203  double global[3] = {-4.9, -4.6, 950}, local[3];
204 
205  mTransformation->MasterToLocal(global, local);
206 
207  mGrid->getCartesianFieldValue(local, B);
208  printf("local[]: %f %f %f -> B[] = %f %f %f -> (%d)\n", local[0], local[1], local[2], B[0], B[1], B[2], Contains(global)); exit(0);
209  }
210 #endif
211 
212  //
213  // Convert xx[] to local coordinate system -> calculate field -> convert to global B[];
214  //
215 
216  //
217  // FIXME: check these codes (after HTC re-import);
218  //
219 
220  double xl[3];//, BL[3];
221 
222  // NB: it looks like this->Contains() call will also have to perform mTransformation->MasterToLocal()
223  // before doing anything else; so no gain to call it first; THINK: the only thing I can do to speed
224  // processing up is to call mShape->Contains() after mTransformation->MasterToLocal() here; hmm?;
225  mTransformation->MasterToLocal(xx, xl);
226 
227  // If ever care about performance, consider to use mGrid->directFieldValue();
228  {
229  TVector3 xlv(xl[0], xl[1], xl[2]), BLV;
230 
231  if (mGrid->getCartesianFieldValue(xlv, BLV)) {
232  for(unsigned iq=0; iq<3; iq++)
233  B[iq] = 0.0;
234 
235  return -1;
236  } //if
237 
238  double BL[3] = {BLV[0], BLV[1], BLV[2]};
239  mTransformation->LocalToMasterVect(BL, B);
240  }
241 
242  return 0;
243 } // EicBeamLineElementMap::GetFieldValue()
244 
245 // ---------------------------------------------------------------------------------------
246 
247 #include <EicMediaHub.h>
248 
249 // Make it configurable parameter later; for now just add 100mm to both width and height;
250 #define _EXTRA_BORE_WIDTH_ (100.0)
251 
252 #define _IRON_ ("iron")
253 #define _VACUUM_ ("vacuum")
254 #define _ALUMINUM_ ("aluminum")
255 
256 #include <TGeoManager.h>
257 
259 {
260  // FIXME: obviously need an Instance() member there;
261  EicMediaHub *mediaHub = new EicMediaHub();
262 
263  mediaHub->Init();
264 
265  // Ok, basically I need to create something matching yoke volume and put it in a proper
266  // place in the geometry tree;
267  char yokeIronName[128], yokeVacuumName[128];
268 
269  snprintf(yokeIronName, 128-1, "%s-Yoke", GetDetectorName().Data());
270  snprintf(yokeVacuumName, 128-1, "%s-Vacuum", GetDetectorName().Data());
271 
272  // Just per Stephen's definition I guess;
273  double origin[3] = {0.0, 0.0, 100.0 * mLength/2};
274  TGeoBBox *yoke = new TGeoBBox(yokeIronName,
275  100.0 * mBore + 0.1 * _EXTRA_BORE_WIDTH_,
276  100.0 * mBore + 0.1 * _EXTRA_BORE_WIDTH_,
277  100.0 * mLength/2, origin);
278  mYoke = new TGeoVolume(yokeIronName, yoke, mediaHub->GetMedium(_IRON_));
279  mYoke->SetFillColor(GetYokeColor());
280  // FIXME: this has no effect -> check!;
281  mYoke->SetLineColor(GetYokeColor());
282  mYoke->RegisterYourself();
283 
284  // Should be vacuum, not air, I guess?; NB: as of 2014/09/11 some of the bores
285  // are set to 0.0 by Stephen (not known yet) -> just do not insert bore volume at all;
286  if (mBore) {
287  TGeoTube *vacuum = new TGeoTube(yokeVacuumName,
288  0.0,
289  100.0 * mBore,
290  100.0 * mLength/2);
291  TGeoVolume *vvacuum = new TGeoVolume(yokeVacuumName, vacuum, mediaHub->GetMedium(_VACUUM_));
292  vvacuum->RegisterYourself();
293 
294  mYoke->AddNode(vvacuum, 0, new TGeoTranslation(origin[0], origin[1], origin[2]));
295  } //if
296 
297 
298  // if(mAngle)
299  // {
300  // mTransformation->RotateY(mAngle*(180./3.14159265359));
301  // //mTransformation->SetDx(0.1*(origin[2]+mLength/2.)*sin(mAngle));
302  // }
303  /*
304  if(mAngle && mLength>0.6)
305  {
306  mTransformation->RotateY(mAngle);
307  if(mLength>2. && mLength<3.)
308  mTransformation->SetDx(10); // was 10 in my original mod (just rotating this last aperture)
309  if(mLength>1.5 && mLength<2.)
310  mTransformation->SetDx(7.5);
311  if(mLength>1. && mLength<1.5)
312  mTransformation->SetDx(5.2);
313  }
314  */
315  /*
316  if(mAngle == -0.573)
317  {
318  mTransformation->RotateY(mAngle);
319  mTransformation->SetDx(33.2);
320  }
321  */
322  //add the aluminum exit window
323  /*
324  TGeoBBox *exitWindow= new TGeoBBox("AlExitWindow",
325  5.,
326  5.,
327  0.99);
328  TGeoVolume *vexitWindow = new TGeoVolume("AlExitWindow", exitWindow, mediaHub->GetMedium(_ALUMINUM_));
329  vexitWindow->RegisterYourself();
330 
331  mYoke->AddNode(vexitWindow, 0, new TGeoTranslation(origin[0], origin[1], origin[2]-200.));
332  */
333 
334  gGeoManager->GetTopVolume()->AddNode(mYoke, 0, mTransformation);
335 
336  return 0;
337 
338 } // EicBeamLineElementMap::ConstructGeometry()
339 
340 // =======================================================================================
341