EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
eASTMagneticField.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file eASTMagneticField.hh
1 // ********************************************************************
2 //
3 // eASTMagneticField.hh
4 // Header file of eAST Magnetic Field class
5 //
6 // History
7 // June 22nd, 2021 : first implementation
8 //
9 // ********************************************************************
10 
11 #ifndef eASTMagneticField_h
12 #define eASTMagneticField_h 1
13 
14 #include "G4MagneticField.hh"
15 #include "G4GenericMessenger.hh"
16 #include "G4SystemOfUnits.hh"
17 #include "G4UnitsTable.hh"
18 
19 #include <vector>
20 #include <array>
21 
22 class G4EquationOfMotion;
23 class G4MagIntegratorStepper;
24 class G4ChordFinder;
25 class G4FieldManager;
26 class G4PropagatorInField;
27 
29 
30  public:
31  eASTMagneticFieldMap(const G4String& name);
32  ~eASTMagneticFieldMap() = default;
33 
34  private:
35 
36  // Static maps to indices of neighboring points
37  static const int kLinearMap[8][3];
38  static const int kCubicMap[64][3];
39 
40  private:
41 
42  // Field name
43  G4String fName{""};
44 
45  public:
46 
47  // Load field map from filename
48  bool Load(const G4String& filename);
49 
50  // Get field value at point
51  void GetFieldValue(const G4double point[4], G4double *field) const {
52  field[0] = 0;
53  field[1] = 0;
54  field[2] = 0;
55  AddFieldValue(point, field);
56  };
57 
58  // Add field value at point
59  void AddFieldValue(const G4double point[4], G4double *field) const;
60 
61  // Print field value at point
62  void PrintFieldValue(const G4ThreeVector& point);
63 
64  private:
65 
66  // Field messenger
67  G4GenericMessenger fFieldMapMessenger;
68 
69  private:
70 
71  // File format
74 
75  private:
76 
77  // Map units and extent
78  double fFieldUnit{CLHEP::tesla};
79  std::array<double,3> fGridUnit{CLHEP::cm, CLHEP::cm, CLHEP::deg};
80  std::array<std::tuple<double,double,double>,3> fGridExtent; // min, max, spacing
81  std::array<unsigned int,3> fGridSize{0,0,0};
82 
83  public:
84 
85  // Map units and extent getters and setters
86  void SetFieldUnit(const G4String& unit) {
87  fFieldUnit = G4UnitDefinition::GetValueOf(unit);
88  }
89  void SetGridUnit(unsigned int i, const G4String& unit) {
90  if (i < fGridExtent.size()) {
91  fGridUnit[i] = G4UnitDefinition::GetValueOf(unit);
92  } else {
93  G4cerr << "ERROR: cannot set magnetic field grid unit" << G4endl;
94  }
95  }
96  void SetGridExtent(unsigned int i, const G4ThreeVector& extent) {
97  if (i < fGridExtent.size() && extent.x() < extent.y() && extent.z() > 0.0) {
98  fGridExtent[i] = std::make_tuple(extent.x(), extent.y(), extent.z());
99  } else {
100  G4cerr << "ERROR: cannot set magnetic field grid extent" << G4endl;
101  }
102  }
103 
104  private:
105 
106  // Map data
107  std::vector<std::vector<std::vector<std::vector<double>>>> fMap;
108 
109  private:
110 
111  // Interpolation type to allow for linear and cubic interpolation
114 
115  public:
116 
117  // Interpolation type setters and getters
118  void SetInterpolationType(const G4String& type) {
119  if (type == "linear") fInterpolationType = kLinear;
120  if (type == "cubic") fInterpolationType = kCubic;
121  }
123  return fInterpolationType;
124  }
125 
126  private:
127 
128  // Linear interpolation functions
129  double _linearInterpolate(const double p[2 << 0], double x) const {
130  return p[0] + x * (p[1] - p[0]);
131  }
132  double _bilinearInterpolate(const double p[2 << 1], const double x[2]) const {
133  double c[2];
134  c[0] = _linearInterpolate(&(p[0]), x[1]);
135  c[1] = _linearInterpolate(&(p[2]), x[1]);
136  return _linearInterpolate(c, x[0]);
137  }
138  double _trilinearInterpolate(const double p[2 << 2], const double x[3]) const {
139  double c[2];
140  c[0] = _bilinearInterpolate(&(p[0]), &(x[1]));
141  c[1] = _bilinearInterpolate(&(p[4]), &(x[1]));
142  return _linearInterpolate(c, x[0]);
143  }
144 
145  // Cubic interpolation functions
146  double _cubicInterpolate(const double p[4 << 0], double x) const {
147  return p[1] + 0.5 * x * (p[2] - p[0] +
148  x * (2. * p[0] - 5. * p[1] + 4. * p[2] - p[3] +
149  x * (3. * (p[1] - p[2]) + p[3] - p[0])));
150  }
151  double _bicubicInterpolate(const double p[4 << 1], const double x[2]) const {
152  double c[4];
153  c[0] = _cubicInterpolate(&(p[0]), x[1]);
154  c[1] = _cubicInterpolate(&(p[4]), x[1]);
155  c[2] = _cubicInterpolate(&(p[8]), x[1]);
156  c[3] = _cubicInterpolate(&(p[12]), x[1]);
157  return _cubicInterpolate(c, x[0]);
158  }
159  double _tricubicInterpolate(const double p[4 << 2], const double x[3]) const {
160  double c[4];
161  c[0] = _bicubicInterpolate(&(p[0]), &(x[1]));
162  c[1] = _bicubicInterpolate(&(p[16]), &(x[1]));
163  c[2] = _bicubicInterpolate(&(p[32]), &(x[1]));
164  c[3] = _bicubicInterpolate(&(p[48]), &(x[1]));
165  return _cubicInterpolate(c, x[0]);
166  }
167 
168 };
169 
170 class eASTMagneticField : public G4MagneticField {
171 
172  public:
173 
175  ~eASTMagneticField() = default;
176 
177  // Activate in ConstuctSDandField
178  void Activate();
179 
180  // Create new field
181  void CreateField(const G4String& name);
182 
183  // Get field value at point
184  void GetFieldValue(const G4double point[4], G4double *field) const {
185  field[0] = 0;
186  field[1] = 0;
187  field[2] = 0;
188  for (auto &map: fMaps) {
189  map.AddFieldValue(point, field);
190  }
191  };
192 
193  // Print field value at point
194  void PrintFieldValue(const G4ThreeVector& point) {
195  for (auto &map: fMaps) {
196  map.PrintFieldValue(point);
197  }
198  };
199 
200  private:
201 
202  // Field messenger
203  G4GenericMessenger fFieldMessenger;
204 
205  private:
206 
207  // Field maps
208  std::vector<eASTMagneticFieldMap> fMaps;
209 
210  private:
211 
212  G4double fMinStep{0.01*mm};
213  G4double fDeltaChord{3.0*mm};
214  G4double fDeltaOneStep{0.01*mm};
215  G4double fDeltaIntersection{0.1*mm};
216  G4double fEpsMin{1.0e-5*mm};
217  G4double fEpsMax{1.0e-4*mm};
218 
219  G4EquationOfMotion* fEquation{nullptr};
220  G4int fEquationDoF{0};
221  G4FieldManager* fFieldManager{nullptr};
222  G4PropagatorInField* fFieldPropagator{nullptr};
223  G4MagIntegratorStepper* fStepper{nullptr};
224  G4ChordFinder* fChordFinder{nullptr};
225 
226 };
227 
228 #endif