]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliMagF.cxx
pythia8130 distributed with AliRoot
[u/mrichter/AliRoot.git] / STEER / AliMagF.cxx
CommitLineData
4c039060 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
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 **************************************************************************/
15
4c039060 16
db83d72f 17#include <TClass.h>
18#include <TFile.h>
19#include <TSystem.h>
fe4da5cc 20
21#include "AliMagF.h"
db83d72f 22#include "AliMagWrapCheb.h"
23#include "AliLog.h"
972ca52f 24
fe4da5cc 25ClassImp(AliMagF)
26
9251fceb 27const Double_t AliMagF::fgkSol2DipZ = -700.;
1dd3d90e 28const UShort_t AliMagF::fgkPolarityConvention = kConvLHC;
db83d72f 29
1dd3d90e 30/*
31 Explanation for polarity conventions: these are the mapping between the
32 current signs and main field components in L3 (Bz) and Dipole (Bx) (in Alice frame)
33 1) kConvMap2005: used for the field mapping in 2005
34 positive L3 current -> negative Bz
35 positive Dip current -> positive Bx
36 2) kConvMapDCS2008: defined by the microswitches/cabling of power converters as of 2008 - 1st half 2009
37 positive L3 current -> positive Bz
38 positive Dip current -> positive Bx
39 3) kConvLHC : defined by LHC
40 positive L3 current -> negative Bz
41 positive Dip current -> negative Bx
42
43 Note: only "negative Bz(L3) with postive Bx(Dipole)" and its inverse was mapped in 2005. Hence
44 the GRP Manager will reject the runs with the current combinations (in the convention defined by the
45 static Int_t AliMagF::GetPolarityConvention()) which do not lead to such field polarities.
46*/
e2afb3b6 47//_______________________________________________________________________
48AliMagF::AliMagF():
db83d72f 49 TVirtualMagField(),
50 fMeasuredMap(0),
51 fMapType(k5kG),
52 fSolenoid(0),
53 fBeamType(kNoBeamField),
54 fBeamEnergy(0),
db83d72f 55 //
e2afb3b6 56 fInteg(0),
db83d72f 57 fPrecInteg(0),
58 fFactorSol(1.),
59 fFactorDip(1.),
60 fMax(15),
61 fDipoleOFF(kFALSE),
e2afb3b6 62 //
db83d72f 63 fQuadGradient(0),
64 fDipoleField(0),
65 fCCorrField(0),
66 fACorr1Field(0),
67 fACorr2Field(0),
68 fParNames("","")
69{
e2afb3b6 70 // Default constructor
71 //
72}
73
74//_______________________________________________________________________
db83d72f 75AliMagF::AliMagF(const char *name, const char* title, Int_t integ,
76 Double_t factorSol, Double_t factorDip,
77 Double_t fmax, BMap_t maptype, const char* path,
9251fceb 78 BeamType_t bt, Double_t be):
db83d72f 79 TVirtualMagField(name),
80 fMeasuredMap(0),
81 fMapType(maptype),
82 fSolenoid(0),
83 fBeamType(bt),
84 fBeamEnergy(be),
db83d72f 85 //
86 fInteg(integ),
604e0531 87 fPrecInteg(1),
db83d72f 88 fFactorSol(1.),
89 fFactorDip(1.),
972ca52f 90 fMax(fmax),
db83d72f 91 fDipoleOFF(factorDip==0.),
92 //
93 fQuadGradient(0),
94 fDipoleField(0),
95 fCCorrField(0),
96 fACorr1Field(0),
97 fACorr2Field(0),
98 fParNames("","")
fe4da5cc 99{
9251fceb 100 // Initialize the field with Geant integration option "integ" and max field "fmax,
101 // Impose scaling of parameterized L3 field by factorSol and of dipole by factorDip.
102 // The "be" is the energy of the beam in GeV/nucleon
aee8290b 103 //
db83d72f 104 SetTitle(title);
105 if(integ<0 || integ > 2) {
106 AliWarning(Form("Invalid magnetic field flag: %5d; Helix tracking chosen instead",integ));
107 fInteg = 2;
108 }
109 if (fInteg == 0) fPrecInteg = 0;
aee8290b 110 //
db83d72f 111 const char* parname = 0;
112 //
f04e7f5f 113 if (fMapType == k2kG) parname = fDipoleOFF ? "Sol12_Dip0_Hole":"Sol12_Dip6_Hole";
114 else if (fMapType == k5kG) parname = fDipoleOFF ? "Sol30_Dip0_Hole":"Sol30_Dip6_Hole";
115 else if (fMapType == k5kGUniform) parname = "Sol30_Dip6_Uniform";
116 else AliFatal(Form("Unknown field identifier %d is requested\n",fMapType));
db83d72f 117 //
118 SetDataFileName(path);
119 SetParamName(parname);
120 //
db83d72f 121 LoadParameterization();
122 InitMachineField(fBeamType,fBeamEnergy);
f04e7f5f 123 double xyz[3]={0.,0.,0.};
124 fSolenoid = GetBz(xyz);
125 SetFactorSol(factorSol);
126 SetFactorDip(factorDip);
e86708b3 127 AliInfo(Form("Alice B fields: Solenoid (%+.2f*)%.0f kG, Dipole %s (%+.2f) %s",
128 factorSol,(fMapType==k5kG||fMapType==k5kGUniform)?5.:2.,
439b5096 129 fDipoleOFF ? "OFF":"ON",factorDip,fMapType==k5kGUniform?" |Constant Field!":""));
130 AliInfo(Form("Machine B fields for %s beam (%.0f GeV): QGrad: %.4f Dipole: %.4f",
131 bt==kBeamTypeAA ? "A-A":(bt==kBeamTypepp ? "p-p":"OFF"),be,fQuadGradient,fDipoleField));
fe4da5cc 132}
133
eeda4611 134//_______________________________________________________________________
135AliMagF::AliMagF(const AliMagF &src):
db83d72f 136 TVirtualMagField(src),
137 fMeasuredMap(0),
138 fMapType(src.fMapType),
139 fSolenoid(src.fSolenoid),
140 fBeamType(src.fBeamType),
141 fBeamEnergy(src.fBeamEnergy),
eeda4611 142 fInteg(src.fInteg),
143 fPrecInteg(src.fPrecInteg),
db83d72f 144 fFactorSol(src.fFactorSol),
145 fFactorDip(src.fFactorDip),
eeda4611 146 fMax(src.fMax),
db83d72f 147 fDipoleOFF(src.fDipoleOFF),
148 fQuadGradient(src.fQuadGradient),
149 fDipoleField(src.fDipoleField),
150 fCCorrField(src.fCCorrField),
151 fACorr1Field(src.fACorr1Field),
152 fACorr2Field(src.fACorr2Field),
153 fParNames(src.fParNames)
eeda4611 154{
db83d72f 155 if (src.fMeasuredMap) fMeasuredMap = new AliMagWrapCheb(*src.fMeasuredMap);
eeda4611 156}
157
e2afb3b6 158//_______________________________________________________________________
db83d72f 159AliMagF::~AliMagF()
ff66b122 160{
db83d72f 161 delete fMeasuredMap;
162}
163
164//_______________________________________________________________________
165Bool_t AliMagF::LoadParameterization()
166{
167 if (fMeasuredMap) {
168 AliError(Form("Field data %s are already loaded from %s\n",GetParamName(),GetDataFileName()));
169 return kTRUE;
170 }
ff66b122 171 //
db83d72f 172 char* fname = gSystem->ExpandPathName(GetDataFileName());
173 TFile* file = TFile::Open(fname);
174 if (!file) {
175 AliError(Form("Failed to open magnetic field data file %s\n",fname));
176 return kFALSE;
177 }
ff66b122 178 //
db83d72f 179 fMeasuredMap = dynamic_cast<AliMagWrapCheb*>(file->Get(GetParamName()));
180 if (!fMeasuredMap) {
181 AliError(Form("Did not find field %s in %s\n",GetParamName(),fname));
182 return kFALSE;
183 }
184 file->Close();
185 delete file;
186 return kTRUE;
ff66b122 187}
188
db83d72f 189
ff66b122 190//_______________________________________________________________________
db83d72f 191void AliMagF::Field(const Double_t *xyz, Double_t *b)
fe4da5cc 192{
db83d72f 193 // Method to calculate the field at point xyz
aee8290b 194 //
9251fceb 195 // b[0]=b[1]=b[2]=0.0;
196 if (fMeasuredMap && xyz[2]>fMeasuredMap->GetMinZ() && xyz[2]<fMeasuredMap->GetMaxZ()) {
db83d72f 197 fMeasuredMap->Field(xyz,b);
198 if (xyz[2]>fgkSol2DipZ || fDipoleOFF) for (int i=3;i--;) b[i] *= fFactorSol;
9251fceb 199 else for (int i=3;i--;) b[i] *= fFactorDip;
db83d72f 200 }
9251fceb 201 else MachineField(xyz, b);
aee8290b 202 //
fe4da5cc 203}
eeda4611 204
205//_______________________________________________________________________
db83d72f 206Double_t AliMagF::GetBz(const Double_t *xyz) const
eeda4611 207{
db83d72f 208 // Method to calculate the field at point xyz
209 //
9251fceb 210 if (fMeasuredMap && xyz[2]>fMeasuredMap->GetMinZ() && xyz[2]<fMeasuredMap->GetMaxZ()) {
211 double bz = fMeasuredMap->GetBz(xyz);
212 return (xyz[2]>fgkSol2DipZ || fDipoleOFF) ? bz*fFactorSol : bz*fFactorDip;
db83d72f 213 }
9251fceb 214 else return 0.;
eeda4611 215}
216
217//_______________________________________________________________________
db83d72f 218AliMagF& AliMagF::operator=(const AliMagF& src)
eeda4611 219{
db83d72f 220 if (this != &src && src.fMeasuredMap) {
221 if (fMeasuredMap) delete fMeasuredMap;
222 fMeasuredMap = new AliMagWrapCheb(*src.fMeasuredMap);
223 SetName(src.GetName());
224 fSolenoid = src.fSolenoid;
225 fBeamType = src.fBeamType;
226 fBeamEnergy = src.fBeamEnergy;
db83d72f 227 fInteg = src.fInteg;
228 fPrecInteg = src.fPrecInteg;
229 fFactorSol = src.fFactorSol;
230 fFactorDip = src.fFactorDip;
231 fMax = src.fMax;
232 fDipoleOFF = src.fDipoleOFF;
233 fParNames = src.fParNames;
234 }
235 return *this;
eeda4611 236}
237
238//_______________________________________________________________________
db83d72f 239void AliMagF::InitMachineField(BeamType_t btype, Double_t benergy)
eeda4611 240{
9251fceb 241 if (btype==kNoBeamField || benergy<1.) {
db83d72f 242 fQuadGradient = fDipoleField = fCCorrField = fACorr1Field = fACorr2Field = 0.;
9251fceb 243 return;
db83d72f 244 }
245 //
9251fceb 246 double rigScale = benergy/7000.; // scale according to ratio of E/Enominal
247 // for ions assume PbPb (with energy provided per nucleon) and account for A/Z
248 if (btype == kBeamTypeAA) rigScale *= 208./82.;
249 //
250 fQuadGradient = 22.0002*rigScale;
251 fDipoleField = 37.8781*rigScale;
252 //
253 // SIDE C
254 fCCorrField = -9.6980;
255 // SIDE A
256 fACorr1Field = -13.2247;
257 fACorr2Field = 11.7905;
db83d72f 258 //
eeda4611 259}
eed8a1a2 260
db83d72f 261//_______________________________________________________________________
262void AliMagF::MachineField(const Double_t *x, Double_t *b) const
eed8a1a2 263{
db83d72f 264 // ---- This is the ZDC part
9251fceb 265 // Compansators for Alice Muon Arm Dipole
266 const Double_t kBComp1CZ = 1075., kBComp1hDZ = 260./2., kBComp1SqR = 4.0*4.0;
267 const Double_t kBComp2CZ = 2049., kBComp2hDZ = 153./2., kBComp2SqR = 4.5*4.5;
268 //
269 const Double_t kTripQ1CZ = 2615., kTripQ1hDZ = 637./2., kTripQ1SqR = 3.5*3.5;
90ae20c9 270 const Double_t kTripQ2CZ = 3480., kTripQ2hDZ = 550./2., kTripQ2SqR = 3.5*3.5;
9251fceb 271 const Double_t kTripQ3CZ = 4130., kTripQ3hDZ = 550./2., kTripQ3SqR = 3.5*3.5;
272 const Double_t kTripQ4CZ = 5015., kTripQ4hDZ = 637./2., kTripQ4SqR = 3.5*3.5;
db83d72f 273 //
9251fceb 274 const Double_t kDip1CZ = 6310.8, kDip1hDZ = 945./2., kDip1SqRC = 4.5*4.5, kDip1SqRA = 3.375*3.375;
275 const Double_t kDip2CZ = 12640.3, kDip2hDZ = 945./2., kDip2SqRC = 4.5*4.5, kDip2SqRA = 3.75*3.75;
276 const Double_t kDip2DXC = 9.7, kDip2DXA = 9.4;
db83d72f 277 //
278 double rad2 = x[0] * x[0] + x[1] * x[1];
279 //
9251fceb 280 b[0] = b[1] = b[2] = 0;
281 //
db83d72f 282 // SIDE C **************************************************
283 if(x[2]<0.){
9251fceb 284 if(TMath::Abs(x[2]+kBComp2CZ)<kBComp2hDZ && rad2 < kBComp2SqR){
285 b[0] = fCCorrField*fFactorDip;
db83d72f 286 }
9251fceb 287 else if(TMath::Abs(x[2]+kTripQ1CZ)<kTripQ1hDZ && rad2 < kTripQ1SqR){
db83d72f 288 b[0] = fQuadGradient*x[1];
289 b[1] = fQuadGradient*x[0];
db83d72f 290 }
9251fceb 291 else if(TMath::Abs(x[2]+kTripQ2CZ)<kTripQ2hDZ && rad2 < kTripQ2SqR){
db83d72f 292 b[0] = -fQuadGradient*x[1];
293 b[1] = -fQuadGradient*x[0];
db83d72f 294 }
9251fceb 295 else if(TMath::Abs(x[2]+kTripQ3CZ)<kTripQ3hDZ && rad2 < kTripQ3SqR){
db83d72f 296 b[0] = -fQuadGradient*x[1];
297 b[1] = -fQuadGradient*x[0];
db83d72f 298 }
9251fceb 299 else if(TMath::Abs(x[2]+kTripQ4CZ)<kTripQ4hDZ && rad2 < kTripQ4SqR){
db83d72f 300 b[0] = fQuadGradient*x[1];
301 b[1] = fQuadGradient*x[0];
db83d72f 302 }
9251fceb 303 else if(TMath::Abs(x[2]+kDip1CZ)<kDip1hDZ && rad2 < kDip1SqRC){
db83d72f 304 b[1] = fDipoleField;
db83d72f 305 }
9251fceb 306 else if(TMath::Abs(x[2]+kDip2CZ)<kDip2hDZ && rad2 < kDip2SqRC) {
307 double dxabs = TMath::Abs(x[0])-kDip2DXC;
308 if ( (dxabs*dxabs + x[1]*x[1])<kDip2SqRC) {
db83d72f 309 b[1] = -fDipoleField;
db83d72f 310 }
311 }
312 }
313 //
314 // SIDE A **************************************************
315 else{
9251fceb 316 if(TMath::Abs(x[2]-kBComp1CZ)<kBComp1hDZ && rad2 < kBComp1SqR) {
db83d72f 317 // Compensator magnet at z = 1075 m
9251fceb 318 b[0] = fACorr1Field*fFactorDip;
db83d72f 319 }
320 //
9251fceb 321 if(TMath::Abs(x[2]-kBComp2CZ)<kBComp2hDZ && rad2 < kBComp2SqR){
322 b[0] = fACorr2Field*fFactorDip;
323 }
324 else if(TMath::Abs(x[2]-kTripQ1CZ)<kTripQ1hDZ && rad2 < kTripQ1SqR){
db83d72f 325 b[0] = -fQuadGradient*x[1];
326 b[1] = -fQuadGradient*x[0];
eed8a1a2 327 }
9251fceb 328 else if(TMath::Abs(x[2]-kTripQ2CZ)<kTripQ2hDZ && rad2 < kTripQ2SqR){
329 b[0] = fQuadGradient*x[1];
330 b[1] = fQuadGradient*x[0];
eed8a1a2 331 }
9251fceb 332 else if(TMath::Abs(x[2]-kTripQ3CZ)<kTripQ3hDZ && rad2 < kTripQ3SqR){
333 b[0] = fQuadGradient*x[1];
334 b[1] = fQuadGradient*x[0];
db83d72f 335 }
9251fceb 336 else if(TMath::Abs(x[2]-kTripQ4CZ)<kTripQ4hDZ && rad2 < kTripQ4SqR){
db83d72f 337 b[0] = -fQuadGradient*x[1];
338 b[1] = -fQuadGradient*x[0];
db83d72f 339 }
9251fceb 340 else if(TMath::Abs(x[2]-kDip1CZ)<kDip1hDZ && rad2 < kDip1SqRA){
db83d72f 341 b[1] = -fDipoleField;
db83d72f 342 }
9251fceb 343 else if(TMath::Abs(x[2]-kDip2CZ)<kDip2hDZ && rad2 < kDip2SqRA) {
344 double dxabs = TMath::Abs(x[0])-kDip2DXA;
345 if ( (dxabs*dxabs + x[1]*x[1])<kDip2SqRA) {
db83d72f 346 b[1] = fDipoleField;
347 }
348 }
349 }
9251fceb 350 //
db83d72f 351}
352
353//_______________________________________________________________________
354void AliMagF::GetTPCInt(const Double_t *xyz, Double_t *b) const
355{
356 // Method to calculate the integral of magnetic integral from xyz to nearest cathode plane
357 b[0]=b[1]=b[2]=0.0;
358 if (fMeasuredMap) {
359 fMeasuredMap->GetTPCInt(xyz,b);
360 for (int i=3;i--;) b[i] *= fFactorSol;
361 }
362}
363
364//_______________________________________________________________________
365void AliMagF::GetTPCIntCyl(const Double_t *rphiz, Double_t *b) const
366{
367 // Method to calculate the integral of magnetic integral from point to nearest cathode plane
368 // in cylindrical coordiates ( -pi<phi<pi convention )
369 b[0]=b[1]=b[2]=0.0;
370 if (fMeasuredMap) {
371 fMeasuredMap->GetTPCIntCyl(rphiz,b);
372 for (int i=3;i--;) b[i] *= fFactorSol;
373 }
eed8a1a2 374}
1dd3d90e 375
376//_______________________________________________________________________
377void AliMagF::SetFactorSol(Float_t fc)
378{
379 // set the sign/scale of the current in the L3 according to fgkPolarityConvention
380 switch (fgkPolarityConvention) {
381 case kConvDCS2008: fFactorSol = -fc; break;
382 case kConvLHC : fFactorSol = -fc; break;
383 default : fFactorSol = fc; break; // case kConvMap2005: fFactorSol = fc; break;
384 }
385}
386
387//_______________________________________________________________________
388void AliMagF::SetFactorDip(Float_t fc)
389{
390 // set the sign*scale of the current in the Dipole according to fgkPolarityConvention
391 switch (fgkPolarityConvention) {
392 case kConvDCS2008: fFactorDip = fc; break;
393 case kConvLHC : fFactorDip = -fc; break;
394 default : fFactorDip = fc; break; // case kConvMap2005: fFactorDip = fc; break;
395 }
396}
397
398//_______________________________________________________________________
399Double_t AliMagF::GetFactorSol() const
400{
401 // return the sign*scale of the current in the Dipole according to fgkPolarityConventionthe
402 switch (fgkPolarityConvention) {
403 case kConvDCS2008: return -fFactorSol;
404 case kConvLHC : return -fFactorSol;
405 default : return fFactorSol; // case kConvMap2005: return fFactorSol;
406 }
407}
408
409//_______________________________________________________________________
410Double_t AliMagF::GetFactorDip() const
411{
412 // return the sign*scale of the current in the Dipole according to fgkPolarityConventionthe
413 switch (fgkPolarityConvention) {
414 case kConvDCS2008: return fFactorDip;
415 case kConvLHC : return -fFactorDip;
416 default : return fFactorDip; // case kConvMap2005: return fFactorDip;
417 }
418}