-
Notifications
You must be signed in to change notification settings - Fork 499
Expand file tree
/
Copy pathMagneticField.h
More file actions
287 lines (214 loc) · 10.5 KB
/
MagneticField.h
File metadata and controls
287 lines (214 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
/// \file MagneticField.h
/// \brief Definition of the MagF class
/// \author ruben.shahoyan@cern.ch
#ifndef ALICEO2_FIELD_MAGNETICFIELD_H_
#define ALICEO2_FIELD_MAGNETICFIELD_H_
#include "FairField.h" // for FairField
#include "Field/MagFieldParam.h"
#include "Field/MagneticWrapperChebyshev.h" // for MagneticWrapperChebyshev
#include "Field/MagFieldFast.h"
#include "TSystem.h"
#include "Rtypes.h" // for Double_t, Char_t, Int_t, Float_t, etc
#include "TNamed.h" // for TNamed
#include <memory> // for str::unique_ptr
class FairParamList;
namespace o2
{
namespace field
{
class MagneticWrapperChebyshev;
}
} // namespace o2
namespace o2
{
namespace field
{
/// Interface between the TVirtualMagField and MagneticWrapperChebyshev: wrapper to the set of magnetic field data +
/// Tosca
/// parametrization by Chebyshev polynomials
class MagneticField : public FairField
{
public:
enum PolarityConvention_t { kConvLHC,
kConvDCS2008,
kConvMap2005 };
enum { kOverrideGRP = BIT(14) }; // don't recreate from GRP if set
/// Default constructor
MagneticField();
/// Initialize the field with Geant integration option "integ" and max field "fmax",
/// Impose scaling of parameterized L3 field by factorSol and of dipole by factorDip.
/// The "be" is the energy of the beam in GeV/nucleon
MagneticField(const char* name, const char* title, Double_t factorSol = 1., Double_t factorDip = 1.,
MagFieldParam::BMap_t maptype = MagFieldParam::k5kG,
MagFieldParam::BeamType_t btype = MagFieldParam::kBeamTypepp, Double_t benergy = -1, Int_t integ = 2,
Double_t fmax = 15, const std::string path = "$(O2_ROOT)/share/Common/maps/mfchebKGI_sym.root");
MagneticField(const MagFieldParam& param);
MagneticField& operator=(const MagneticField& src);
/// Default destructor
~MagneticField() override = default;
/// create field from rounded value, i.e. +-5 or +-2 kGauss
static MagneticField* createNominalField(int fld, bool uniform = false);
/// real field creation is here
void CreateField();
/// allow fast field param
void AllowFastField(bool v = true);
bool fastFieldExists() const
{
return !(mMapType == MagFieldParam::k5kGUniform || mDipoleOnOffFlag == true);
}
void rescaleField(float l3Cur, float diCur, bool uniform, int convention = 0);
/// Virtual methods from FairField
/// X component, avoid using since slow
Double_t GetBx(Double_t x, Double_t y, Double_t z) override
{
double xyz[3] = {x, y, z}, b[3];
MagneticField::Field(xyz, b);
return b[0];
}
/// Y component, avoid using since slow
Double_t GetBy(Double_t x, Double_t y, Double_t z) override
{
double xyz[3] = {x, y, z}, b[3];
MagneticField::Field(xyz, b);
return b[1];
}
/// Z component
Double_t GetBz(Double_t x, Double_t y, Double_t z) override
{
double xyz[3] = {x, y, z};
return getBz(xyz);
}
/// Method to calculate the field at point xyz
/// Main interface from TVirtualMagField used in simulation
void Field(const Double_t* __restrict__ point, Double_t* __restrict__ bField) override;
void field(const math_utils::Point3D<float> xyz, float bxyz[3])
{
double xyzd[3] = {xyz.X(), xyz.Y(), xyz.Z()}, bxyzd[3] = {0};
Field(xyzd, bxyzd);
bxyz[0] = bxyzd[0];
bxyz[1] = bxyzd[1];
bxyz[2] = bxyzd[2];
}
void field(const math_utils::Point3D<double> xyz, double bxyz[3])
{
double xyzd[3] = {xyz.X(), xyz.Y(), xyz.Z()};
Field(xyzd, bxyz);
}
void field(const double* __restrict__ point, double* __restrict__ bField)
{
Field(point, bField);
}
void field(const float* __restrict__ point, float* __restrict__ bField)
{
double xyz[3] = {point[0], point[1], point[2]}, bxyz[3] = {0};
Field(xyz, bxyz);
bField[0] = bxyz[0];
bField[1] = bxyz[1];
bField[2] = bxyz[2];
}
/// 3d field query alias for Alias Method to calculate the field at point xyz
void GetBxyz(const Double_t p[3], Double_t* b) override { MagneticField::Field(p, b); }
/// Fill Paramater
void FillParContainer() override;
/// Method to calculate the integral_0^z of br,bt,bz
void getTPCIntegral(const Double_t* xyz, Double_t* b) const;
/// Method to calculate the integral_0^z of br,bt,bz
void getTPCRatIntegral(const Double_t* xyz, Double_t* b) const;
/// Method to calculate the integral_0^z of br,bt,bz in cylindrical coordinates ( -pi<phi<pi convention )
void getTPCIntegralCylindrical(const Double_t* rphiz, Double_t* b) const;
/// Method to calculate the integral_0^z of bx/bz,by/bz and (bx/bz)^2+(by/bz)^2 in
/// cylindrical coordinates ( -pi<phi<pi convention )
void getTPCRatIntegralCylindrical(const Double_t* rphiz, Double_t* b) const;
/// Method to calculate the field at point xyz
Double_t getBz(const Double_t* xyz) const;
MagneticWrapperChebyshev* getMeasuredMap() const { return mMeasuredMap.get(); }
/// get fast field direct pointer
const MagFieldFast* getFastField() const { return mFastField.get(); }
// Former MagF methods or their aliases
/// Sets the sign/scale of the current in the L3 according to sPolarityConvention
void setFactorSolenoid(float fc = 1.);
/// Sets the sign*scale of the current in the Dipole according to sPolarityConvention
void setFactorDipole(float fc = 1.);
/// Returns the sign*scale of the current in the Dipole according to sPolarityConventionthe
Double_t getFactorSolenoid() const;
/// Return the sign*scale of the current in the Dipole according to sPolarityConventionthe
Double_t getFactorDipole() const;
Double_t Factor() const { return getFactorSolenoid(); }
Double_t getCurrentSolenoid() const
{
return getFactorSolenoid() * (mMapType == MagFieldParam::k2kG ? 12000 : 30000);
}
Double_t getCurrentDipole() const { return getFactorDipole() * 6000; }
Bool_t IsUniform() const { return mMapType == MagFieldParam::k5kGUniform; }
void MachineField(const Double_t* __restrict__ x, Double_t* __restrict__ b) const;
MagFieldParam::BMap_t getMapType() const { return mMapType; }
MagFieldParam::BeamType_t getBeamType() const { return mBeamType; }
/// Returns beam type in text form
const char* getBeamTypeText() const;
Double_t getBeamEnergy() const { return mBeamEnergy; }
Double_t Max() const { return mMaxField; }
Int_t Integral() const { return mDefaultIntegration; }
Int_t precIntegral() const { return mPrecisionInteg; }
Double_t solenoidField() const { return mSolenoid; }
Char_t* getDataFileName() const { return (Char_t*)mParameterNames.GetName(); }
Char_t* getParameterName() const { return (Char_t*)mParameterNames.GetTitle(); }
void setDataFileName(const Char_t* nm) { mParameterNames.SetName(nm); }
void setParameterName(const Char_t* nm) { mParameterNames.SetTitle(nm); }
/// Prints short or long info
void Print(Option_t* opt) const override;
Bool_t loadParameterization();
static Int_t getPolarityConvention() { return Int_t(sPolarityConvention); }
static MagFieldParam::BMap_t getFieldMapScale(float& l3, float& dip, bool uniform, int convention = 0);
/// The magnetic field map, defined externally...
/// L3 current 30000 A -> 0.5 T
/// L3 current 12000 A -> 0.2 T
/// dipole current 6000 A
/// The polarities must match the convention (LHC or DCS2008)
/// unless the special uniform map was used for MC
static MagneticField* createFieldMap(float l3Current = -30000., float diCurrent = -6000., Int_t convention = 0,
Bool_t uniform = kFALSE, float beamenergy = 7000, const Char_t* btype = "pp",
const std::string path = std::string(gSystem->Getenv("VMCWORKDIR")) +
std::string("/Common/maps/mfchebKGI_sym.root"));
protected:
// not supposed to be changed during the run, set only at the initialization via constructor
void initializeMachineField(MagFieldParam::BeamType_t btype, Double_t benergy);
void setBeamType(MagFieldParam::BeamType_t type) { mBeamType = type; }
void setBeamEnergy(float energy) { mBeamEnergy = energy; }
private:
std::unique_ptr<MagneticWrapperChebyshev> mMeasuredMap; //! Measured part of the field map
std::unique_ptr<MagFieldFast> mFastField; // ! optional fast parametrization
MagFieldParam::BMap_t mMapType; ///< field map type
Double_t mSolenoid; ///< Solenoid field setting
MagFieldParam::BeamType_t mBeamType; ///< Beam type: A-A (mBeamType=0) or p-p (mBeamType=1)
Double_t mBeamEnergy; ///< Beam energy in GeV
Int_t mDefaultIntegration; ///< Default integration method as indicated in Geant
Int_t mPrecisionInteg; ///< Alternative integration method, e.g. for higher precision
Double_t mMultipicativeFactorSolenoid; ///< Multiplicative factor for solenoid
Double_t mMultipicativeFactorDipole; ///< Multiplicative factor for dipole
Double_t mMaxField; ///< Max Field as indicated in Geant
Bool_t mDipoleOnOffFlag; ///< Dipole ON/OFF flag
Double_t mQuadrupoleGradient; ///< Gradient field for inner triplet quadrupoles
Double_t mDipoleField; ///< Field value for D1 and D2 dipoles
Double_t mCompensatorField2C; ///< Side C 2nd compensator field
Double_t mCompensatorField1A; ///< Side A 1st compensator field
Double_t mCompensatorField2A; ///< Side A 2nd compensator field
TNamed mParameterNames; ///< file and parameterization loaded
static const Double_t sSolenoidToDipoleZ; ///< conventional Z of transition from L3 to Dipole field
static const UShort_t sPolarityConvention; ///< convention for the mapping of the curr.sign on main component sign
MagneticField(const MagneticField& src);
ClassDefOverride(o2::field::MagneticField,
3) // Class for all Alice MagField wrapper for measured data + Tosca parameterization
};
} // namespace field
} // namespace o2
#endif