LCOV - code coverage report
Current view: top level - STEER/STEERBase - AliMagF.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 159 294 54.1 %
Date: 2016-06-14 17:26:59 Functions: 20 27 74.1 %

          Line data    Source code
       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             : 
      16             : 
      17             : #include <TClass.h>
      18             : #include <TFile.h>
      19             : #include <TSystem.h>
      20             : #include <TPRegexp.h>
      21             : 
      22             : #include "AliMagF.h"
      23             : #include "AliMagWrapCheb.h"
      24             : #include "AliLog.h"
      25             : 
      26         176 : ClassImp(AliMagF)
      27             : 
      28             : const Double_t AliMagF::fgkSol2DipZ    =  -700.;  
      29             : const UShort_t AliMagF::fgkPolarityConvention = AliMagF::kConvLHC;
      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 -> positive 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             : 
      47             :  ----------------------------------------------- 
      48             : 
      49             :  Explanation on integrals in the TPC region
      50             :  GetTPCInt(xyz,b) and GetTPCRatInt(xyz,b) give integrals from point (x,y,z) to point (x,y,0) 
      51             :  (irrespectively of the z sign) of the following:
      52             :  TPCInt:    b contains int{bx}, int{by}, int{bz}
      53             :  TPCRatInt: b contains int{bx/bz}, int{by/bz}, int{(bx/bz)^2+(by/bz)^2}
      54             :   
      55             :  The same applies to integral in cylindrical coordinates:
      56             :  GetTPCIntCyl(rphiz,b)
      57             :  GetTPCIntRatCyl(rphiz,b)
      58             :  They accept the R,Phi,Z coordinate (-pi<phi<pi) and return the field 
      59             :  integrals in cyl. coordinates.
      60             : 
      61             :  Thus, to compute the integral from arbitrary xy_z1 to xy_z2, one should take
      62             :  b = b1-b2 with b1 and b2 coming from GetTPCInt(xy_z1,b1) and GetTPCInt(xy_z2,b2)
      63             : 
      64             :  Note: the integrals are defined for the range -300<Z<300 and 0<R<300
      65             : */
      66             : //_______________________________________________________________________
      67             : AliMagF::AliMagF():
      68           3 :   TVirtualMagField(),
      69           3 :   fMeasuredMap(0),
      70           3 :   fMapType(k5kG),
      71           3 :   fSolenoid(0),
      72           3 :   fBeamType(kNoBeamField),
      73           3 :   fBeamEnergy(0),
      74             :   //
      75           3 :   fInteg(0),
      76           3 :   fPrecInteg(0),
      77           3 :   fFactorSol(1.),
      78           3 :   fFactorDip(1.),
      79           3 :   fMax(15),
      80           3 :   fDipoleOFF(kFALSE),
      81             :   //
      82           3 :   fQuadGradient(0),
      83           3 :   fDipoleField(0),
      84           3 :   fCCorrField(0), 
      85           3 :   fACorr1Field(0),
      86           3 :   fACorr2Field(0),
      87           3 :   fParNames("","")
      88          15 : {
      89             :   // Default constructor
      90             :   //
      91           6 : }
      92             : 
      93             : //_______________________________________________________________________
      94             : AliMagF::AliMagF(const char *name, const char* title, Double_t factorSol, Double_t factorDip, 
      95             :                  BMap_t maptype, BeamType_t bt, Double_t be,Int_t integ, Double_t fmax, const char* path):
      96           5 :   TVirtualMagField(name),
      97           5 :   fMeasuredMap(0),
      98           5 :   fMapType(maptype),
      99           5 :   fSolenoid(0),
     100           5 :   fBeamType(bt),
     101           5 :   fBeamEnergy(be),
     102             :   //
     103           5 :   fInteg(integ),
     104           5 :   fPrecInteg(1),
     105           5 :   fFactorSol(1.),
     106           5 :   fFactorDip(1.),
     107           5 :   fMax(fmax),
     108           5 :   fDipoleOFF(factorDip==0.),
     109             :   //
     110           5 :   fQuadGradient(0),
     111           5 :   fDipoleField(0),
     112           5 :   fCCorrField(0), 
     113           5 :   fACorr1Field(0),
     114           5 :   fACorr2Field(0),
     115           5 :   fParNames("","")
     116          25 : {
     117             :   // Initialize the field with Geant integration option "integ" and max field "fmax,
     118             :   // Impose scaling of parameterized L3 field by factorSol and of dipole by factorDip.
     119             :   // The "be" is the energy of the beam in GeV/nucleon
     120             :   //
     121           5 :   SetTitle(title);
     122           5 :   if(integ<0 || integ > 2) {
     123           0 :     AliWarning(Form("Invalid magnetic field flag: %5d; Helix tracking chosen instead",integ));
     124           0 :     fInteg = 2;
     125           0 :   }
     126           5 :   if (fInteg == 0) fPrecInteg = 0;
     127             :   //
     128           5 :   if (fBeamEnergy<=0 && fBeamType!=kNoBeamField) {
     129           0 :     if      (fBeamType == kBeamTypepp) fBeamEnergy = 7000.; // max proton energy
     130           0 :     else if (fBeamType == kBeamTypeAA) fBeamEnergy = 2760;  // max PbPb energy
     131           0 :     else if (fBeamType == kBeamTypepA || fBeamType == kBeamTypeAp) fBeamEnergy = 2760;  // same rigitiy max PbPb energy
     132           0 :     AliInfo("Maximim possible beam energy for requested beam is assumed");
     133             :   } 
     134             :   const char* parname = 0;
     135             :   //  
     136           5 :   if      (fMapType == k2kG) parname = fDipoleOFF ? "Sol12_Dip0_Hole":"Sol12_Dip6_Hole";
     137          10 :   else if (fMapType == k5kG) parname = fDipoleOFF ? "Sol30_Dip0_Hole":"Sol30_Dip6_Hole";
     138           0 :   else if (fMapType == k5kGUniform) parname = "Sol30_Dip6_Uniform";
     139           0 :   else AliFatal(Form("Unknown field identifier %d is requested\n",fMapType));
     140             :   //
     141           5 :   SetDataFileName(path);
     142           5 :   SetParamName(parname);
     143             :   //
     144           5 :   LoadParameterization();
     145           5 :   InitMachineField(fBeamType,fBeamEnergy);
     146           5 :   double xyz[3]={0.,0.,0.};
     147          10 :   fSolenoid = GetBz(xyz);
     148           5 :   SetFactorSol(factorSol);
     149           5 :   SetFactorDip(factorDip);
     150           5 :   Print("a");
     151          10 : }
     152             : 
     153             : //_______________________________________________________________________
     154             : AliMagF::AliMagF(const AliMagF &src):
     155           0 :   TVirtualMagField(src),
     156           0 :   fMeasuredMap(0),
     157           0 :   fMapType(src.fMapType),
     158           0 :   fSolenoid(src.fSolenoid),
     159           0 :   fBeamType(src.fBeamType),
     160           0 :   fBeamEnergy(src.fBeamEnergy),
     161           0 :   fInteg(src.fInteg),
     162           0 :   fPrecInteg(src.fPrecInteg),
     163           0 :   fFactorSol(src.fFactorSol),
     164           0 :   fFactorDip(src.fFactorDip),
     165           0 :   fMax(src.fMax),
     166           0 :   fDipoleOFF(src.fDipoleOFF),
     167           0 :   fQuadGradient(src.fQuadGradient),
     168           0 :   fDipoleField(src.fDipoleField),
     169           0 :   fCCorrField(src.fCCorrField), 
     170           0 :   fACorr1Field(src.fACorr1Field),
     171           0 :   fACorr2Field(src.fACorr2Field),
     172           0 :   fParNames(src.fParNames)
     173           0 : {
     174           0 :   if (src.fMeasuredMap) fMeasuredMap = new AliMagWrapCheb(*src.fMeasuredMap);
     175           0 : }
     176             : 
     177             : //_______________________________________________________________________
     178             : AliMagF::~AliMagF()
     179          30 : {
     180          10 :   delete fMeasuredMap;
     181          15 : }
     182             : 
     183             : //_______________________________________________________________________
     184             : Bool_t AliMagF::LoadParameterization()
     185             : {
     186          10 :   if (fMeasuredMap) {
     187           0 :     AliFatal(Form("Field data %s are already loaded from %s\n",GetParamName(),GetDataFileName()));
     188           0 :   }
     189             :   //
     190           5 :   char* fname = gSystem->ExpandPathName(GetDataFileName());
     191           5 :   TFile* file = TFile::Open(fname);
     192           5 :   if (!file) {
     193           0 :     AliFatal(Form("Failed to open magnetic field data file %s\n",fname)); 
     194           0 :   }
     195             :   //
     196          15 :   fMeasuredMap = dynamic_cast<AliMagWrapCheb*>(file->Get(GetParamName()));
     197           5 :   if (!fMeasuredMap) {
     198           0 :     AliFatal(Form("Did not find field %s in %s\n",GetParamName(),fname)); 
     199           0 :   }
     200           5 :   file->Close();
     201          10 :   delete file;
     202           5 :   return kTRUE;
     203             : }
     204             : 
     205             : 
     206             : //_______________________________________________________________________
     207             : void AliMagF::Field(const Double_t *xyz, Double_t *b)
     208             : {
     209             :   // Method to calculate the field at point  xyz
     210             :   //
     211             :   //  b[0]=b[1]=b[2]=0.0;
     212    15867394 :   if (fMeasuredMap && xyz[2]>fMeasuredMap->GetMinZ() && xyz[2]<fMeasuredMap->GetMaxZ()) {
     213     2876176 :     fMeasuredMap->Field(xyz,b);
     214    28090408 :     if (xyz[2]>fgkSol2DipZ || fDipoleOFF) for (int i=3;i--;) b[i] *= fFactorSol;
     215      671352 :     else                                  for (int i=3;i--;) b[i] *= fFactorDip;    
     216             :   }
     217     1090874 :   else MachineField(xyz, b);
     218             :   //
     219     3967050 : }
     220             : 
     221             : //_______________________________________________________________________
     222             : Double_t AliMagF::GetBz(const Double_t *xyz) const
     223             : {
     224             :   // Method to calculate the field at point  xyz
     225             :   //
     226     1189696 :   if (fMeasuredMap && xyz[2]>fMeasuredMap->GetMinZ() && xyz[2]<fMeasuredMap->GetMaxZ()) {
     227      297424 :     double bz = fMeasuredMap->GetBz(xyz);
     228      892272 :     return (xyz[2]>fgkSol2DipZ || fDipoleOFF) ? bz*fFactorSol : bz*fFactorDip;    
     229             :   }
     230           0 :   else return 0.;
     231      297424 : }
     232             : 
     233             : //_______________________________________________________________________
     234             : AliMagF& AliMagF::operator=(const AliMagF& src)
     235             : {
     236           0 :   if (this != &src) {
     237           0 :     if (src.fMeasuredMap) { 
     238           0 :       if (fMeasuredMap) delete fMeasuredMap;
     239           0 :       fMeasuredMap = new AliMagWrapCheb(*src.fMeasuredMap);
     240           0 :     }
     241           0 :     SetName(src.GetName());
     242           0 :     fSolenoid    = src.fSolenoid;
     243           0 :     fBeamType    = src.fBeamType;
     244           0 :     fBeamEnergy  = src.fBeamEnergy;
     245           0 :     fInteg       = src.fInteg;
     246           0 :     fPrecInteg   = src.fPrecInteg;
     247           0 :     fFactorSol   = src.fFactorSol;
     248           0 :     fFactorDip   = src.fFactorDip;
     249           0 :     fMax         = src.fMax;
     250           0 :     fDipoleOFF   = src.fDipoleOFF;
     251           0 :     fParNames    = src.fParNames;
     252           0 :   }
     253           0 :   return *this;
     254           0 : }
     255             : 
     256             : //_______________________________________________________________________
     257             : void AliMagF::InitMachineField(BeamType_t btype, Double_t benergy)
     258             : {
     259          10 :   if (btype==kNoBeamField) {
     260           4 :     fQuadGradient = fDipoleField = fCCorrField = fACorr1Field = fACorr2Field = 0.;
     261           4 :     return;
     262             :   }
     263             :   //
     264           1 :   double rigScale = benergy/7000.;   // scale according to ratio of E/Enominal
     265             :   // for ions assume PbPb (with energy provided per nucleon) and account for A/Z
     266           2 :   if (btype==kBeamTypeAA/* || btype==kBeamTypepA || btype==kBeamTypeAp */) rigScale *= 208./82.;
     267             :   // Attention: in p-Pb the energy recorded in the GRP is the PROTON energy, no rigidity
     268             :   // rescaling is needed
     269             :   //
     270           1 :   fQuadGradient = 22.0002*rigScale;
     271           1 :   fDipoleField  = 37.8781*rigScale;
     272             :   //
     273             :   // SIDE C
     274           1 :   fCCorrField   = -9.6980;
     275             :   // SIDE A
     276           1 :   fACorr1Field  = -13.2247;
     277           1 :   fACorr2Field  =  11.7905;
     278             :   //
     279           6 : }
     280             : 
     281             : //_______________________________________________________________________
     282             : void AliMagF::MachineField(const Double_t *x, Double_t *b) const
     283             : {
     284             :   // ---- This is the ZDC part
     285             :   // Compansators for Alice Muon Arm Dipole
     286             :   const Double_t kBComp1CZ = 1075., kBComp1hDZ = 260./2., kBComp1SqR = 4.0*4.0; 
     287             :   const Double_t kBComp2CZ = 2049., kBComp2hDZ = 153./2., kBComp2SqR = 4.5*4.5; 
     288             :   //  
     289             :   const Double_t kTripQ1CZ = 2615., kTripQ1hDZ = 637./2., kTripQ1SqR = 3.5*3.5;
     290             :   const Double_t kTripQ2CZ = 3480., kTripQ2hDZ = 550./2., kTripQ2SqR = 3.5*3.5;
     291             :   const Double_t kTripQ3CZ = 4130., kTripQ3hDZ = 550./2., kTripQ3SqR = 3.5*3.5;
     292             :   const Double_t kTripQ4CZ = 5015., kTripQ4hDZ = 637./2., kTripQ4SqR = 3.5*3.5;
     293             :   //
     294             :   const Double_t kDip1CZ = 6310.8,  kDip1hDZ = 945./2., kDip1SqRC = 4.5*4.5, kDip1SqRA = 3.375*3.375;
     295             :   const Double_t kDip2CZ = 12640.3, kDip2hDZ = 945./2., kDip2SqRC = 4.5*4.5, kDip2SqRA = 3.75*3.75;
     296             :   const Double_t kDip2DXC = 9.7, kDip2DXA = 9.4;
     297             :   //
     298     2181748 :   double rad2 = x[0] * x[0] + x[1] * x[1];
     299             :   //
     300     1090874 :   b[0] = b[1] = b[2] = 0;
     301             :   //
     302             :   // SIDE C **************************************************
     303     1090874 :   if(x[2]<0.){  
     304         806 :     if(TMath::Abs(x[2]+kBComp2CZ)<kBComp2hDZ && rad2 < kBComp2SqR){
     305           0 :       b[0] = fCCorrField*fFactorDip;
     306           0 :     } 
     307         806 :     else if(TMath::Abs(x[2]+kTripQ1CZ)<kTripQ1hDZ && rad2 < kTripQ1SqR){
     308           0 :       b[0] = fQuadGradient*x[1];
     309           0 :       b[1] = fQuadGradient*x[0];
     310           0 :     }
     311         806 :     else if(TMath::Abs(x[2]+kTripQ2CZ)<kTripQ2hDZ && rad2 < kTripQ2SqR){
     312           0 :       b[0] = -fQuadGradient*x[1];
     313           0 :       b[1] = -fQuadGradient*x[0];
     314           0 :     }
     315         806 :     else if(TMath::Abs(x[2]+kTripQ3CZ)<kTripQ3hDZ && rad2 < kTripQ3SqR){
     316           0 :       b[0] = -fQuadGradient*x[1];
     317           0 :       b[1] = -fQuadGradient*x[0];
     318           0 :     }
     319         806 :     else if(TMath::Abs(x[2]+kTripQ4CZ)<kTripQ4hDZ && rad2 < kTripQ4SqR){
     320           0 :       b[0] = fQuadGradient*x[1];
     321           0 :       b[1] = fQuadGradient*x[0];
     322           0 :     }
     323         806 :     else if(TMath::Abs(x[2]+kDip1CZ)<kDip1hDZ && rad2 < kDip1SqRC){
     324           0 :       b[1] = fDipoleField;
     325           0 :     }
     326         806 :     else if(TMath::Abs(x[2]+kDip2CZ)<kDip2hDZ && rad2 < kDip2SqRC) {
     327           0 :       double dxabs = TMath::Abs(x[0])-kDip2DXC;
     328           0 :       if ( (dxabs*dxabs + x[1]*x[1])<kDip2SqRC) {
     329           0 :         b[1] = -fDipoleField;
     330           0 :       }
     331           0 :     }
     332             :   }
     333             :   //
     334             :   // SIDE A **************************************************
     335             :   else{        
     336     1090068 :     if(TMath::Abs(x[2]-kBComp1CZ)<kBComp1hDZ && rad2 < kBComp1SqR) {
     337             :       // Compensator magnet at z = 1075 m 
     338        7228 :       b[0] = fACorr1Field*fFactorDip;
     339        7228 :     }
     340             :     //
     341     1090068 :     if(TMath::Abs(x[2]-kBComp2CZ)<kBComp2hDZ && rad2 < kBComp2SqR){
     342          61 :       b[0] = fACorr2Field*fFactorDip;
     343          61 :     }
     344     1090007 :     else if(TMath::Abs(x[2]-kTripQ1CZ)<kTripQ1hDZ && rad2 < kTripQ1SqR){
     345           0 :       b[0] = -fQuadGradient*x[1];
     346           0 :       b[1] = -fQuadGradient*x[0];
     347           0 :     }
     348     1090007 :     else if(TMath::Abs(x[2]-kTripQ2CZ)<kTripQ2hDZ && rad2 < kTripQ2SqR){
     349           0 :       b[0] =  fQuadGradient*x[1];
     350           0 :       b[1] =  fQuadGradient*x[0];
     351           0 :     }
     352     1090007 :     else if(TMath::Abs(x[2]-kTripQ3CZ)<kTripQ3hDZ && rad2 < kTripQ3SqR){
     353           0 :       b[0] =  fQuadGradient*x[1];
     354           0 :       b[1] =  fQuadGradient*x[0];
     355           0 :     }
     356     1090007 :     else if(TMath::Abs(x[2]-kTripQ4CZ)<kTripQ4hDZ && rad2 < kTripQ4SqR){
     357           0 :       b[0] = -fQuadGradient*x[1];
     358           0 :       b[1] = -fQuadGradient*x[0];
     359           0 :     }
     360     1090007 :     else if(TMath::Abs(x[2]-kDip1CZ)<kDip1hDZ && rad2 < kDip1SqRA){
     361           0 :       b[1] = -fDipoleField;
     362           0 :     }
     363     1090007 :     else if(TMath::Abs(x[2]-kDip2CZ)<kDip2hDZ && rad2 < kDip2SqRA) {
     364           0 :       double dxabs = TMath::Abs(x[0])-kDip2DXA;
     365           0 :       if ( (dxabs*dxabs + x[1]*x[1])<kDip2SqRA) {
     366           0 :         b[1] = fDipoleField;
     367           0 :       }
     368           0 :     }
     369             :   }
     370             :   //
     371     1090874 : }
     372             : 
     373             : //_______________________________________________________________________
     374             : void AliMagF::GetTPCInt(const Double_t *xyz, Double_t *b) const
     375             : {
     376             :   // Method to calculate the integral_0^z of br,bt,bz 
     377           0 :   b[0]=b[1]=b[2]=0.0;
     378           0 :   if (fMeasuredMap) {
     379           0 :     fMeasuredMap->GetTPCInt(xyz,b);
     380           0 :     for (int i=3;i--;) b[i] *= fFactorSol;
     381           0 :   }
     382           0 : }
     383             : 
     384             : //_______________________________________________________________________
     385             : void AliMagF::GetTPCRatInt(const Double_t *xyz, Double_t *b) const
     386             : {
     387             :   // Method to calculate the integral_0^z of bx/bz,by/bz and (bx/bz)^2+(by/bz)^2
     388           0 :   b[0]=b[1]=b[2]=0.0;
     389           0 :   if (fMeasuredMap) {
     390           0 :     fMeasuredMap->GetTPCRatInt(xyz,b);
     391           0 :     b[2] /= 100;
     392           0 :   }
     393           0 : }
     394             : 
     395             : //_______________________________________________________________________
     396             : void AliMagF::GetTPCIntCyl(const Double_t *rphiz, Double_t *b) const
     397             : {
     398             :   // Method to calculate the integral_0^z of br,bt,bz 
     399             :   // in cylindrical coordiates ( -pi<phi<pi convention )
     400           0 :   b[0]=b[1]=b[2]=0.0;
     401           0 :   if (fMeasuredMap) {
     402           0 :     fMeasuredMap->GetTPCIntCyl(rphiz,b);
     403           0 :     for (int i=3;i--;) b[i] *= fFactorSol;
     404           0 :   }
     405           0 : }
     406             : 
     407             : //_______________________________________________________________________
     408             : void AliMagF::GetTPCRatIntCyl(const Double_t *rphiz, Double_t *b) const
     409             : {
     410             :   // Method to calculate the integral_0^z of bx/bz,by/bz and (bx/bz)^2+(by/bz)^2
     411             :   // in cylindrical coordiates ( -pi<phi<pi convention )
     412           0 :   b[0]=b[1]=b[2]=0.0;
     413           0 :   if (fMeasuredMap) {
     414           0 :     fMeasuredMap->GetTPCRatIntCyl(rphiz,b);
     415           0 :     b[2] /= 100;
     416           0 :   }
     417           0 : }
     418             : 
     419             : //_______________________________________________________________________
     420             : void AliMagF::SetFactorSol(Float_t fc)
     421             : {
     422             :   // set the sign/scale of the current in the L3 according to fgkPolarityConvention
     423             :   switch (fgkPolarityConvention) {
     424             :   case kConvDCS2008: fFactorSol = -fc; break;
     425          10 :   case kConvLHC    : fFactorSol = -fc; break;
     426             :   default          : fFactorSol =  fc; break;  // case kConvMap2005: fFactorSol =  fc; break;
     427             :   }
     428           5 : }
     429             : 
     430             : //_______________________________________________________________________
     431             : void AliMagF::SetFactorDip(Float_t fc)
     432             : {
     433             :   // set the sign*scale of the current in the Dipole according to fgkPolarityConvention
     434             :   switch (fgkPolarityConvention) {
     435             :   case kConvDCS2008: fFactorDip =  fc; break;
     436          10 :   case kConvLHC    : fFactorDip = -fc; break;
     437             :   default          : fFactorDip =  fc; break;  // case kConvMap2005: fFactorDip =  fc; break;
     438             :   }
     439           5 : }
     440             : 
     441             : //_______________________________________________________________________
     442             : Double_t AliMagF::GetFactorSol() const
     443             : {
     444             :   // return the sign*scale of the current in the Dipole according to fgkPolarityConventionthe 
     445             :   switch (fgkPolarityConvention) {
     446             :   case kConvDCS2008: return -fFactorSol;
     447          44 :   case kConvLHC    : return -fFactorSol;
     448             :   default          : return  fFactorSol;       //  case kConvMap2005: return  fFactorSol;
     449             :   }
     450             : }
     451             : 
     452             : //_______________________________________________________________________
     453             : Double_t AliMagF::GetFactorDip() const
     454             : {
     455             :   // return the sign*scale of the current in the Dipole according to fgkPolarityConventionthe 
     456             :   switch (fgkPolarityConvention) {
     457             :   case kConvDCS2008: return  fFactorDip;
     458          44 :   case kConvLHC    : return -fFactorDip;
     459             :   default          : return  fFactorDip;       //  case kConvMap2005: return  fFactorDip;
     460             :   }
     461             : }
     462             : 
     463             : //_____________________________________________________________________________
     464             : AliMagF* AliMagF::CreateFieldMap(Float_t l3Cur, Float_t diCur, Int_t convention, Bool_t uniform,
     465             :                                  Float_t beamenergy, const Char_t *beamtype, const Char_t *path,
     466             :                                  Bool_t returnNULLOnInvalidCurrent) 
     467             : {
     468             :   //------------------------------------------------
     469             :   // The magnetic field map, defined externally...
     470             :   // L3 current 30000 A  -> 0.5 T
     471             :   // L3 current 12000 A  -> 0.2 T
     472             :   // dipole current 6000 A
     473             :   // The polarities must match the convention (LHC or DCS2008) 
     474             :   // unless the special uniform map was used for MC
     475             :   //------------------------------------------------
     476           4 :   AliLog::EType_t error_type = returnNULLOnInvalidCurrent ? AliLog::kError : AliLog::kFatal;
     477             : 
     478             :   const Float_t l3NominalCurrent1=30000.; // (A)
     479             :   const Float_t l3NominalCurrent2=12000.; // (A)
     480             :   const Float_t diNominalCurrent =6000. ; // (A)
     481             : 
     482             :   const Float_t tolerance=0.03; // relative current tolerance
     483             :   const Float_t zero=77.;       // "zero" current (A)
     484             :   //
     485             :   BMap_t map = k5kG;
     486             :   double sclL3,sclDip;
     487             :   //
     488           4 :   Float_t l3Pol = l3Cur > 0 ? 1:-1;
     489           4 :   Float_t diPol = diCur > 0 ? 1:-1;
     490             :  
     491           4 :   l3Cur = TMath::Abs(l3Cur);
     492           4 :   diCur = TMath::Abs(diCur);
     493             :   //
     494           4 :   if (TMath::Abs((sclDip=diCur/diNominalCurrent)-1.) > tolerance && !uniform) {
     495           0 :     if (diCur <= zero) sclDip = 0.; // some small current.. -> Dipole OFF
     496             :     else {
     497           0 :       AliMessageGeneral("AliMagF",error_type,Form("Wrong dipole current (%f A)!",diCur));
     498           0 :       return NULL;
     499             :     }
     500           0 :   }
     501             :   //
     502           4 :   if (uniform) { 
     503             :     // special treatment of special MC with uniform mag field (normalized to 0.5 T)
     504             :     // no check for scaling/polarities are done
     505             :     map   = k5kGUniform;
     506           0 :     sclL3 = l3Cur/l3NominalCurrent1; 
     507           0 :   }
     508             :   else {
     509           8 :     if      (TMath::Abs((sclL3=l3Cur/l3NominalCurrent1)-1.) < tolerance) map  = k5kG;
     510           0 :     else if (TMath::Abs((sclL3=l3Cur/l3NominalCurrent2)-1.) < tolerance) map  = k2kG;
     511           0 :     else if (l3Cur <= zero && diCur<=zero)   { sclL3=0; sclDip=0; map  = k5kGUniform;}
     512             :     else {
     513           0 :       AliMessageGeneral("AliMagF",error_type,Form("Wrong L3 current (%f A)!",l3Cur));
     514           0 :       return NULL;
     515             :     }
     516             :   }
     517             :   //
     518           4 :   if (sclDip!=0 && map!=k5kGUniform) {
     519          16 :     if ( (l3Cur<=zero) || ((convention==kConvLHC && l3Pol!=diPol) || (convention==kConvDCS2008 && l3Pol==diPol)) ) { 
     520           0 :       AliMessageGeneral("AliMagF",error_type,Form("Wrong combination for L3/Dipole polarities (%c/%c) for convention %d",
     521             :                                      l3Pol>0?'+':'-',diPol>0?'+':'-',GetPolarityConvention()));
     522           0 :       return NULL;
     523             :     }
     524             :   }
     525             :   //
     526           8 :   if (l3Pol<0) sclL3  = -sclL3;
     527           8 :   if (diPol<0) sclDip = -sclDip;
     528             :   //
     529             :   BeamType_t btype = kNoBeamField;
     530           4 :   TString btypestr = beamtype;
     531           4 :   btypestr.ToLower();
     532          12 :   TPRegexp protonBeam("(proton|p)\\s*-?\\s*\\1");
     533          12 :   TPRegexp ionBeam("(lead|pb|ion|a|A)\\s*-?\\s*\\1");
     534          12 :   TPRegexp protonionBeam("(proton|p)\\s*-?\\s*(lead|pb|ion|a|A)");
     535          12 :   TPRegexp ionprotonBeam("(lead|pb|ion|a|A)\\s*-?\\s*(proton|p)");
     536           8 :   if (btypestr.Contains(ionBeam)) btype = kBeamTypeAA;
     537           8 :   else if (btypestr.Contains(protonBeam)) btype = kBeamTypepp;
     538           8 :   else if (btypestr.Contains(protonionBeam)) btype = kBeamTypepA;
     539           8 :   else if (btypestr.Contains(ionprotonBeam)) btype = kBeamTypeAp;
     540           8 :   else AliInfoGeneral("AliMagF",Form("Assume no LHC magnet field for the beam type %s, ",beamtype));
     541           4 :   char ttl[80];
     542           8 :   snprintf(ttl,79,"L3: %+5d Dip: %+4d kA; %s | Polarities in %s convention",(int)TMath::Sign(l3Cur,float(sclL3)),
     543           4 :           (int)TMath::Sign(diCur,float(sclDip)),uniform ? " Constant":"",
     544           4 :           convention==kConvLHC ? "LHC":"DCS2008");
     545             :   // LHC and DCS08 conventions have opposite dipole polarities
     546           4 :   if ( GetPolarityConvention() != convention) sclDip = -sclDip;
     547             :   //
     548           8 :   return new AliMagF("MagneticFieldMap", ttl,sclL3,sclDip,map,btype,beamenergy,2,10.,path);
     549             :   //
     550           8 : }
     551             : 
     552             : //_____________________________________________________________________________
     553             : const char*  AliMagF::GetBeamTypeText() const
     554             : {
     555             :   // beam type in text form
     556             :   const char *beamNA  = "No Beam";
     557             :   const char *beamPP  = "p-p";
     558             :   const char *beamPbPb= "A-A";
     559             :   const char *beamPPb = "p-A";
     560             :   const char *beamPbP = "A-p";
     561          10 :   switch ( fBeamType ) {
     562           0 :   case kBeamTypepp : return beamPP;
     563           1 :   case kBeamTypeAA : return beamPbPb;
     564           0 :   case kBeamTypepA : return beamPPb;
     565           0 :   case kBeamTypeAp : return beamPbP;
     566             :   case kNoBeamField: 
     567           4 :   default:           return beamNA;
     568             :   }
     569           5 : }
     570             : 
     571             : //_____________________________________________________________________________
     572             : void AliMagF::Print(Option_t *opt) const
     573             : {
     574             :   // print short or long info
     575          10 :   TString opts = opt; opts.ToLower();
     576          25 :   AliInfo(Form("%s:%s",GetName(),GetTitle()));
     577          20 :   AliInfo(Form("Solenoid (%+.2f*)%.0f kG, Dipole %s (%+.2f) %s",
     578             :                GetFactorSol(),(fMapType==k5kG||fMapType==k5kGUniform)?5.:2.,
     579             :                fDipoleOFF ? "OFF":"ON",GetFactorDip(),fMapType==k5kGUniform?" |Constant Field!":""));
     580          10 :   if (opts.Contains("a")) {
     581          15 :     AliInfo(Form("Machine B fields for %s beam (%.0f GeV): QGrad: %.4f Dipole: %.4f",
     582             :                  GetBeamTypeText(),
     583             :                  fBeamEnergy,fQuadGradient,fDipoleField));
     584          25 :     AliInfo(Form("Uses %s of %s",GetParamName(),GetDataFileName()));
     585             :   }
     586           5 : }

Generated by: LCOV version 1.11