1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
22 #include "AliMagWrapCheb.h"
27 const Double_t AliMagF::fgkSol2DipZ = -700.;
28 const Double_t AliMagF::fgkBMachineZ1 = 919.;
29 const Double_t AliMagF::fgkBMachineZ2 = -1972.;
31 //_______________________________________________________________________
37 fBeamType(kNoBeamField),
55 // Default constructor
59 //_______________________________________________________________________
60 AliMagF::AliMagF(const char *name, const char* title, Int_t integ,
61 Double_t factorSol, Double_t factorDip,
62 Double_t fmax, BMap_t maptype, const char* path,
63 BeamType_t bt, Double_t be, Bool_t compensator):
64 TVirtualMagField(name),
70 fCompensator(compensator),
77 fDipoleOFF(factorDip==0.),
88 if(integ<0 || integ > 2) {
89 AliWarning(Form("Invalid magnetic field flag: %5d; Helix tracking chosen instead",integ));
92 if (fInteg == 0) fPrecInteg = 0;
94 const char* parname = 0;
96 if (fMapType == k2kG) {
98 parname = fDipoleOFF ? "Sol12_Dip0_Hole":"Sol12_Dip6_Hole";
99 } else if (fMapType == k5kG) {
101 parname = fDipoleOFF ? "Sol30_Dip0_Hole":"Sol30_Dip6_Hole";
102 } else if (fMapType == k5kGUniform) {
104 parname = "Sol30_Dip6_Uniform";
106 AliFatal(Form("Unknown field identifier %d is requested\n",fMapType));
109 SetDataFileName(path);
110 SetParamName(parname);
112 SetFactorSol(factorSol);
113 SetFactorDip(factorDip);
114 LoadParameterization();
115 InitMachineField(fBeamType,fBeamEnergy);
118 //_______________________________________________________________________
119 AliMagF::AliMagF(const AliMagF &src):
120 TVirtualMagField(src),
122 fMapType(src.fMapType),
123 fSolenoid(src.fSolenoid),
124 fBeamType(src.fBeamType),
125 fBeamEnergy(src.fBeamEnergy),
126 fCompensator(src.fCompensator),
128 fPrecInteg(src.fPrecInteg),
129 fFactorSol(src.fFactorSol),
130 fFactorDip(src.fFactorDip),
132 fDipoleOFF(src.fDipoleOFF),
133 fQuadGradient(src.fQuadGradient),
134 fDipoleField(src.fDipoleField),
135 fCCorrField(src.fCCorrField),
136 fACorr1Field(src.fACorr1Field),
137 fACorr2Field(src.fACorr2Field),
138 fParNames(src.fParNames)
140 if (src.fMeasuredMap) fMeasuredMap = new AliMagWrapCheb(*src.fMeasuredMap);
143 //_______________________________________________________________________
149 //_______________________________________________________________________
150 Bool_t AliMagF::LoadParameterization()
153 AliError(Form("Field data %s are already loaded from %s\n",GetParamName(),GetDataFileName()));
157 char* fname = gSystem->ExpandPathName(GetDataFileName());
158 TFile* file = TFile::Open(fname);
160 AliError(Form("Failed to open magnetic field data file %s\n",fname));
164 fMeasuredMap = dynamic_cast<AliMagWrapCheb*>(file->Get(GetParamName()));
166 AliError(Form("Did not find field %s in %s\n",GetParamName(),fname));
175 //_______________________________________________________________________
176 void AliMagF::Field(const Double_t *xyz, Double_t *b)
178 // Method to calculate the field at point xyz
181 if (xyz[2] > fgkBMachineZ1 || xyz[2] < fgkBMachineZ2) MachineField(xyz, b);
182 else if (fMeasuredMap) {
183 fMeasuredMap->Field(xyz,b);
184 if (xyz[2]>fgkSol2DipZ || fDipoleOFF) for (int i=3;i--;) b[i] *= fFactorSol;
185 else for (int i=3;i--;) b[i] *= fFactorDip;
190 //_______________________________________________________________________
191 Double_t AliMagF::GetBz(const Double_t *xyz) const
193 // Method to calculate the field at point xyz
195 if (xyz[2] <= fgkBMachineZ1 && xyz[2] >= fgkBMachineZ2) return fMeasuredMap->GetBz(xyz);
197 double b[3] = {0,0,0};
198 MachineField(xyz, b);
204 //_______________________________________________________________________
205 AliMagF& AliMagF::operator=(const AliMagF& src)
207 if (this != &src && src.fMeasuredMap) {
208 if (fMeasuredMap) delete fMeasuredMap;
209 fMeasuredMap = new AliMagWrapCheb(*src.fMeasuredMap);
210 SetName(src.GetName());
211 fSolenoid = src.fSolenoid;
212 fBeamType = src.fBeamType;
213 fBeamEnergy = src.fBeamEnergy;
214 fCompensator = src.fCompensator;
216 fPrecInteg = src.fPrecInteg;
217 fFactorSol = src.fFactorSol;
218 fFactorDip = src.fFactorDip;
220 fDipoleOFF = src.fDipoleOFF;
221 fParNames = src.fParNames;
226 //_______________________________________________________________________
227 void AliMagF::InitMachineField(BeamType_t btype, Double_t benergy)
229 const double kToler = 0.1;
230 if (btype==kNoBeamField) {
231 fQuadGradient = fDipoleField = fCCorrField = fACorr1Field = fACorr2Field = 0.;
234 else if (btype==kBeamTypepp && TMath::Abs(1.-benergy/5000.)<kToler ){
236 fQuadGradient = 15.7145;
237 fDipoleField = 27.0558;
239 fCCorrField = 9.7017;
241 fACorr1Field = -13.2143;
242 fACorr2Field = -11.9909;
243 } else if (btype == kBeamTypepp && TMath::Abs(1.-benergy/450.)<kToler) {
245 Double_t const kEnergyRatio = benergy / 7000.;
246 fQuadGradient = 22.0002 * kEnergyRatio;
247 fDipoleField = 37.8781 * kEnergyRatio;
249 fCCorrField = 9.6908;
251 fACorr1Field = -13.2014;
252 fACorr2Field = -9.6908;
253 } else if ( (btype == kBeamTypepp && TMath::Abs(1.-benergy/7000.)<kToler) ||
254 (fBeamType == kBeamTypeAA) ) {
255 // Pb-Pb @ 2.7+2.7 TeV or p-p @ 7+7 TeV
256 fQuadGradient = 22.0002;
257 fDipoleField = 37.8781;
259 fCCorrField = 9.6908;
261 fACorr1Field = -13.2014;
262 fACorr2Field = -9.6908;
267 //_______________________________________________________________________
268 void AliMagF::MachineField(const Double_t *x, Double_t *b) const
270 // ---- This is the ZDC part
271 const Double_t kCCorrBegin = fgkBMachineZ2-0.5,kCCorrEnd = kCCorrBegin - 153., kCCorrSqRadius = 4.5*4.5;
273 const Double_t kCTripletBegin = -2296.5;
274 const Double_t kCQ1Begin = kCTripletBegin, kCQ1End = kCQ1Begin-637., kCQ1SqRadius = 3.5*3.5;
275 const Double_t kCQ2Begin = kCTripletBegin-908.5, kCQ2End = kCQ2Begin-550., kCQ2SqRadius = 3.5*3.5;
276 const Double_t kCQ3Begin = kCTripletBegin-1558.5, kCQ3End = kCQ3Begin-550., kCQ3SqRadius = 3.5*3.5;
277 const Double_t kCQ4Begin = kCTripletBegin-2400., kCQ4End = kCQ4Begin-637., kCQ4SqRadius = 3.5*3.5;
279 const Double_t kCD1Begin = -5838.3, kCD1End = kCD1Begin-945., kCD1SqRadius = 4.5*4.5;
280 const Double_t kCD2Begin = -12167.8, kCD2End = kCD2Begin-945., kCD2SqRadius = 4.5*4.5;
281 const Double_t kCD2XCentre1 = -9.7;
282 const Double_t kCD2XCentre2 = 9.7;
285 // NB -> kACorr1Begin = 919. to be checked
286 const Double_t kACorr1Begin = fgkBMachineZ1, kACorr1End = kACorr1Begin+260., kCCorr1SqRadius = 4.*4.;
287 const Double_t kACorr2Begin = -fgkBMachineZ2 + 0.5, kACorr2End = kACorr2Begin+153., kCCorr2SqRadius = 4.5*4.5;
288 const Double_t kATripletBegin = 2296.5;
289 const Double_t kAQ1Begin = kATripletBegin, kAQ1End = kAQ1Begin+637., kAQ1SqRadius = 3.5*3.5;
290 const Double_t kAQ2Begin = kATripletBegin+908.5, kAQ2End = kAQ2Begin+550., kAQ2SqRadius = 3.5*3.5;
291 const Double_t kAQ3Begin = kATripletBegin+1558.5, kAQ3End = kAQ3Begin+550., kAQ3SqRadius = 3.5*3.5;
292 const Double_t kAQ4Begin = kATripletBegin+2400., kAQ4End = kAQ4Begin+637., kAQ4SqRadius = 3.5*3.5;
294 const Double_t kAD1Begin = 5838.3, kAD1End = kAD1Begin+945., kAD1SqRadius = 3.375*3.375;
295 const Double_t kAD2Begin = 12167.8, kAD2End = kAD2Begin+945., kAD2SqRadius = 3.75*3.75;
296 const Double_t kAD2XCentre1 = -9.4;
297 const Double_t kAD2XCentre2 = 9.4;
299 double rad2 = x[0] * x[0] + x[1] * x[1];
301 // SIDE C **************************************************
303 if(x[2] < kCCorrBegin && x[2] > kCCorrEnd && rad2 < kCCorrSqRadius){
308 else if(x[2] < kCQ1Begin && x[2] > kCQ1End && rad2 < kCQ1SqRadius){
309 b[0] = fQuadGradient*x[1];
310 b[1] = fQuadGradient*x[0];
313 else if(x[2] < kCQ2Begin && x[2] > kCQ2End && rad2 < kCQ2SqRadius){
314 b[0] = -fQuadGradient*x[1];
315 b[1] = -fQuadGradient*x[0];
318 else if(x[2] < kCQ3Begin && x[2] > kCQ3End && rad2 < kCQ3SqRadius){
319 b[0] = -fQuadGradient*x[1];
320 b[1] = -fQuadGradient*x[0];
323 else if(x[2] < kCQ4Begin && x[2] > kCQ4End && rad2 < kCQ4SqRadius){
324 b[0] = fQuadGradient*x[1];
325 b[1] = fQuadGradient*x[0];
328 else if(x[2] < kCD1Begin && x[2] > kCD1End && rad2 < kCD1SqRadius){
333 else if(x[2] < kCD2Begin && x[2] > kCD2End){
334 if(((x[0]-kCD2XCentre1)*(x[0]-kCD2XCentre1)+(x[1]*x[1]))<kCD2SqRadius
335 || ((x[0]-kCD2XCentre2)*(x[0]-kCD2XCentre2)+(x[1]*x[1]))<kCD2SqRadius){
336 b[1] = -fDipoleField;
343 // SIDE A **************************************************
345 if(fCompensator && (x[2] > kACorr1Begin && x[2] < kACorr1End) && rad2 < kCCorr1SqRadius) {
346 // Compensator magnet at z = 1075 m
353 if(x[2] > kACorr2Begin && x[2] < kACorr2End && rad2 < kCCorr2SqRadius){
358 else if(x[2] > kAQ1Begin && x[2] < kAQ1End && rad2 < kAQ1SqRadius){
359 // First quadrupole of inner triplet de-focussing in x-direction
360 b[0] = -fQuadGradient*x[1];
361 b[1] = -fQuadGradient*x[0];
364 else if(x[2] > kAQ2Begin && x[2] < kAQ2End && rad2 < kAQ2SqRadius){
365 b[0] = fQuadGradient*x[1];
366 b[1] = fQuadGradient*x[0];
369 else if(x[2] > kAQ3Begin && x[2] < kAQ3End && rad2 < kAQ3SqRadius){
370 b[0] = fQuadGradient*x[1];
371 b[1] = fQuadGradient*x[0];
374 else if(x[2] > kAQ4Begin && x[2] < kAQ4End && rad2 < kAQ4SqRadius){
375 b[0] = -fQuadGradient*x[1];
376 b[1] = -fQuadGradient*x[0];
379 else if(x[2] > kAD1Begin && x[2] < kAD1End && rad2 < kAD1SqRadius){
381 b[1] = -fDipoleField;
384 else if(x[2] > kAD2Begin && x[2] < kAD2End){
385 if(((x[0]-kAD2XCentre1)*(x[0]-kAD2XCentre1)+(x[1]*x[1])) < kAD2SqRadius
386 || ((x[0]-kAD2XCentre2)*(x[0]-kAD2XCentre2)+(x[1]*x[1])) < kAD2SqRadius){
393 //_______________________________________________________________________
394 void AliMagF::GetTPCInt(const Double_t *xyz, Double_t *b) const
396 // Method to calculate the integral of magnetic integral from xyz to nearest cathode plane
399 fMeasuredMap->GetTPCInt(xyz,b);
400 for (int i=3;i--;) b[i] *= fFactorSol;
404 //_______________________________________________________________________
405 void AliMagF::GetTPCIntCyl(const Double_t *rphiz, Double_t *b) const
407 // Method to calculate the integral of magnetic integral from point to nearest cathode plane
408 // in cylindrical coordiates ( -pi<phi<pi convention )
411 fMeasuredMap->GetTPCIntCyl(rphiz,b);
412 for (int i=3;i--;) b[i] *= fFactorSol;