LCOV - code coverage report
Current view: top level - TPC/TPCbase - AliTPCExBExact.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 175 0.6 %
Date: 2016-06-14 17:26:59 Functions: 1 17 5.9 %

          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             : /// \class AliTPCExBExact
      17             : /// \brief This implementation AliTPCExB is using an "exact" calculation of the ExB effect.
      18             : ///
      19             : /// That is, it uses the drift ODE to calculate the distortion
      20             : /// without any further assumption.
      21             : /// Due to the numerical integration of the ODE, there are some numerical
      22             : /// uncertencies involed.
      23             : 
      24             : #include "TMath.h"
      25             : #include "TTreeStream.h"
      26             : #include "AliMagF.h"
      27             : #include "AliTPCExBExact.h"
      28             : 
      29             : /// \cond CLASSIMP
      30          24 : ClassImp(AliTPCExBExact)
      31             : /// \endcond
      32             : 
      33             : const Double_t AliTPCExBExact::fgkEM=1.602176487e-19/9.10938215e-31;
      34             : const Double_t AliTPCExBExact::fgkDriftField=-40.e3;
      35             : 
      36           0 : AliTPCExBExact::AliTPCExBExact()
      37           0 :   : fDriftVelocity(0),
      38             :     //fkMap(0),
      39           0 :     fkField(0),fkN(0),
      40           0 :     fkNX(0),fkNY(0),fkNZ(0),
      41           0 :     fkXMin(-250.),fkXMax(250.),fkYMin(-250.),fkYMax(250.),
      42           0 :     fkZMin(-250.),fkZMax(250.),
      43           0 :     fkNLook(0),fkLook(0) {
      44             :   /// purely for I/O
      45             : 
      46           0 : }
      47             : 
      48           0 : AliTPCExBExact::AliTPCExBExact(const AliMagF *bField,
      49             :                                Double_t driftVelocity,
      50             :                                Int_t nx,Int_t ny,Int_t nz,Int_t n)
      51           0 :   : fDriftVelocity(driftVelocity),
      52             :     //fkMap(0),
      53           0 :     fkField(bField),fkN(n),
      54           0 :     fkNX(nx),fkNY(ny),fkNZ(nz),
      55           0 :     fkXMin(-250.),fkXMax(250.),fkYMin(-250.),fkYMax(250.),
      56           0 :     fkZMin(-250.),fkZMax(250.),
      57           0 :     fkNLook(0),fkLook(0) {
      58             :   /// The constructor. One has to supply a magnetic field and an (initial)
      59             :   /// drift velocity. Since some kind of lookuptable is created the
      60             :   /// number of its meshpoints can be supplied.
      61             :   /// n sets the number of integration steps to be used when integrating
      62             :   /// over the full drift length.
      63             : 
      64           0 :   CreateLookupTable();
      65           0 : }
      66             : 
      67             : /*
      68             : AliTPCExBExact::AliTPCExBExact(const AliFieldMap *bFieldMap,
      69             :                                Double_t driftVelocity,Int_t n)
      70             :   : fDriftVelocity(driftVelocity),
      71             :     fkMap(bFieldMap),fkField(0),fkN(n),
      72             :     fkNX(0),fkNY(0),fkNZ(0),
      73             :     fkXMin(-250.),fkXMax(250.),fkYMin(-250.),fkYMax(250.),
      74             :     fkZMin(-250.),fkZMax(250.),
      75             :     fkNLook(0),fkLook(0) {
      76             :   //
      77             :   // The constructor. One has to supply a field map and an (initial)
      78             :   // drift velocity.
      79             :   // n sets the number of integration steps to be used when integrating
      80             :   // over the full drift length.
      81             :   //
      82             : 
      83             :   fkXMin=bFieldMap->Xmin()
      84             :     -TMath::Ceil( (bFieldMap->Xmin()+250.0)/bFieldMap->DelX())
      85             :     *bFieldMap->DelX();
      86             :   fkXMax=bFieldMap->Xmax()
      87             :     -TMath::Floor((bFieldMap->Xmax()-250.0)/bFieldMap->DelX())
      88             :     *bFieldMap->DelX();
      89             :   fkYMin=bFieldMap->Ymin()
      90             :     -TMath::Ceil( (bFieldMap->Ymin()+250.0)/bFieldMap->DelY())
      91             :     *bFieldMap->DelY();
      92             :   fkYMax=bFieldMap->Ymax()
      93             :     -TMath::Floor((bFieldMap->Ymax()-250.0)/bFieldMap->DelY())
      94             :     *bFieldMap->DelY();
      95             :   fkZMax=bFieldMap->Zmax()
      96             :     -TMath::Floor((bFieldMap->Zmax()-250.0)/bFieldMap->DelZ())
      97             :     *bFieldMap->DelZ();
      98             :   fkZMax=TMath::Max(0.,fkZMax); // I really hope that this is unnecessary!
      99             : 
     100             :   fkNX=static_cast<Int_t>((fkXMax-fkXMin)/bFieldMap->DelX()+1.1);
     101             :   fkNY=static_cast<Int_t>((fkYMax-fkYMin)/bFieldMap->DelY()+1.1);
     102             :   fkNZ=static_cast<Int_t>((fkZMax-fkZMin)/bFieldMap->DelZ()+1.1);
     103             : 
     104             :   CreateLookupTable();
     105             : }
     106             : */
     107             : 
     108           0 : AliTPCExBExact::~AliTPCExBExact() {
     109             :   /// destruct the poor object.
     110             : 
     111           0 :   delete[] fkLook;
     112           0 : }
     113             : 
     114             : void AliTPCExBExact::Correct(const Double_t *position, Double_t *corrected) {
     115             :   /// correct for the distortion
     116             : 
     117           0 :   Double_t x=(position[0]-fkXMin)/(fkXMax-fkXMin)*(fkNX-1);
     118           0 :   Int_t xi1=static_cast<Int_t>(x);
     119           0 :   xi1=TMath::Max(TMath::Min(xi1,fkNX-2),0);
     120           0 :   Int_t xi2=xi1+1;
     121           0 :   Double_t dx=(x-xi1);
     122           0 :   Double_t dx1=(xi2-x);
     123             : 
     124           0 :   Double_t y=(position[1]-fkYMin)/(fkYMax-fkYMin)*(fkNY-1);
     125           0 :   Int_t yi1=static_cast<Int_t>(y);
     126           0 :   yi1=TMath::Max(TMath::Min(yi1,fkNY-2),0);
     127           0 :   Int_t yi2=yi1+1;
     128           0 :   Double_t dy=(y-yi1);
     129           0 :   Double_t dy1=(yi2-y);
     130             : 
     131           0 :   Double_t z=position[2]/fkZMax*(fkNZ-1);
     132             :   Int_t side;
     133           0 :   if (z>0) {
     134             :     side=1;
     135           0 :   }
     136             :   else {
     137           0 :     z=-z;
     138             :     side=0;
     139             :   }
     140           0 :   Int_t zi1=static_cast<Int_t>(z);
     141           0 :   zi1=TMath::Max(TMath::Min(zi1,fkNZ-2),0);
     142           0 :   Int_t zi2=zi1+1;
     143           0 :   Double_t dz=(z-zi1);
     144           0 :   Double_t dz1=(zi2-z);
     145             : 
     146           0 :   for (int i=0;i<3;++i)
     147           0 :     corrected[i]
     148           0 :       =fkLook[(((xi1*fkNY+yi1)*fkNZ+zi1)*2+side)*3+i]*dx1*dy1*dz1
     149           0 :       +fkLook[(((xi1*fkNY+yi1)*fkNZ+zi2)*2+side)*3+i]*dx1*dy1*dz
     150           0 :       +fkLook[(((xi1*fkNY+yi2)*fkNZ+zi1)*2+side)*3+i]*dx1*dy *dz1
     151           0 :       +fkLook[(((xi1*fkNY+yi2)*fkNZ+zi2)*2+side)*3+i]*dx1*dy *dz
     152           0 :       +fkLook[(((xi2*fkNY+yi2)*fkNZ+zi1)*2+side)*3+i]*dx *dy *dz1
     153           0 :       +fkLook[(((xi2*fkNY+yi2)*fkNZ+zi2)*2+side)*3+i]*dx *dy *dz
     154           0 :       +fkLook[(((xi2*fkNY+yi1)*fkNZ+zi1)*2+side)*3+i]*dx *dy1*dz1
     155           0 :       +fkLook[(((xi2*fkNY+yi1)*fkNZ+zi2)*2+side)*3+i]*dx *dy1*dz ;
     156             :   //    corrected[2]=position[2];
     157           0 : }
     158             : 
     159             : /*
     160             : void AliTPCExBExact::TestThisBeautifulObject(const AliFieldMap *bFieldMap,
     161             :                                              const char* fileName) {
     162             :   //
     163             :   // Have a look at the common part "TestThisBeautifulObjectGeneric".
     164             :   //
     165             :   fkMap=bFieldMap;
     166             :   fkField=0;
     167             :   TestThisBeautifulObjectGeneric(fileName);
     168             : }
     169             : */
     170             : 
     171             : void AliTPCExBExact::TestThisBeautifulObject(const AliMagF *bField,
     172             :                                              const char* fileName) {
     173             :   /// Have a look at the common part "TestThisBeautifulObjectGeneric".
     174             : 
     175           0 :   fkField=bField;
     176             :   //fkMap=0;
     177           0 :   TestThisBeautifulObjectGeneric(fileName);
     178           0 : }
     179             : 
     180             : void AliTPCExBExact::TestThisBeautifulObjectGeneric(const char* fileName) {
     181             :   /// Well, as the name sais... it tests the object.
     182             : 
     183           0 :   TTreeSRedirector ts(fileName);
     184           0 :   Double_t x[3];
     185           0 :   for (x[0]=-250.;x[0]<=250.;x[0]+=10.)
     186           0 :     for (x[1]=-250.;x[1]<=250.;x[1]+=10.)
     187           0 :       for (x[2]=-250.;x[2]<=250.;x[2]+=10.) {
     188           0 :         Double_t d[3];
     189           0 :         Double_t dnl[3];
     190           0 :         Correct(x,d);
     191           0 :         CalculateDistortion(x,dnl);
     192           0 :         Double_t r=TMath::Sqrt(x[0]*x[0]+x[1]*x[1]);
     193           0 :         Double_t rd=TMath::Sqrt(d[0]*d[0]+d[1]*d[1]);
     194           0 :         Double_t dr=r-rd;
     195           0 :         Double_t phi=TMath::ATan2(x[0],x[1]);
     196           0 :         Double_t phid=TMath::ATan2(d[0],d[1]);
     197           0 :         Double_t dphi=phi-phid;
     198           0 :         if (dphi<0.) dphi+=TMath::TwoPi();
     199           0 :         if (dphi>TMath::Pi()) dphi=TMath::TwoPi()-dphi;
     200           0 :         Double_t drphi=r*dphi;
     201           0 :         Double_t dx=x[0]-d[0];
     202           0 :         Double_t dy=x[1]-d[1];
     203           0 :         Double_t dz=x[2]-d[2];
     204           0 :         Double_t dnlx=x[0]-dnl[0];
     205           0 :         Double_t dnly=x[1]-dnl[1];
     206           0 :         Double_t dnlz=x[2]-dnl[2];
     207           0 :         Double_t b[3];
     208           0 :         GetB(b,x);
     209           0 :         ts<<"positions"
     210           0 :           <<"bx="<<b[0]
     211           0 :           <<"by="<<b[1]
     212           0 :           <<"bz="<<b[2]
     213           0 :           <<"x0="<<x[0]
     214           0 :           <<"x1="<<x[1]
     215           0 :           <<"x2="<<x[2]
     216           0 :           <<"dx="<<dx
     217           0 :           <<"dy="<<dy
     218           0 :           <<"dz="<<dz
     219           0 :           <<"dnlx="<<dnlx
     220           0 :           <<"dnly="<<dnly
     221           0 :           <<"dnlz="<<dnlz
     222           0 :           <<"r="<<r
     223           0 :           <<"phi="<<phi
     224           0 :           <<"dr="<<dr
     225           0 :           <<"drphi="<<drphi
     226           0 :           <<"\n";
     227           0 :       }
     228           0 : }
     229             : 
     230             : void AliTPCExBExact::CreateLookupTable() {
     231             :   /// Helper function to fill the lookup table.
     232             : 
     233           0 :   fkNLook=fkNX*fkNY*fkNZ*2*3;
     234           0 :   fkLook=new Double_t[fkNLook];
     235           0 :   Double_t x[3];
     236           0 :   for (int i=0;i<fkNX;++i) {
     237           0 :     x[0]=fkXMin+(fkXMax-fkXMin)/(fkNX-1)*i;
     238           0 :     for (int j=0;j<fkNY;++j) {
     239           0 :       x[1]=fkYMin+(fkYMax-fkYMin)/(fkNY-1)*j;
     240           0 :       for (int k=0;k<fkNZ;++k) {
     241           0 :         x[2]=1.*fkZMax/(fkNZ-1)*k;
     242           0 :         x[2]=TMath::Max((Double_t)0.0001,x[2]); //ugly
     243           0 :         CalculateDistortion(x,&fkLook[(((i*fkNY+j)*fkNZ+k)*2+1)*3]);
     244           0 :         x[2]=-x[2];
     245           0 :         CalculateDistortion(x,&fkLook[(((i*fkNY+j)*fkNZ+k)*2+0)*3]);
     246             :       }
     247             :     }
     248             :   }
     249           0 : }
     250             : 
     251             : void AliTPCExBExact::GetE(Double_t *e,const Double_t *x) const {
     252             :   /// Helper function returning the E field in SI units (V/m).
     253             : 
     254           0 :   e[0]=0.;
     255           0 :   e[1]=0.;
     256           0 :   e[2]=(x[2]<0.?-1.:1.)*fgkDriftField; // in V/m
     257           0 : }
     258             : 
     259             : void AliTPCExBExact::GetB(Double_t *b,const Double_t *x) const {
     260             :   /// Helper function returning the B field in SI units (T).
     261             : 
     262           0 :   Double_t xm[3];
     263             :   // the beautiful m to cm (and the ugly "const_cast") and Double_t
     264             :   // to Float_t read the NRs introduction!:
     265           0 :   for (int i=0;i<3;++i) xm[i]=x[i]*100.;
     266           0 :   Double_t bf[3];
     267             :   //if (fkMap!=0)
     268             :   //  fkMap->Field(xm,bf);
     269             :   //else
     270           0 :   ((AliMagF*)fkField)->Field(xm,bf);
     271           0 :   for (int i=0;i<3;++i) b[i]=bf[i]/10.;
     272           0 : }
     273             : 
     274             : void AliTPCExBExact::Motion(const Double_t *x,Double_t,
     275             :                             Double_t *dxdt) const {
     276             :   /// The differential equation of motion of the electrons.
     277             : 
     278           0 :   Double_t tau=fDriftVelocity/fgkDriftField/fgkEM;
     279           0 :   Double_t tau2=tau*tau;
     280           0 :   Double_t e[3];
     281           0 :   Double_t b[3];
     282           0 :   GetE(e,x);
     283           0 :   GetB(b,x);
     284           0 :   Double_t wx=fgkEM*b[0];
     285           0 :   Double_t wy=fgkEM*b[1];
     286           0 :   Double_t wz=fgkEM*b[2];
     287           0 :   Double_t ex=fgkEM*e[0];
     288           0 :   Double_t ey=fgkEM*e[1];
     289           0 :   Double_t ez=fgkEM*e[2];
     290           0 :   Double_t w2=(wx*wx+wy*wy+wz*wz);
     291           0 :   dxdt[0]=(1.+wx*wx*tau2)*ex+(wz*tau+wx*wy*tau2)*ey+(-wy*tau+wx*wz*tau2)*ez;
     292           0 :   dxdt[1]=(-wz*tau+wx*wy*tau2)*ex+(1.+wy*wy*tau2)*ey+(wx*tau+wy*wz*tau2)*ez;
     293           0 :   dxdt[2]=(wy*tau+wx*wz*tau2)*ex+(-wx*tau+wy*wz*tau2)*ey+(1.+wz*wz*tau2)*ez;
     294           0 :   Double_t fac=tau/(1.+w2*tau2);
     295           0 :   dxdt[0]*=fac;
     296           0 :   dxdt[1]*=fac;
     297           0 :   dxdt[2]*=fac;
     298           0 : }
     299             : 
     300             : void AliTPCExBExact::CalculateDistortion(const Double_t *x0,
     301             :                                          Double_t *dist) const {
     302             :   /// Helper function that calculates one distortion by integration
     303             :   /// (only used to fill the lookup table).
     304             : 
     305           0 :   Double_t h=0.01*250./fDriftVelocity/fkN;
     306             :   Double_t t=0.;
     307           0 :   Double_t xt[3];
     308           0 :   Double_t xo[3];
     309           0 :   for (int i=0;i<3;++i)
     310           0 :     xo[i]=xt[i]=x0[i]*0.01;
     311           0 :   while (TMath::Abs(xt[2])<250.*0.01) {
     312           0 :     for (int i=0;i<3;++i)
     313           0 :       xo[i]=xt[i];
     314           0 :     DGLStep(xt,t,h);
     315           0 :     t+=h;
     316             :   }
     317           0 :   if (t!=0.) {
     318           0 :     Double_t p=((xt[2]<0.?-1.:1.)*250.*0.01-xo[2])/(xt[2]-xo[2]);
     319           0 :     dist[0]=(xo[0]+p*(xt[0]-xo[0]))*100.;
     320           0 :     dist[1]=(xo[1]+p*(xt[1]-xo[1]))*100.;
     321             :     //    dist[2]=(xo[2]+p*(xt[2]-xo[2]))*100.;
     322           0 :     dist[2]=(x0[2]>0.?-1:1.)*(t-h+p*h)*fDriftVelocity*100.;
     323           0 :     dist[2]+=(x0[2]<0.?-1:1.)*250.;
     324           0 :   }
     325             :   else {
     326           0 :     dist[0]=x0[0];
     327           0 :     dist[1]=x0[1];
     328           0 :     dist[2]=x0[2];
     329             :   }
     330             :   // reverse the distortion, i.e. get the correction
     331           0 :   dist[0]=x0[0]-(dist[0]-x0[0]);
     332           0 :   dist[1]=x0[1]-(dist[1]-x0[1]);
     333           0 : }
     334             : 
     335             : void AliTPCExBExact::DGLStep(Double_t *x,Double_t t,Double_t h) const {
     336             :   /// An elementary integration step.
     337             :   /// (simple Euler Method)
     338             : 
     339           0 :   Double_t dxdt[3];
     340           0 :   Motion(x,t,dxdt);
     341           0 :   for (int i=0;i<3;++i)
     342           0 :     x[i]+=h*dxdt[i];
     343             : 
     344             :   /* suggestions about how to write it this way are welcome!
     345             :      void DGLStep(void (*f)(const Double_t *x,Double_t t,Double_t *dxdt),
     346             :                    Double_t *x,Double_t t,Double_t h,Int_t n) const;
     347             :   */
     348             : 
     349           0 : }

Generated by: LCOV version 1.11