Public Member Functions | Private Member Functions | Private Attributes | List of all members
mag::GArMagneticField Class Reference

#include <GArMagneticField.h>

Inheritance diagram for mag::GArMagneticField:

Public Member Functions

 GArMagneticField (fhicl::ParameterSet const &pset)
 
 GArMagneticField (GArMagneticField const &)=delete
 
virtual ~GArMagneticField ()=default
 
void reconfigure (fhicl::ParameterSet const &pset)
 
std::vector< MagneticFieldDescription > const & Fields () const override
 
size_t NumFields () const override
 
MagFieldMode_t const & UseField (size_t f) const override
 
std::string const & MagnetizedVolume (size_t f) const override
 
G4ThreeVector const FieldAtPoint (G4ThreeVector const &p=G4ThreeVector(0)) const override
 
G4ThreeVector const UniformFieldInVolume (std::string const &volName) const override
 

Private Member Functions

void ReadRZFile (const std::string &filename, RZFieldMap &rzmap)
 
void ReadXYZFile (const std::string &filename, XYZFieldMap &xyzmap, const float unitFactor)
 
G4ThreeVector CalcRZField (G4ThreeVector const &p, RZFieldMap const &rzmap) const
 
G4ThreeVector CalcXYZField (G4ThreeVector const &p, XYZFieldMap const &xyzmap) const
 

Private Attributes

float fGlobalScaleFactor
 
std::vector< MagneticFieldDescription > fFieldDescriptions
 Descriptions of the fields. More...
 
float fUnitFactor
 

Detailed Description

Definition at line 25 of file GArMagneticField.h.

Constructor & Destructor Documentation

mag::GArMagneticField::GArMagneticField ( fhicl::ParameterSet const &  pset)
explicit

Definition at line 46 of file GArMagneticField.cxx.

47 {
48  this->reconfigure(pset);
49 }
void reconfigure(fhicl::ParameterSet const &pset)
mag::GArMagneticField::GArMagneticField ( GArMagneticField const &  )
delete
virtual mag::GArMagneticField::~GArMagneticField ( )
virtualdefault

Member Function Documentation

G4ThreeVector mag::GArMagneticField::CalcRZField ( G4ThreeVector const &  p,
RZFieldMap const &  rzmap 
) const
private

Definition at line 364 of file GArMagneticField.cxx.

365 {
366  // check for validity
367  if(rzm.dr <= 0)
368  {
369  throw cet::exception("GArMagneticField: RZ map bad R spacing:") << rzm.dr;
370  }
371  if(rzm.dz <= 0)
372  {
373  throw cet::exception("GArMagneticField: RZ map bad Z spacing:") << rzm.dz;
374  }
375 
376  TVector3 pv(p.x(), p.y(), p.z());
377  TVector3 ploc = pv - rzm.CoordOffset;
378  float zloc = ploc.Dot(rzm.ZAxis);
379  float rloc = (ploc.Cross(rzm.ZAxis)).Mag();
380  float azloc = TMath::Abs(zloc);
381  if(azloc > rzm.dz * rzm.nz() || rloc > rzm.dr * rzm.nr())
382  {
383  return G4ThreeVector(0, 0, 0);
384  }
385  else
386  {
387  TVector3 fv(0, 0, 0);
388  size_t ibinr = rloc / rzm.dr;
389  size_t ibinz = azloc / rzm.dz;
390  float bzcomponent = rzm.bz.at(ibinr).at(ibinz); // closest grid point
391 
392  // cheesy interpolation in just one direction at a time. A better interpolation
393  // would be to stretch a surface around four points.
394  // also this interpolation naively only interpolates Bz as a function of Z and
395  // br as a function of r. the four-point surface would be more symmetrical
396 
397  if(ibinz == 0)
398  {
399  float dbz
400  = ((rzm.bz.at(ibinr).at(ibinz + 1) - bzcomponent) / rzm.dz) * (azloc - (int)azloc);
401  bzcomponent += dbz;
402  }
403  else
404  {
405  float dbz = (bzcomponent - (rzm.bz.at(ibinr).at(ibinz - 1)) / rzm.dz)
406  * (azloc - rzm.dz * ((int)azloc / rzm.dz));
407  bzcomponent += dbz;
408  }
409  fv = bzcomponent * rzm.ZAxis; // z component of field.
410 
411  float bradial = rzm.br.at(ibinr).at(ibinz);
412  if(ibinr == 0)
413  {
414  float dbr = ((rzm.br.at(ibinr + 1).at(ibinz) - bradial) / rzm.dr)
415  * (rloc - rzm.dr * ((int)rloc / rzm.dr));
416  bradial += dbr;
417  }
418  else
419  {
420  float dbr = (bradial - (rzm.br.at(ibinr - 1).at(ibinz)) / rzm.dr)
421  * (rloc - rzm.dr * ((int)rloc / rzm.dr));
422  bradial += dbr;
423  }
424 
425  // calculate radial direction of the field
426 
427  TVector3 rperp = ploc - zloc * rzm.ZAxis;
428  float mrp = rperp.Mag();
429 
430  // we only can have a radial component of the field if we are at r>0
431  if(mrp != 0)
432  {
433  rperp *= (1.0 / mrp);
434  if(zloc > 0) // swap the radial field direction based on the sign of z.
435  {
436  fv += rperp * bradial;
437  }
438  else
439  {
440  fv -= rperp * bradial;
441  }
442  }
443  G4ThreeVector fvg(fv.X(), fv.Y(), fv.Z());
444  return fvg;
445  }
446 }
p
Definition: test.py:223
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
G4ThreeVector mag::GArMagneticField::CalcXYZField ( G4ThreeVector const &  p,
XYZFieldMap const &  xyzmap 
) const
private

Definition at line 449 of file GArMagneticField.cxx.

450 {
451  const float x = fd.UseSymmetry ? std::abs(p.x() - fd.xo) : p.x() - fd.xo;
452  const float y = fd.UseSymmetry ? std::abs(p.y() - fd.yo) : p.y() - fd.yo;
453  const float z = fd.UseSymmetry ? std::abs(p.z() - fd.zo) : p.z() - fd.zo;
454 
455  Interpolator interp;
456  const float bx = interp.interpolate(x, y, z, fd.fx, fd.dx, fd.dy, fd.dz, 0.0, 0.0, 0.0);
457  const float by = interp.interpolate(x, y, z, fd.fy, fd.dx, fd.dy, fd.dz, 0.0, 0.0, 0.0);
458  const float bz = interp.interpolate(x, y, z, fd.fz, fd.dx, fd.dy, fd.dz, 0.0, 0.0, 0.0);
459 
460  return G4ThreeVector(bx, by, bz);
461 }
T abs(T value)
p
Definition: test.py:223
list x
Definition: train.py:276
G4ThreeVector const mag::GArMagneticField::FieldAtPoint ( G4ThreeVector const &  p = G4ThreeVector(0)) const
override

Definition at line 168 of file GArMagneticField.cxx.

169 {
170  // check that the input point is in the magnetized volume
171  // Use the gGeoManager to determine what node the point
172  // is in
173  double point[3] = {p.x(), p.y(), p.z()};
174  G4ThreeVector zerofield(0, 0, 0);
175  G4ThreeVector calculatedfield = zerofield;
176 
177  // loop over the field descriptions to see if the point is in any of them
178  for(const auto& fd : fFieldDescriptions)
179  {
180  // we found a node, see if its name is the same as
181  // the volume with the field
182 
183  if(fd.fGeoVol->Contains(point))
184  {
185  // "Automatic" for now just means constant field.
186  if(fd.fMode == mag::kConstantBFieldMode || fd.fMode == mag::kAutomaticBFieldMode)
187  {
188  calculatedfield = fd.fField;
189  }
190  else if(fd.fMode == mag::kNoBFieldMode)
191  {
192  calculatedfield = zerofield;
193  }
194  else if(fd.fMode == mag::kFieldRZMapMode)
195  {
196  calculatedfield = CalcRZField(p, fd.fRZFieldMap);
197  }
198  else if(fd.fMode == mag::kFieldXYZMapMode)
199  {
200  calculatedfield = CalcXYZField(p, fd.fXYZFieldMap);
201  }
202  else
203  {
204  throw cet::exception("GArMagneticField_service: Ununderstood field mode: ")
205  << fd.fMode;
206  }
207  }
208  calculatedfield *= fd.fScaleFactor;
209  }
210 
211  calculatedfield *= fGlobalScaleFactor;
212 
213  // std::cout << "field at point: " << p << " field: " << calculatedfield << std::endl;
214  return calculatedfield;
215 }
std::vector< MagneticFieldDescription > fFieldDescriptions
Descriptions of the fields.
p
Definition: test.py:223
G4ThreeVector CalcRZField(G4ThreeVector const &p, RZFieldMap const &rzmap) const
G4ThreeVector CalcXYZField(G4ThreeVector const &p, XYZFieldMap const &xyzmap) const
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::vector<MagneticFieldDescription> const& mag::GArMagneticField::Fields ( ) const
inlineoverride

Definition at line 36 of file GArMagneticField.h.

36 { return fFieldDescriptions; }
std::vector< MagneticFieldDescription > fFieldDescriptions
Descriptions of the fields.
std::string const& mag::GArMagneticField::MagnetizedVolume ( size_t  f) const
inlineoverride

Definition at line 45 of file GArMagneticField.h.

45 { return fFieldDescriptions[f].fVolume; }
std::vector< MagneticFieldDescription > fFieldDescriptions
Descriptions of the fields.
size_t mag::GArMagneticField::NumFields ( ) const
inlineoverride

Definition at line 39 of file GArMagneticField.h.

39 { return fFieldDescriptions.size(); }
std::vector< MagneticFieldDescription > fFieldDescriptions
Descriptions of the fields.
void mag::GArMagneticField::ReadRZFile ( const std::string filename,
RZFieldMap &  rzmap 
)
private

Definition at line 234 of file GArMagneticField.cxx.

235 {
236  std::cout << "GArMagneticField: Opening magnetic field RZ map in: " << filename << std::endl;
237  std::ifstream inFile(filename, std::ios::in);
239 
240  int rcounter = -1;
241  float rcur = 0;
242  float zcur = 0;
243  rzmap.dr = 0;
244  rzmap.dz = 0;
245 
246  while(std::getline(inFile, line))
247  {
248  float x = 0;
249  float y = 0;
250  float z = 0;
251  float bx = 0;
252  float by = 0;
253  float bz = 0;
254  float b = 0;
255  std::stringstream linestream(line);
256  linestream >> x >> y >> z >> bx >> by >> bz >> b;
257  // we get this in meters. convert to cm
258  x *= 100.0;
259  y *= 100.0;
260  z *= 100.0;
261  float r = TMath::Sqrt(x * x + y * y);
262  float br = bx; // Vladimir's map defines it this way.
263 
264  std::vector<float> emptyvec;
265  if(TMath::Abs(r - rcur) > 0.001 || rcounter < 0)
266  {
267  rzmap.br.push_back(emptyvec);
268  rzmap.bz.push_back(emptyvec);
269  rcounter++;
270  if(r > rcur + 0.001)
271  {
272  rzmap.dr = r - rcur;
273  }
274  rcur = r;
275  }
276  rzmap.br[rcounter].push_back(br);
277  rzmap.bz[rcounter].push_back(bz);
278  if(z - zcur > 0.001)
279  {
280  rzmap.dz = z - zcur;
281  }
282  zcur = z;
283  }
284 }
std::string string
Definition: nybbler.cc:12
string filename
Definition: train.py:213
TFile * inFile
Definition: makeDST.cxx:36
void line(double t, double *p, double &x, double &y, double &z)
static bool * b
Definition: config.cpp:1043
list x
Definition: train.py:276
QTextStream & endl(QTextStream &s)
void mag::GArMagneticField::ReadXYZFile ( const std::string filename,
XYZFieldMap &  xyzmap,
const float  unitFactor 
)
private

Definition at line 287 of file GArMagneticField.cxx.

288 {
289  std::cout << "GArMagneticField: Opening magnetic field XYZ map in: " << filename << std::endl;
290  std::fstream fin(filename, std::fstream::in);
292 
293  int xcount{-1}, ycount{-1}, zcount{-1};
294  float xcurr{0}, ycurr{0}, zcurr{0};
295 
296  while(std::getline(fin >> std::ws, line))
297  {
298  std::stringstream ss(line);
299 
300  if(ss.str().front() == '#')
301  continue;
302 
303  ss >> xyzmap.xo >> xyzmap.yo >> xyzmap.zo >> xyzmap.dx >> xyzmap.dy >> xyzmap.dz;
304 
305  // Position coordinates need to be in mm
306  xyzmap.xo *= unitFactor;
307  xyzmap.yo *= unitFactor;
308  xyzmap.zo *= unitFactor;
309  xyzmap.dx *= unitFactor;
310  xyzmap.dy *= unitFactor;
311  xyzmap.dz *= unitFactor;
312 
313  break;
314  }
315 
316  while(std::getline(fin >> std::ws, line))
317  {
318  float x{0}, y{0}, z{0}, fx{0}, fy{0}, fz{0}, f{0};
319  std::stringstream ss(line);
320 
321  if(ss.str().front() == '#')
322  continue;
323 
324  ss >> x >> y >> z >> fx >> fy >> fz >> f;
325 
326  // Position coordinates need to be in mm
327  x *= unitFactor;
328  y *= unitFactor;
329  z *= unitFactor;
330 
331  if(std::abs(x - xcurr) > 0.0 || xcount < 0)
332  {
333  xcurr = x;
334  xcount += 1;
335  ycount = -1;
336  xyzmap.fx.emplace_back(std::vector<std::vector<float>>{});
337  xyzmap.fy.emplace_back(std::vector<std::vector<float>>{});
338  xyzmap.fz.emplace_back(std::vector<std::vector<float>>{});
339  }
340 
341  if(std::abs(y - ycurr) > 0.0 || ycount < 0)
342  {
343  ycurr = y;
344  ycount += 1;
345  zcount = -1;
346  xyzmap.fx[xcount].emplace_back(std::vector<float>{});
347  xyzmap.fy[xcount].emplace_back(std::vector<float>{});
348  xyzmap.fz[xcount].emplace_back(std::vector<float>{});
349  }
350 
351  xyzmap.fx[xcount][ycount].push_back(fx);
352  xyzmap.fy[xcount][ycount].push_back(fy);
353  xyzmap.fz[xcount][ycount].push_back(fz);
354 
355  if(std::abs(z - zcurr) > 0.0 || zcount < 0)
356  {
357  zcurr = z;
358  zcount += 1;
359  }
360  }
361 }
std::string string
Definition: nybbler.cc:12
struct vector vector
string filename
Definition: train.py:213
T abs(T value)
void line(double t, double *p, double &x, double &y, double &z)
list x
Definition: train.py:276
QTextStream & endl(QTextStream &s)
void mag::GArMagneticField::reconfigure ( fhicl::ParameterSet const &  pset)

Definition at line 52 of file GArMagneticField.cxx.

53 {
54  fGlobalScaleFactor = pset.get<float>("GlobalScaleFactor", 1.0);
55  fUnitFactor = pset.get<float>("UnitFactor", 1.);
56  auto fieldDescriptions = pset.get<std::vector<fhicl::ParameterSet>>("FieldDescriptions");
57 
58  MagneticFieldDescription fieldDescription;
59  for(auto itr : fieldDescriptions)
60  {
61  fieldDescription.fMode = (mag::MagFieldMode_t)(itr.get<int>("UseField"));
62 
63  // if the mode is turned to off, no point looking for a volume or
64  // trying to put a description into the fFieldDescriptions data member.
65  // if all input field descriptions are set to fMode = kNoBFieldMode, then the
66  // methods to return the fields will not go into the loop over fFieldDescriptions
67  // and will just return a 0 field.
68  if(fieldDescription.fMode == mag::kNoBFieldMode)
69  continue;
70 
71  fieldDescription.fScaleFactor = itr.get<float>("ScaleFactor", 1.0);
72  fieldDescription.fVolume = itr.get<std::string>("MagnetizedVolume");
73  fieldDescription.fGeoVol = gGeoManager->FindVolumeFast(fieldDescription.fVolume.c_str());
74 
75  // check that we have a good volume
76  if(fieldDescription.fGeoVol == nullptr)
77  {
78  throw cet::exception("GArMagneticField")
79  << "cannot locate volume " << fieldDescription.fVolume << " in gGeoManager, bail";
80  }
81 
82  // These need to be read as types that FHICL know about, but they
83  // are used by Geant, so I store them in Geant4 types.
84  std::vector<double> defaultField = {0, 0, 0};
85  std::vector<double> field = itr.get<std::vector<double>>("ConstantField", defaultField);
86 
87  // Force the dimension of the field definition
88  field.resize(3);
89  for(size_t i = 0; i < 3; ++i)
90  fieldDescription.fField[i] = field[i];
91 
92  if(fieldDescription.fMode == mag::kFieldRZMapMode)
93  {
94  fieldDescription.fFieldMapFilename = itr.get<std::string>("FieldMapFilename");
95  cet::search_path sp("FW_SEARCH_PATH");
96  std::string fn2 = fieldDescription.fFieldMapFilename;
97  std::string fullname;
98  sp.find_file(fn2, fullname);
99 
100  struct stat sb;
101  if(fullname.empty() || stat(fullname.c_str(), &sb) != 0)
102  {
103  throw cet::exception("RadioGen")
104  << "Input magnetic field file " << fn2 << " not found in FW_SEARCH_PATH!\n";
105  }
106 
107  auto start = std::chrono::steady_clock::now();
108  struct RZFieldMap rzmap;
109  ReadRZFile(fullname, rzmap);
111 
112  std::vector<double> ZAxis = itr.get<std::vector<double>>("ZAxis");
113  rzmap.ZAxis.SetXYZ(ZAxis[0], ZAxis[1], ZAxis[2]);
114 
115  std::vector<double> CoordOffset = itr.get<std::vector<double>>("CoordOffset");
116  rzmap.CoordOffset.SetXYZ(CoordOffset[0], CoordOffset[1], CoordOffset[2]);
117 
118  std::chrono::duration<double> elapsed_seconds = end - start;
119  std::cout << "GArMagneticField: Finished reading RZ map in " << elapsed_seconds.count() << "s, now setting it: " << rzmap.dr
120  << " " << rzmap.dz << std::endl;
121  std::cout << "Array sizes (R, Z): " << rzmap.br.size() << " " << rzmap.br[0].size()
122  << std::endl;
123  fieldDescription.fRZFieldMap = rzmap;
124  }
125 
126  if(fieldDescription.fMode == mag::kFieldXYZMapMode)
127  {
128  fieldDescription.fFieldMapFilename = itr.get<std::string>("FieldMapFilename");
129  cet::search_path sp("FW_SEARCH_PATH");
130  std::string fn2 = fieldDescription.fFieldMapFilename;
131  std::string fullname;
132  sp.find_file(fn2, fullname);
133 
134  struct stat sb;
135  if(fullname.empty() || stat(fullname.c_str(), &sb) != 0)
136  {
137  throw cet::exception("RadioGen")
138  << "Input magnetic field file " << fn2 << " not found in FW_SEARCH_PATH!\n";
139  }
140 
141  auto start = std::chrono::steady_clock::now();
142  struct XYZFieldMap xyzmap;
143  ReadXYZFile(fullname, xyzmap, fUnitFactor);
145 
146  std::vector<double> ZAxis
147  = itr.get<std::vector<double>>("ZAxis", std::vector<double>{0.0, 0.0, 1.0});
148  xyzmap.ZAxis.SetXYZ(ZAxis[0], ZAxis[1], ZAxis[2]);
149 
150  xyzmap.CoordOffset.SetXYZ(xyzmap.xo, xyzmap.yo, xyzmap.zo);
151  std::chrono::duration<double> elapsed_seconds = end - start;
152  std::cout << "GArMagneticField: Finished reading XYZ map in " << elapsed_seconds.count()
153  << "s." << std::endl;
154 
155  xyzmap.UseSymmetry = itr.get<bool>("UseSymmetry", false);
156  std::cout << "GArMagneticField: Is map symmetric - " << std::boolalpha
157  << xyzmap.UseSymmetry << std::endl;
158  fieldDescription.fXYZFieldMap = xyzmap;
159  }
160 
161  fFieldDescriptions.push_back(fieldDescription);
162  }
163 
164  return;
165 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
std::string string
Definition: nybbler.cc:12
void ReadXYZFile(const std::string &filename, XYZFieldMap &xyzmap, const float unitFactor)
std::vector< MagneticFieldDescription > fFieldDescriptions
Descriptions of the fields.
void ReadRZFile(const std::string &filename, RZFieldMap &rzmap)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
G4ThreeVector const mag::GArMagneticField::UniformFieldInVolume ( std::string const &  volName) const
override

Definition at line 218 of file GArMagneticField.cxx.

219 {
220  // if the input volume name is the same as the magnetized volume
221  // return the uniform field
222 
223  for(auto fd : fFieldDescriptions)
224  {
225  if(fd.fVolume.compare(volName) == 0)
226  return fd.fField;
227  }
228 
229  // if we get here, we can't find a field
230  return G4ThreeVector(0);
231 }
std::vector< MagneticFieldDescription > fFieldDescriptions
Descriptions of the fields.
MagFieldMode_t const& mag::GArMagneticField::UseField ( size_t  f) const
inlineoverride

Definition at line 42 of file GArMagneticField.h.

42 { return fFieldDescriptions[f].fMode; }
std::vector< MagneticFieldDescription > fFieldDescriptions
Descriptions of the fields.

Member Data Documentation

std::vector<MagneticFieldDescription> mag::GArMagneticField::fFieldDescriptions
private

Descriptions of the fields.

Definition at line 63 of file GArMagneticField.h.

float mag::GArMagneticField::fGlobalScaleFactor
private

Definition at line 62 of file GArMagneticField.h.

float mag::GArMagneticField::fUnitFactor
private

Definition at line 64 of file GArMagneticField.h.


The documentation for this class was generated from the following files: