File indexing completed on 2024-09-27 07:02:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef eASTMagneticField_h
0012 #define eASTMagneticField_h 1
0013
0014 #include "G4MagneticField.hh"
0015 #include "G4GenericMessenger.hh"
0016 #include "G4SystemOfUnits.hh"
0017 #include "G4UnitsTable.hh"
0018
0019 #include <vector>
0020 #include <array>
0021
0022 class G4EquationOfMotion;
0023 class G4MagIntegratorStepper;
0024 class G4ChordFinder;
0025 class G4FieldManager;
0026 class G4PropagatorInField;
0027
0028 class eASTMagneticFieldMap {
0029
0030 public:
0031 eASTMagneticFieldMap(const G4String& name);
0032 ~eASTMagneticFieldMap() = default;
0033
0034 private:
0035
0036
0037 static const int kLinearMap[8][3];
0038 static const int kCubicMap[64][3];
0039
0040 private:
0041
0042
0043 G4String fName{""};
0044
0045 public:
0046
0047
0048 bool Load(const G4String& filename);
0049
0050
0051 void GetFieldValue(const G4double point[4], G4double *field) const {
0052 field[0] = 0;
0053 field[1] = 0;
0054 field[2] = 0;
0055 AddFieldValue(point, field);
0056 };
0057
0058
0059 void AddFieldValue(const G4double point[4], G4double *field) const;
0060
0061
0062 void PrintFieldValue(const G4ThreeVector& point);
0063
0064 private:
0065
0066
0067 G4GenericMessenger fFieldMapMessenger;
0068
0069 private:
0070
0071
0072 enum EFileFormat {kFileFormatUndefined, kFileFormatRZPhi, kFileFormatRZ};
0073 EFileFormat fFileFormat{kFileFormatUndefined};
0074
0075 private:
0076
0077
0078 double fFieldUnit{CLHEP::tesla};
0079 std::array<double,3> fGridUnit{CLHEP::cm, CLHEP::cm, CLHEP::deg};
0080 std::array<std::tuple<double,double,double>,3> fGridExtent;
0081 std::array<unsigned int,3> fGridSize{0,0,0};
0082
0083 public:
0084
0085
0086 void SetFieldUnit(const G4String& unit) {
0087 fFieldUnit = G4UnitDefinition::GetValueOf(unit);
0088 }
0089 void SetGridUnit(unsigned int i, const G4String& unit) {
0090 if (i < fGridExtent.size()) {
0091 fGridUnit[i] = G4UnitDefinition::GetValueOf(unit);
0092 } else {
0093 G4cerr << "ERROR: cannot set magnetic field grid unit" << G4endl;
0094 }
0095 }
0096 void SetGridExtent(unsigned int i, const G4ThreeVector& extent) {
0097 if (i < fGridExtent.size() && extent.x() < extent.y() && extent.z() > 0.0) {
0098 fGridExtent[i] = std::make_tuple(extent.x(), extent.y(), extent.z());
0099 } else {
0100 G4cerr << "ERROR: cannot set magnetic field grid extent" << G4endl;
0101 }
0102 }
0103
0104 private:
0105
0106
0107 std::vector<std::vector<std::vector<std::vector<double>>>> fMap;
0108
0109 private:
0110
0111
0112 enum EInterpolationType {kLinear, kCubic};
0113 EInterpolationType fInterpolationType{kLinear};
0114
0115 public:
0116
0117
0118 void SetInterpolationType(const G4String& type) {
0119 if (type == "linear") fInterpolationType = kLinear;
0120 if (type == "cubic") fInterpolationType = kCubic;
0121 }
0122 EInterpolationType GetInterpolationType() const {
0123 return fInterpolationType;
0124 }
0125
0126 private:
0127
0128
0129 double _linearInterpolate(const double p[2 << 0], double x) const {
0130 return p[0] + x * (p[1] - p[0]);
0131 }
0132 double _bilinearInterpolate(const double p[2 << 1], const double x[2]) const {
0133 double c[2];
0134 c[0] = _linearInterpolate(&(p[0]), x[1]);
0135 c[1] = _linearInterpolate(&(p[2]), x[1]);
0136 return _linearInterpolate(c, x[0]);
0137 }
0138 double _trilinearInterpolate(const double p[2 << 2], const double x[3]) const {
0139 double c[2];
0140 c[0] = _bilinearInterpolate(&(p[0]), &(x[1]));
0141 c[1] = _bilinearInterpolate(&(p[4]), &(x[1]));
0142 return _linearInterpolate(c, x[0]);
0143 }
0144
0145
0146 double _cubicInterpolate(const double p[4 << 0], double x) const {
0147 return p[1] + 0.5 * x * (p[2] - p[0] +
0148 x * (2. * p[0] - 5. * p[1] + 4. * p[2] - p[3] +
0149 x * (3. * (p[1] - p[2]) + p[3] - p[0])));
0150 }
0151 double _bicubicInterpolate(const double p[4 << 1], const double x[2]) const {
0152 double c[4];
0153 c[0] = _cubicInterpolate(&(p[0]), x[1]);
0154 c[1] = _cubicInterpolate(&(p[4]), x[1]);
0155 c[2] = _cubicInterpolate(&(p[8]), x[1]);
0156 c[3] = _cubicInterpolate(&(p[12]), x[1]);
0157 return _cubicInterpolate(c, x[0]);
0158 }
0159 double _tricubicInterpolate(const double p[4 << 2], const double x[3]) const {
0160 double c[4];
0161 c[0] = _bicubicInterpolate(&(p[0]), &(x[1]));
0162 c[1] = _bicubicInterpolate(&(p[16]), &(x[1]));
0163 c[2] = _bicubicInterpolate(&(p[32]), &(x[1]));
0164 c[3] = _bicubicInterpolate(&(p[48]), &(x[1]));
0165 return _cubicInterpolate(c, x[0]);
0166 }
0167
0168 };
0169
0170 class eASTMagneticField : public G4MagneticField {
0171
0172 public:
0173
0174 eASTMagneticField();
0175 ~eASTMagneticField() = default;
0176
0177
0178 void Activate();
0179
0180
0181 void CreateField(const G4String& name);
0182
0183
0184 void GetFieldValue(const G4double point[4], G4double *field) const {
0185 field[0] = 0;
0186 field[1] = 0;
0187 field[2] = 0;
0188 for (auto &map: fMaps) {
0189 map.AddFieldValue(point, field);
0190 }
0191 };
0192
0193
0194 void PrintFieldValue(const G4ThreeVector& point) {
0195 for (auto &map: fMaps) {
0196 map.PrintFieldValue(point);
0197 }
0198 };
0199
0200 private:
0201
0202
0203 G4GenericMessenger fFieldMessenger;
0204
0205 private:
0206
0207
0208 std::vector<eASTMagneticFieldMap> fMaps;
0209
0210 private:
0211
0212 G4double fMinStep{0.01*mm};
0213 G4double fDeltaChord{3.0*mm};
0214 G4double fDeltaOneStep{0.01*mm};
0215 G4double fDeltaIntersection{0.1*mm};
0216 G4double fEpsMin{1.0e-5*mm};
0217 G4double fEpsMax{1.0e-4*mm};
0218
0219 G4EquationOfMotion* fEquation{nullptr};
0220 G4int fEquationDoF{0};
0221 G4FieldManager* fFieldManager{nullptr};
0222 G4PropagatorInField* fFieldPropagator{nullptr};
0223 G4MagIntegratorStepper* fStepper{nullptr};
0224 G4ChordFinder* fChordFinder{nullptr};
0225
0226 };
0227
0228 #endif