5c6d2bc1b3af51c23764a6d926287226e85d19b5
[u/mrichter/AliRoot.git] / TPC / AliTPCFCVoltError3D.cxx
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 //                                                                          //
18 // AliTPCFCVoltError3D class                                                //
19 // The class calculates the space point distortions due to residual voltage //
20 // errors on the Field Cage boundaries (rods) of the TPC in 3D.             //
21 //                                                                          //
22 // The class allows "effective Omega Tau" corrections.                      // 
23 //                                                                          //
24 // NOTE: This class is capable of calculating z distortions due to          //
25 //       drift velocity changes in dependence of the electric field!!!      //
26 //                                                                          //
27 // date: 08/08/2010                                                         //
28 // Authors: Jim Thomas, Stefan Rossegger                                    //
29 //                                                                          //
30 // Example usage :                                                          //
31 //  AliTPCFCVoltError3D fcerror;                                            //
32 //////////////////////////////////////////////////////////////////////////////
33
34 #include "AliMagF.h"
35 #include "TGeoGlobalMagField.h"
36 #include "AliTPCcalibDB.h"
37 #include "AliTPCParam.h"
38 #include "AliLog.h"
39 #include "TMatrixD.h"
40
41 #include "TMath.h"
42 #include "AliTPCROC.h"
43 #include "AliTPCFCVoltError3D.h"
44
45 ClassImp(AliTPCFCVoltError3D)
46
47 AliTPCFCVoltError3D::AliTPCFCVoltError3D()
48   : AliTPCCorrection("FieldCageVoltErrors","FieldCage (Rods) Voltage Errors"),
49     fC0(0.),fC1(0.),
50     fInitLookUp(kFALSE)
51 {
52   //
53   // default constructor
54   //
55
56   // flags for filled 'basic lookup tables'
57   for (Int_t i=0; i<5; i++){
58     fInitLookUpBasic[i]= kFALSE;  
59   }
60
61   // Boundary settings 
62   for (Int_t i=0; i<36; i++){
63     fRodVoltShiftA[i] = 0;  
64     fRodVoltShiftC[i] = 0;  
65   }
66   for (Int_t i=0; i<2; i++){
67     fRotatedClipVoltA[i] = 0;  
68     fRotatedClipVoltC[i] = 0;  
69   }
70   // 
71   for (Int_t i=0; i<36; i++){
72     fCopperRodShiftA[i] = 0;  
73     fCopperRodShiftC[i] = 0;  
74   }
75
76   // Array which will contain the solution according to the setted boundary conditions
77   // it represents a sum up of the 4 basic look up tables (created individually)
78   // see InitFCVoltError3D() function
79   for ( Int_t k = 0 ; k < kNPhi ; k++ ) {
80     fLookUpErOverEz[k]   =  new TMatrixD(kNR,kNZ);  
81     fLookUpEphiOverEz[k] =  new TMatrixD(kNR,kNZ);
82     fLookUpDeltaEz[k]    =  new TMatrixD(kNR,kNZ);   
83   }
84   
85   for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
86     fLookUpBasic1ErOverEz[k]   = 0;
87     fLookUpBasic1EphiOverEz[k] = 0; 
88     fLookUpBasic1DeltaEz[k]    = 0;
89
90     fLookUpBasic2ErOverEz[k]   = 0;
91     fLookUpBasic2EphiOverEz[k] = 0; 
92     fLookUpBasic2DeltaEz[k]    = 0;
93
94     fLookUpBasic3ErOverEz[k]   = 0;
95     fLookUpBasic3EphiOverEz[k] = 0; 
96     fLookUpBasic3DeltaEz[k]    = 0;
97
98     fLookUpBasic4ErOverEz[k]   = 0;
99     fLookUpBasic4EphiOverEz[k] = 0; 
100     fLookUpBasic4DeltaEz[k]    = 0;
101     
102     fLookUpBasic5ErOverEz[k]   = 0;
103     fLookUpBasic5EphiOverEz[k] = 0; 
104     fLookUpBasic5DeltaEz[k]    = 0;
105
106     fLookUpBasic6ErOverEz[k]   = 0;
107     fLookUpBasic6EphiOverEz[k] = 0; 
108     fLookUpBasic6DeltaEz[k]    = 0;
109   }
110
111 }
112
113 AliTPCFCVoltError3D::~AliTPCFCVoltError3D() {
114   //
115   // destructor
116   //
117   
118   for ( Int_t k = 0 ; k < kNPhi ; k++ ) {
119     delete fLookUpErOverEz[k];
120     delete fLookUpEphiOverEz[k];
121     delete fLookUpDeltaEz[k];
122   }
123
124   for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
125     delete fLookUpBasic1ErOverEz[k];  // does nothing if pointer is zero!
126     delete fLookUpBasic1EphiOverEz[k]; 
127     delete fLookUpBasic1DeltaEz[k]; 
128
129     delete fLookUpBasic2ErOverEz[k];  // does nothing if pointer is zero!
130     delete fLookUpBasic2EphiOverEz[k]; 
131     delete fLookUpBasic2DeltaEz[k]; 
132     
133     delete fLookUpBasic3ErOverEz[k];  // does nothing if pointer is zero!
134     delete fLookUpBasic3EphiOverEz[k]; 
135     delete fLookUpBasic3DeltaEz[k]; 
136
137     delete fLookUpBasic4ErOverEz[k];  // does nothing if pointer is zero!
138     delete fLookUpBasic4EphiOverEz[k]; 
139     delete fLookUpBasic4DeltaEz[k]; 
140
141     delete fLookUpBasic5ErOverEz[k];  // does nothing if pointer is zero!
142     delete fLookUpBasic5EphiOverEz[k]; 
143     delete fLookUpBasic5DeltaEz[k]; 
144
145     delete fLookUpBasic6ErOverEz[k];  // does nothing if pointer is zero!
146     delete fLookUpBasic6EphiOverEz[k]; 
147     delete fLookUpBasic6DeltaEz[k]; 
148
149   }
150 }
151
152 void AliTPCFCVoltError3D::Init() {
153   //
154   // Initialization funtion
155   //
156   
157   AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
158   if (!magF) AliError("Magneticd field - not initialized");
159   Double_t bzField = magF->SolenoidField()/10.; //field in T
160   AliTPCParam *param= AliTPCcalibDB::Instance()->GetParameters();
161   if (!param) AliError("Parameters - not initialized");
162   Double_t vdrift = param->GetDriftV()/1000000.; // [cm/us]   // From dataBase: to be updated: per second (ideally)
163   Double_t ezField = 400; // [V/cm]   // to be updated: never (hopefully)
164   Double_t wt = -10.0 * (bzField*10) * vdrift / ezField ; 
165   // Correction Terms for effective omegaTau; obtained by a laser calibration run
166   SetOmegaTauT1T2(wt,fT1,fT2);
167
168   InitFCVoltError3D();
169 }
170
171 void AliTPCFCVoltError3D::Update(const TTimeStamp &/*timeStamp*/) {
172   //
173   // Update function 
174   //
175   AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
176   if (!magF) AliError("Magneticd field - not initialized");
177   Double_t bzField = magF->SolenoidField()/10.; //field in T
178   AliTPCParam *param= AliTPCcalibDB::Instance()->GetParameters();
179   if (!param) AliError("Parameters - not initialized");
180   Double_t vdrift = param->GetDriftV()/1000000.; // [cm/us]  // From dataBase: to be updated: per second (ideally)
181   Double_t ezField = 400; // [V/cm]   // to be updated: never (hopefully)
182   Double_t wt = -10.0 * (bzField*10) * vdrift / ezField ; 
183   // Correction Terms for effective omegaTau; obtained by a laser calibration run
184   SetOmegaTauT1T2(wt,fT1,fT2);
185
186
187 }
188
189
190
191 void AliTPCFCVoltError3D::GetCorrection(const Float_t x[],const Short_t roc,Float_t dx[]) {
192   //
193   // Calculates the correction due e.g. residual voltage errors on the TPC boundaries
194   //   
195
196   if (!fInitLookUp) {
197     AliInfo("Lookup table was not initialized! Perform the inizialisation now ...");
198     InitFCVoltError3D();
199   }
200
201   Int_t   order     = 1 ;               // FIXME: hardcoded? Linear interpolation = 1, Quadratic = 2         
202                                         // note that the poisson solution was linearly mirroed on this grid!
203   Double_t intEr, intEphi, intDeltaEz;
204   Double_t r, phi, z ;
205   Int_t    sign;
206
207   r      =  TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
208   phi    =  TMath::ATan2(x[1],x[0]) ;
209   if ( phi < 0 ) phi += TMath::TwoPi() ;                   // Table uses phi from 0 to 2*Pi
210   z      =  x[2] ;                                         // Create temporary copy of x[2]
211
212   if ( (roc%36) < 18 ) {
213     sign =  1;       // (TPC A side)
214   } else {
215     sign = -1;       // (TPC C side)
216   }
217   
218   if ( sign==1  && z <  fgkZOffSet ) z =  fgkZOffSet;    // Protect against discontinuity at CE
219   if ( sign==-1 && z > -fgkZOffSet ) z = -fgkZOffSet;    // Protect against discontinuity at CE
220   
221
222   if ( (sign==1 && z<0) || (sign==-1 && z>0) ) // just a consistency check
223     AliError("ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!");
224
225   // Get the Er and Ephi field integrals plus the integral over DeltaEz 
226   intEr      = Interpolate3DTable(order, r, z, phi, kNR, kNZ, kNPhi, 
227                                   fgkRList, fgkZList, fgkPhiList, fLookUpErOverEz  );
228   intEphi    = Interpolate3DTable(order, r, z, phi, kNR, kNZ, kNPhi, 
229                                   fgkRList, fgkZList, fgkPhiList, fLookUpEphiOverEz  );
230   intDeltaEz = Interpolate3DTable(order, r, z, phi, kNR, kNZ, kNPhi, 
231                                   fgkRList, fgkZList, fgkPhiList, fLookUpDeltaEz  );
232
233   //  printf("%lf %lf %lf\n",intEr,intEphi,intDeltaEz);
234
235   // Calculate distorted position
236   if ( r > 0.0 ) {
237     phi =  phi + ( fC0*intEphi - fC1*intEr ) / r;      
238     r   =  r   + ( fC0*intEr   + fC1*intEphi );  
239   }
240   
241   // Calculate correction in cartesian coordinates
242   dx[0] = r * TMath::Cos(phi) - x[0];
243   dx[1] = r * TMath::Sin(phi) - x[1]; 
244   dx[2] = intDeltaEz;  // z distortion - (internally scaled with driftvelocity dependency 
245                        // on the Ez field plus the actual ROC misalignment (if set TRUE)
246
247 }
248
249 void AliTPCFCVoltError3D::InitFCVoltError3D() {
250   //
251   // Initialization of the Lookup table which contains the solutions of the 
252   // Dirichlet boundary problem
253   // Calculation of the single 3D-Poisson solver is done just if needed
254   // (see basic lookup tables in header file)
255   //
256
257   const Int_t   order       =    1  ;  // Linear interpolation = 1, Quadratic = 2  
258   const Float_t gridSizeR   =  (fgkOFCRadius-fgkIFCRadius) / (kRows-1) ;
259   const Float_t gridSizeZ   =  fgkTPCZ0 / (kColumns-1) ;
260   const Float_t gridSizePhi =  TMath::TwoPi() / ( 18.0 * kPhiSlicesPerSector);
261
262   // temporary arrays to create the boundary conditions
263   TMatrixD *arrayofArrayV[kPhiSlices], *arrayofCharge[kPhiSlices] ; 
264   for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
265     arrayofArrayV[k]     =   new TMatrixD(kRows,kColumns) ;
266     arrayofCharge[k]     =   new TMatrixD(kRows,kColumns) ;
267   }
268   Double_t  innerList[kPhiSlices], outerList[kPhiSlices] ;
269   
270   // list of point as used in the poisson relation and the interpolation (during sum up)
271   Double_t  rlist[kRows], zedlist[kColumns] , philist[kPhiSlices];
272   for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
273     philist[k] =  gridSizePhi * k;
274     for ( Int_t i = 0 ; i < kRows ; i++ )    {
275       rlist[i] = fgkIFCRadius + i*gridSizeR ;
276       for ( Int_t j = 0 ; j < kColumns ; j++ ) { // Fill Vmatrix with Boundary Conditions
277         zedlist[j]  = j * gridSizeZ ;
278       }
279     }
280   }
281
282   // ==========================================================================
283   // Solve Poisson's equation in 3D cylindrical coordinates by relaxation technique
284   // Allow for different size grid spacing in R and Z directions
285   
286   const Int_t   symmetry[6] =    {1,1,-1,-1,1,1}; // shifted rod (2x), rotated clip (2x), only rod shift on OFC (1x)
287
288   // check which lookup tables are needed ---------------------------------
289
290   Bool_t needTable[6] ={kFALSE,kFALSE,kFALSE,kFALSE,kFALSE,kFALSE};
291
292   // Shifted rods & strips
293   for ( Int_t rod = 0 ; rod < 18 ; rod++ ) {
294     if (fRodVoltShiftA[rod]!=0) needTable[0]=kTRUE;
295     if (fRodVoltShiftC[rod]!=0) needTable[0]=kTRUE;
296   }
297   for ( Int_t rod = 18 ; rod < 36 ; rod++ ) {
298     if (fRodVoltShiftA[rod]!=0) needTable[1]=kTRUE;
299     if (fRodVoltShiftC[rod]!=0) needTable[1]=kTRUE;
300   }
301   // Rotated clips
302   if (fRotatedClipVoltA[0]!=0 || fRotatedClipVoltC[0]!=0) needTable[2]=kTRUE;
303   if (fRotatedClipVoltA[1]!=0 || fRotatedClipVoltC[1]!=0) needTable[3]=kTRUE;
304  
305   // shifted Copper rods 
306   for ( Int_t rod = 0 ; rod < 18 ; rod++ ) {
307     if (fCopperRodShiftA[rod]!=0) needTable[4]=kTRUE;
308     if (fCopperRodShiftC[rod]!=0) needTable[4]=kTRUE;
309   }
310   // shifted Copper rods 
311   for ( Int_t rod = 18; rod < 36 ; rod++ ) {
312     if (fCopperRodShiftA[rod]!=0) needTable[5]=kTRUE;
313     if (fCopperRodShiftC[rod]!=0) needTable[5]=kTRUE;
314   }
315
316
317   // reserve the arrays for the basic lookup tables ----------------------
318   if (needTable[0] && !fInitLookUpBasic[0]) {
319     for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {   // Possibly make an extra table to be used for 0 == 360
320       fLookUpBasic1ErOverEz[k]   =   new TMatrixD(kRows,kColumns);
321       fLookUpBasic1EphiOverEz[k] =   new TMatrixD(kRows,kColumns);
322       fLookUpBasic1DeltaEz[k]    =   new TMatrixD(kRows,kColumns);
323       // will be deleted in destructor
324     }
325   }
326   if (needTable[1] && !fInitLookUpBasic[1]) {
327     for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {   // Possibly make an extra table to be used for 0 == 360
328       fLookUpBasic2ErOverEz[k]   =   new TMatrixD(kRows,kColumns);
329       fLookUpBasic2EphiOverEz[k] =   new TMatrixD(kRows,kColumns);
330       fLookUpBasic2DeltaEz[k]    =   new TMatrixD(kRows,kColumns);
331       // will be deleted in destructor
332     }
333   }
334   if (needTable[2] && !fInitLookUpBasic[2]) {
335     for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {   // Possibly make an extra table to be used for 0 == 360
336       fLookUpBasic3ErOverEz[k]   =   new TMatrixD(kRows,kColumns);
337       fLookUpBasic3EphiOverEz[k] =   new TMatrixD(kRows,kColumns);
338       fLookUpBasic3DeltaEz[k]    =   new TMatrixD(kRows,kColumns);
339       // will be deleted in destructor
340     }
341   }
342   if (needTable[3] && !fInitLookUpBasic[3]) {
343     for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {   // Possibly make an extra table to be used for 0 == 360
344       fLookUpBasic4ErOverEz[k]   =   new TMatrixD(kRows,kColumns);
345       fLookUpBasic4EphiOverEz[k] =   new TMatrixD(kRows,kColumns);
346       fLookUpBasic4DeltaEz[k]    =   new TMatrixD(kRows,kColumns);
347       // will be deleted in destructor
348     }
349   }
350   if (needTable[4] && !fInitLookUpBasic[4]) {
351     for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {   // Possibly make an extra table to be used for 0 == 360
352       fLookUpBasic5ErOverEz[k]   =   new TMatrixD(kRows,kColumns);
353       fLookUpBasic5EphiOverEz[k] =   new TMatrixD(kRows,kColumns);
354       fLookUpBasic5DeltaEz[k]    =   new TMatrixD(kRows,kColumns);
355       // will be deleted in destructor
356     }
357   }
358   if (needTable[5] && !fInitLookUpBasic[5]) {
359     for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {   // Possibly make an extra table to be used for 0 == 360
360       fLookUpBasic6ErOverEz[k]   =   new TMatrixD(kRows,kColumns);
361       fLookUpBasic6EphiOverEz[k] =   new TMatrixD(kRows,kColumns);
362       fLookUpBasic6DeltaEz[k]    =   new TMatrixD(kRows,kColumns);
363       // will be deleted in destructor
364     }
365   }
366  
367   // Set bondaries and solve Poisson's equation --------------------------
368  
369   for (Int_t look=0; look<6; look++) {
370    
371     Float_t inner18[18] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;  
372     Float_t outer18[18] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ; 
373   
374     if (needTable[look] && !fInitLookUpBasic[look]) {
375
376       // Specify which rod is the reference; other distortions calculated by summing over multiple rotations of refrence
377       // Note: the interpolation later on depends on it!! Do not change if not really needed!
378       if (look==0) {
379         AliInfo(Form("IFC - ROD&Strip shift : Filling table (~ %d sec)",3*(int)(kPhiSlices/5)));
380         inner18[0] = 1;  
381       } else if (look==1) {
382         AliInfo(Form("OFC - ROD&Strip shift : Filling table (~ %d sec)",3*(int)(kPhiSlices/5)));
383         outer18[0] = 1;  
384       } else if (look==2) {
385         AliInfo(Form("IFC - Clip rot. : Filling table (~ %d sec)",3*(int)(kPhiSlices/5)));
386         inner18[0] = 1; 
387       } else if (look==3) {
388         AliInfo(Form("OFC - Clip rot. : Filling table (~ %d sec)",3*(int)(kPhiSlices/5)));
389         outer18[0] = 1;  
390       } else if (look==4) {
391         AliInfo(Form("IFC - CopperRod shift : Filling table (~ %d sec)",3*(int)(kPhiSlices/5)));
392         inner18[0] = 1;  
393       } else if (look==5) {
394         AliInfo(Form("OFC - CopperRod shift : Filling table (~ %d sec)",3*(int)(kPhiSlices/5)));
395         outer18[0] = 1;  
396       }
397       // Build potentials on boundary stripes for a rotated clip (SYMMETRY==-1) or a shifted rod (SYMMETRY==1)
398       if (look<4) {
399         // in these cases, the strips follow the actual rod shift (linear interpolation between the rods)
400         for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
401           Int_t slices = kPhiSlicesPerSector ;
402           Int_t ipoint = k/slices  ;  
403           innerList[k] = (((ipoint+1)*slices-k)*inner18[ipoint]-(k-ipoint*slices)*inner18[ipoint+1])/slices ;
404           outerList[k] = (((ipoint+1)*slices-k)*outer18[ipoint]-(k-ipoint*slices)*outer18[ipoint+1])/slices ;
405           if ( (k%slices) == 0 && symmetry[look] == -1 ) { innerList[k] = 0.0 ; outerList[k] = 0.0 ; } 
406           // above, force Zero if Anti-Sym
407         } 
408       } else if (look==4){
409         // in this case, we assume that the strips stay at the correct position, but the rods move
410         // the distortion is then much more localized around the rod (indicated by real data)
411         for ( Int_t k = 0 ; k < kPhiSlices ; k++ )
412           innerList[k] = outerList[k] = 0;
413         innerList[0] = inner18[0];     // point at rod
414         innerList[0] = inner18[0]/4*3;  // point close to rod (educated guess)
415       } else if (look==5){
416         // in this case, we assume that the strips stay at the correct position, but the copper plated OFC-rods move
417         // the distortion is then much more localized around the rod (indicated by real data)
418         for ( Int_t k = 0 ; k < kPhiSlices ; k++ )
419           innerList[k] = outerList[k] = 0;
420         outerList[0] = outer18[0];   // point at rod
421         outerList[1] = outer18[0]/4; // point close to rod (educated-`guessed` scaling)
422       }
423
424       // Fill arrays with initial conditions.  V on the boundary and Charge in the volume.
425       for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
426         TMatrixD &arrayV    =  *arrayofArrayV[k] ;
427         TMatrixD &charge    =  *arrayofCharge[k] ;
428         for ( Int_t i = 0 ; i < kRows ; i++ )    {
429           for ( Int_t j = 0 ; j < kColumns ; j++ ) { // Fill Vmatrix with Boundary Conditions
430             arrayV(i,j) = 0.0 ; 
431             charge(i,j) = 0.0 ;
432             if ( i == 0 )       arrayV(i,j) = innerList[k] ; 
433             if ( i == kRows-1 ) arrayV(i,j) = outerList[k] ; 
434           }
435         }      
436         // no charge in the volume
437         for ( Int_t i = 1 ; i < kRows-1 ; i++ )  { 
438           for ( Int_t j = 1 ; j < kColumns-1 ; j++ ) {
439             charge(i,j)  =  0.0 ;
440           }
441         }
442       }      
443      
444       // Solve Poisson's equation in 3D cylindrical coordinates by relaxation technique
445       // Allow for different size grid spacing in R and Z directions
446       if (look==0) {
447         PoissonRelaxation3D( arrayofArrayV, arrayofCharge, 
448                              fLookUpBasic1ErOverEz, fLookUpBasic1EphiOverEz, fLookUpBasic1DeltaEz,
449                              kRows, kColumns, kPhiSlices, gridSizePhi, kIterations, symmetry[0]) ;
450         AliInfo("IFC - ROD&Strip shift : done ");
451       } else if (look==1) {
452         PoissonRelaxation3D( arrayofArrayV, arrayofCharge, 
453                              fLookUpBasic2ErOverEz, fLookUpBasic2EphiOverEz, fLookUpBasic2DeltaEz,
454                              kRows, kColumns, kPhiSlices, gridSizePhi, kIterations, symmetry[1]) ;
455         
456         AliInfo("OFC - ROD&Strip shift : done ");
457       } else if (look==2) {
458         PoissonRelaxation3D( arrayofArrayV, arrayofCharge, 
459                              fLookUpBasic3ErOverEz, fLookUpBasic3EphiOverEz, fLookUpBasic3DeltaEz,
460                              kRows, kColumns, kPhiSlices, gridSizePhi, kIterations, symmetry[2]) ;
461         AliInfo("IFC - Clip rot. : done ");
462       } else if (look==3) {
463         PoissonRelaxation3D( arrayofArrayV, arrayofCharge, 
464                              fLookUpBasic4ErOverEz, fLookUpBasic4EphiOverEz, fLookUpBasic4DeltaEz,
465                              kRows, kColumns, kPhiSlices, gridSizePhi, kIterations, symmetry[3]) ;
466         AliInfo("OFC - Clip rot. : done ");
467       } else if (look==4) {
468         PoissonRelaxation3D( arrayofArrayV, arrayofCharge, 
469                              fLookUpBasic5ErOverEz, fLookUpBasic5EphiOverEz, fLookUpBasic5DeltaEz,
470                              kRows, kColumns, kPhiSlices, gridSizePhi, kIterations, symmetry[4]) ;
471         AliInfo("IFC - CopperRod shift : done ");
472       } else if (look==5) {
473         PoissonRelaxation3D( arrayofArrayV, arrayofCharge, 
474                              fLookUpBasic6ErOverEz, fLookUpBasic6EphiOverEz, fLookUpBasic6DeltaEz,
475                              kRows, kColumns, kPhiSlices, gridSizePhi, kIterations, symmetry[5]) ;
476         AliInfo("OFC - CopperRod shift : done ");
477       }
478       
479       fInitLookUpBasic[look] = kTRUE;
480     }
481   }
482   
483
484   // =============================================================================
485   // Create the final lookup table with corresponding ROD shifts or clip rotations
486
487   Float_t erIntegralSum   = 0.0 ;
488   Float_t ephiIntegralSum = 0.0 ;
489   Float_t ezIntegralSum   = 0.0 ;
490
491   Double_t phiPrime     = 0. ;
492   Double_t erIntegral   = 0. ;
493   Double_t ephiIntegral = 0. ;
494   Double_t ezIntegral   = 0. ;
495
496
497   AliInfo("Calculation of combined Look-up Table");
498
499   // Interpolate and sum the Basic lookup tables onto the standard grid
500   Double_t  r, phi, z ;
501   for ( Int_t k = 0 ; k < kNPhi ; k++ ) {
502     phi = fgkPhiList[k] ;
503
504     TMatrixD &erOverEz   =  *fLookUpErOverEz[k]  ;
505     TMatrixD &ephiOverEz =  *fLookUpEphiOverEz[k];
506     TMatrixD &deltaEz    =  *fLookUpDeltaEz[k]   ;
507
508     for ( Int_t i = 0 ; i < kNZ ; i++ ) {
509       z = TMath::Abs(fgkZList[i]) ;  // Symmetric solution in Z that depends only on ABS(Z)
510       for ( Int_t j = 0 ; j < kNR ; j++ ) { 
511         r = fgkRList[j] ;
512         // Interpolate basicLookup tables; once for each rod, then sum the results
513         
514         erIntegralSum   = 0.0 ;
515         ephiIntegralSum = 0.0 ;
516         ezIntegralSum   = 0.0 ;
517  
518         // SHIFTED RODS =========================================================
519
520         // IFC ROD SHIFTS +++++++++++++++++++++++++++++
521         for ( Int_t rod = 0 ; rod < 18 ; rod++ ) {
522           
523           erIntegral = ephiIntegral = ezIntegral = 0.0 ;
524           
525           if ( fRodVoltShiftA[rod] == 0 && fgkZList[i] > 0) continue ;
526           if ( fRodVoltShiftC[rod] == 0 && fgkZList[i] < 0) continue ;
527
528           // Rotate to a position where we have maps and prepare to sum
529           phiPrime =  phi - rod*kPhiSlicesPerSector*gridSizePhi ;  
530
531           if ( phiPrime < 0 ) phiPrime += TMath::TwoPi() ;   // Stay in range from 0 to TwoPi    
532
533           if ( (phiPrime >= 0) && (phiPrime <= kPhiSlices*gridSizePhi) ) {
534             
535             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
536                                               rlist, zedlist, philist, fLookUpBasic1ErOverEz  );
537             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
538                                               rlist, zedlist, philist, fLookUpBasic1EphiOverEz);
539             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
540                                               rlist, zedlist, philist, fLookUpBasic1DeltaEz   );
541             
542           }  else if ( (phiPrime <= TMath::TwoPi()) && (phiPrime >= (TMath::TwoPi()-kPhiSlices*gridSizePhi)) ){
543             
544             phiPrime     = TMath::TwoPi() - phiPrime ;
545             
546             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
547                                               rlist, zedlist, philist, fLookUpBasic1ErOverEz  );
548             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
549                                               rlist, zedlist, philist, fLookUpBasic1EphiOverEz);
550             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
551                                               rlist, zedlist, philist, fLookUpBasic1DeltaEz   );
552             
553             // Flip symmetry of phi integral for symmetric boundary conditions
554             if ( symmetry[0] ==  1 ) ephiIntegral *= -1  ;    
555             // Flip symmetry of r integral if anti-symmetric boundary conditions 
556             if ( symmetry[0] == -1 ) erIntegral   *= -1  ;    
557
558           }
559
560           if ( fgkZList[i] > 0 ) {
561             erIntegralSum   += fRodVoltShiftA[rod]*erIntegral   ;
562             ephiIntegralSum += fRodVoltShiftA[rod]*ephiIntegral ;
563             ezIntegralSum   += fRodVoltShiftA[rod]*ezIntegral;
564           } else if ( fgkZList[i] < 0 ) {
565             erIntegralSum   += fRodVoltShiftC[rod]*erIntegral   ;
566             ephiIntegralSum += fRodVoltShiftC[rod]*ephiIntegral ;
567             ezIntegralSum   -= fRodVoltShiftC[rod]*ezIntegral;
568           }
569         }
570
571         // OFC ROD SHIFTS +++++++++++++++++++++++++++++
572         for ( Int_t rod = 18 ; rod < 36 ; rod++ ) {
573
574           erIntegral = ephiIntegral = ezIntegral = 0.0 ;
575           
576           if ( fRodVoltShiftA[rod] == 0 && fgkZList[i] > 0) continue ;
577           if ( fRodVoltShiftC[rod] == 0 && fgkZList[i] < 0) continue ;
578
579           // Rotate to a position where we have maps and prepare to sum
580           phiPrime =  phi - (rod-18)*kPhiSlicesPerSector*gridSizePhi ;  
581
582                   
583           if ( phiPrime < 0 ) phiPrime += TMath::TwoPi() ;   // Stay in range from 0 to TwoPi    
584
585           if ( (phiPrime >= 0) && (phiPrime <= kPhiSlices*gridSizePhi) ) {
586             
587             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
588                                               rlist, zedlist, philist, fLookUpBasic2ErOverEz  );
589             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
590                                               rlist, zedlist, philist, fLookUpBasic2EphiOverEz);
591             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
592                                               rlist, zedlist, philist, fLookUpBasic2DeltaEz   );
593             
594           }  else if ( (phiPrime <= TMath::TwoPi()) && (phiPrime >= (TMath::TwoPi()-kPhiSlices*gridSizePhi)) ){
595             
596             phiPrime     = TMath::TwoPi() - phiPrime ;
597             
598             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
599                                               rlist, zedlist, philist, fLookUpBasic2ErOverEz  );
600             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
601                                               rlist, zedlist, philist, fLookUpBasic2EphiOverEz);
602             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
603                                               rlist, zedlist, philist, fLookUpBasic2DeltaEz   );
604             
605             // Flip symmetry of phi integral for symmetric boundary conditions
606             if ( symmetry[1] ==  1 ) ephiIntegral *= -1  ;    
607             // Flip symmetry of r integral if anti-symmetric boundary conditions 
608             if ( symmetry[1] == -1 ) erIntegral   *= -1  ;    
609
610           }
611
612           if ( fgkZList[i] > 0 ) {
613             erIntegralSum   += fRodVoltShiftA[rod]*erIntegral   ;
614             ephiIntegralSum += fRodVoltShiftA[rod]*ephiIntegral ;
615             ezIntegralSum   += fRodVoltShiftA[rod]*ezIntegral;
616           } else if ( fgkZList[i] < 0 ) {
617             erIntegralSum   += fRodVoltShiftC[rod]*erIntegral   ;
618             ephiIntegralSum += fRodVoltShiftC[rod]*ephiIntegral ;
619             ezIntegralSum   -= fRodVoltShiftC[rod]*ezIntegral;
620           }
621
622         } // rod loop - shited ROD
623
624
625         // Rotated clips =========================================================
626
627         Int_t rodIFC = 11; // resistor rod positions, IFC
628         Int_t rodOFC =  3; // resistor rod positions, OFC
629         // just one rod on IFC and OFC
630
631         // IFC ROTATED CLIP +++++++++++++++++++++++++++++
632         for ( Int_t rod = rodIFC ; rod < rodIFC+1 ; rod++ ) { // loop over 1 to keep the "ignore"-functionality
633
634           erIntegral = ephiIntegral = ezIntegral = 0.0 ;
635           if ( fRotatedClipVoltA[0] == 0 && fgkZList[i] > 0) continue ;
636           if ( fRotatedClipVoltC[0] == 0 && fgkZList[i] < 0) continue ;
637
638           // Rotate to a position where we have maps and prepare to sum
639           phiPrime =  phi - rod*kPhiSlicesPerSector*gridSizePhi ;  
640           
641           if ( phiPrime < 0 ) phiPrime += TMath::TwoPi() ;   // Stay in range from 0 to TwoPi    
642           
643           if ( (phiPrime >= 0) && (phiPrime <= kPhiSlices*gridSizePhi) ) {
644             
645             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
646                                               rlist, zedlist, philist, fLookUpBasic3ErOverEz  );
647             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
648                                               rlist, zedlist, philist, fLookUpBasic3EphiOverEz);
649             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
650                                               rlist, zedlist, philist, fLookUpBasic3DeltaEz   );
651             
652           }  else if ( (phiPrime <= TMath::TwoPi()) && (phiPrime >= (TMath::TwoPi()-kPhiSlices*gridSizePhi)) ){
653             
654             phiPrime     = TMath::TwoPi() - phiPrime ;
655             
656             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
657                                               rlist, zedlist, philist, fLookUpBasic3ErOverEz  );
658             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
659                                               rlist, zedlist, philist, fLookUpBasic3EphiOverEz);
660             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
661                                               rlist, zedlist, philist, fLookUpBasic3DeltaEz   );
662             
663             // Flip symmetry of phi integral for symmetric boundary conditions
664             if ( symmetry[2] ==  1 ) ephiIntegral *= -1  ;    
665             // Flip symmetry of r integral if anti-symmetric boundary conditions 
666             if ( symmetry[2] == -1 ) erIntegral   *= -1  ;    
667             
668           }
669           
670           if ( fgkZList[i] > 0 ) {
671             erIntegralSum   += fRotatedClipVoltA[0]*erIntegral   ;
672             ephiIntegralSum += fRotatedClipVoltA[0]*ephiIntegral ;
673             ezIntegralSum   += fRotatedClipVoltA[0]*ezIntegral;
674           } else if ( fgkZList[i] < 0 ) {
675             erIntegralSum   += fRotatedClipVoltC[0]*erIntegral   ;
676             ephiIntegralSum += fRotatedClipVoltC[0]*ephiIntegral ;
677             ezIntegralSum   -= fRotatedClipVoltC[0]*ezIntegral;
678           }
679         }
680
681         // OFC: ROTATED CLIP  +++++++++++++++++++++++++++++
682         for ( Int_t rod = rodOFC ; rod < rodOFC+1 ; rod++ ) { // loop over 1 to keep the "ignore"-functionality
683           
684           erIntegral = ephiIntegral = ezIntegral = 0.0 ;
685           
686           if ( fRotatedClipVoltA[1] == 0 && fgkZList[i] > 0) continue ;
687           if ( fRotatedClipVoltC[1] == 0 && fgkZList[i] < 0) continue ;
688
689           // Rotate to a position where we have maps and prepare to sum
690           phiPrime =  phi - rod*kPhiSlicesPerSector*gridSizePhi ;  
691           
692           
693           if ( phiPrime < 0 ) phiPrime += TMath::TwoPi() ;   // Stay in range from 0 to TwoPi    
694           
695           if ( (phiPrime >= 0) && (phiPrime <= kPhiSlices*gridSizePhi) ) {
696             
697             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
698                                               rlist, zedlist, philist, fLookUpBasic4ErOverEz  );
699             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
700                                               rlist, zedlist, philist, fLookUpBasic4EphiOverEz);
701             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
702                                               rlist, zedlist, philist, fLookUpBasic4DeltaEz   );
703             
704           }  else if ( (phiPrime <= TMath::TwoPi()) && (phiPrime >= (TMath::TwoPi()-kPhiSlices*gridSizePhi)) ){
705             
706             phiPrime     = TMath::TwoPi() - phiPrime ;
707             
708             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
709                                               rlist, zedlist, philist, fLookUpBasic4ErOverEz  );
710             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
711                                               rlist, zedlist, philist, fLookUpBasic4EphiOverEz);
712             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
713                                               rlist, zedlist, philist, fLookUpBasic4DeltaEz   );
714             
715             // Flip symmetry of phi integral for symmetric boundary conditions
716             if ( symmetry[3] ==  1 ) ephiIntegral *= -1  ;    
717             // Flip symmetry of r integral if anti-symmetric boundary conditions 
718             if ( symmetry[3] == -1 ) erIntegral   *= -1  ;    
719             
720           }
721           
722           if ( fgkZList[i] > 0 ) {
723             erIntegralSum   += fRotatedClipVoltA[1]*erIntegral   ;
724             ephiIntegralSum += fRotatedClipVoltA[1]*ephiIntegral ;
725             ezIntegralSum   += fRotatedClipVoltA[1]*ezIntegral;
726           } else if ( fgkZList[i] < 0 ) {
727             erIntegralSum   += fRotatedClipVoltC[1]*erIntegral   ;
728             ephiIntegralSum += fRotatedClipVoltC[1]*ephiIntegral ;
729             ezIntegralSum   -= fRotatedClipVoltC[1]*ezIntegral;
730           }
731         }
732
733         // IFC Cooper rod shift  +++++++++++++++++++++++++++++
734         for ( Int_t rod = 0 ; rod < 18 ; rod++ ) {
735           
736           erIntegral = ephiIntegral = ezIntegral = 0.0 ;
737           
738           if ( fCopperRodShiftA[rod] == 0 && fgkZList[i] > 0) continue ;
739           if ( fCopperRodShiftC[rod] == 0 && fgkZList[i] < 0) continue ;
740
741           // Rotate to a position where we have maps and prepare to sum
742           phiPrime =  phi - rod*kPhiSlicesPerSector*gridSizePhi ;  
743
744           if ( phiPrime < 0 ) phiPrime += TMath::TwoPi() ;   // Stay in range from 0 to TwoPi    
745
746           if ( (phiPrime >= 0) && (phiPrime <= kPhiSlices*gridSizePhi) ) {
747             
748             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
749                                               rlist, zedlist, philist, fLookUpBasic5ErOverEz  );
750             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
751                                               rlist, zedlist, philist, fLookUpBasic5EphiOverEz);
752             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
753                                               rlist, zedlist, philist, fLookUpBasic5DeltaEz   );
754             
755           }  else if ( (phiPrime <= TMath::TwoPi()) && (phiPrime >= (TMath::TwoPi()-kPhiSlices*gridSizePhi)) ){
756             
757             phiPrime     = TMath::TwoPi() - phiPrime ;
758             
759             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
760                                               rlist, zedlist, philist, fLookUpBasic5ErOverEz  );
761             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
762                                               rlist, zedlist, philist, fLookUpBasic5EphiOverEz);
763             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
764                                               rlist, zedlist, philist, fLookUpBasic5DeltaEz   );
765             
766             // Flip symmetry of phi integral for symmetric boundary conditions
767             if ( symmetry[4] ==  1 ) ephiIntegral *= -1  ;    
768             // Flip symmetry of r integral if anti-symmetric boundary conditions 
769             if ( symmetry[4] == -1 ) erIntegral   *= -1  ;    
770
771           }
772
773           if ( fgkZList[i] > 0 ) {
774             erIntegralSum   += fCopperRodShiftA[rod]*erIntegral   ;
775             ephiIntegralSum += fCopperRodShiftA[rod]*ephiIntegral ;
776             ezIntegralSum   += fCopperRodShiftA[rod]*ezIntegral;
777           } else if ( fgkZList[i] < 0 ) {
778             erIntegralSum   += fCopperRodShiftC[rod]*erIntegral   ;
779             ephiIntegralSum += fCopperRodShiftC[rod]*ephiIntegral ;
780             ezIntegralSum   -= fCopperRodShiftC[rod]*ezIntegral;
781           }
782         }
783
784         // OFC Cooper rod shift  +++++++++++++++++++++++++++++
785         for ( Int_t rod = 18 ; rod < 36 ; rod++ ) {
786           
787           erIntegral = ephiIntegral = ezIntegral = 0.0 ;
788           
789           if ( fCopperRodShiftA[rod] == 0 && fgkZList[i] > 0) continue ;
790           if ( fCopperRodShiftC[rod] == 0 && fgkZList[i] < 0) continue ;
791
792           // Rotate to a position where we have maps and prepare to sum
793           phiPrime =  phi - rod*kPhiSlicesPerSector*gridSizePhi ;  
794
795           if ( phiPrime < 0 ) phiPrime += TMath::TwoPi() ;   // Stay in range from 0 to TwoPi    
796
797           if ( (phiPrime >= 0) && (phiPrime <= kPhiSlices*gridSizePhi) ) {
798             
799             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
800                                               rlist, zedlist, philist, fLookUpBasic6ErOverEz  );
801             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
802                                               rlist, zedlist, philist, fLookUpBasic6EphiOverEz);
803             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
804                                               rlist, zedlist, philist, fLookUpBasic6DeltaEz   );
805             
806           }  else if ( (phiPrime <= TMath::TwoPi()) && (phiPrime >= (TMath::TwoPi()-kPhiSlices*gridSizePhi)) ){
807             
808             phiPrime     = TMath::TwoPi() - phiPrime ;
809             
810             erIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices, 
811                                               rlist, zedlist, philist, fLookUpBasic6ErOverEz  );
812             ephiIntegral = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
813                                               rlist, zedlist, philist, fLookUpBasic6EphiOverEz);
814             ezIntegral   = Interpolate3DTable(order, r, z, phiPrime, kRows, kColumns, kPhiSlices,
815                                               rlist, zedlist, philist, fLookUpBasic6DeltaEz   );
816             
817             // Flip symmetry of phi integral for symmetric boundary conditions
818             if ( symmetry[5] ==  1 ) ephiIntegral *= -1  ;    
819             // Flip symmetry of r integral if anti-symmetric boundary conditions 
820             if ( symmetry[5] == -1 ) erIntegral   *= -1  ;    
821
822           }
823
824           if ( fgkZList[i] > 0 ) {
825             erIntegralSum   += fCopperRodShiftA[rod]*erIntegral   ;
826             ephiIntegralSum += fCopperRodShiftA[rod]*ephiIntegral ;
827             ezIntegralSum   += fCopperRodShiftA[rod]*ezIntegral;
828           } else if ( fgkZList[i] < 0 ) {
829             erIntegralSum   += fCopperRodShiftC[rod]*erIntegral   ;
830             ephiIntegralSum += fCopperRodShiftC[rod]*ephiIntegral ;
831             ezIntegralSum   -= fCopperRodShiftC[rod]*ezIntegral;
832           }
833         }
834
835         // put the sum into the final lookup table
836         erOverEz(j,i)   =  erIntegralSum;
837         ephiOverEz(j,i) =  ephiIntegralSum;
838         deltaEz(j,i)    =  ezIntegralSum;
839         
840         //      if (j==1) printf("%lf %lf %lf: %lf %lf %lf\n",r, phi, z, erIntegralSum,ephiIntegralSum,ezIntegralSum);
841  
842       } // endo r loop
843     } // end of z loop
844   } // end of phi loop
845
846
847   // clear the temporary arrays lists
848   for ( Int_t k = 0 ; k < kPhiSlices ; k++ )  {
849     delete arrayofArrayV[k];
850     delete arrayofCharge[k];
851   }
852  
853   AliInfo(" done");
854   fInitLookUp = kTRUE;
855
856 }
857
858 void AliTPCFCVoltError3D::Print(const Option_t* option) const {
859   //
860   // Print function to check the settings of the Rod shifts and the rotated clips
861   // option=="a" prints the C0 and C1 coefficents for calibration purposes
862   //
863
864   TString opt = option; opt.ToLower();
865   printf("%s\n",GetTitle());
866   printf(" - ROD shifts  (residual voltage settings): 40V correspond to 1mm of shift\n");
867   Int_t count = 0;
868   printf("  : A-side - (Rod & Strips) \n     "); 
869   for (Int_t i=0; i<36;i++) {
870     if (fRodVoltShiftA[i]!=0) {
871       printf("Rod%2d:%3.1fV ",i,fRodVoltShiftA[i]);
872       count++;
873     }
874     if (count==0&&i==35) 
875       printf("-> all at 0 V\n");
876     else if (i==35){
877       printf("\n");
878       count=0;
879     }
880   } 
881   printf("  : C-side - (Rod & Strips) \n     "); 
882   for (Int_t i=0; i<36;i++) {
883     if (fRodVoltShiftC[i]!=0) {
884       printf("Rod%2d:%3.1fV ",i,fRodVoltShiftC[i]);
885       count++;
886     }
887     if (count==0&&i==35) 
888       printf("-> all at 0 V\n");
889     else if (i==35){
890       printf("\n");
891       count=0;
892     }
893   } 
894  
895   printf(" - Rotated clips (residual voltage settings): 40V correspond to 1mm of 'offset'\n");
896   if (fRotatedClipVoltA[0]!=0) {   printf("     A side (IFC): HV Rod: %3.1f V \n",fRotatedClipVoltA[0]); count++; }
897   if (fRotatedClipVoltA[1]!=0) {   printf("     A side (OFC): HV Rod: %3.1f V \n",fRotatedClipVoltA[1]); count++; }
898   if (fRotatedClipVoltC[0]!=0) {   printf("     C side (IFC): HV Rod: %3.1f V \n",fRotatedClipVoltC[0]); count++; }
899   if (fRotatedClipVoltC[1]!=0) {   printf("     C side (OFC): HV Rod: %3.1f V \n",fRotatedClipVoltC[1]); count++; }
900   if (count==0) 
901     printf("     -> no rotated clips \n");
902
903   count=0;
904   printf(" - Copper ROD shifts (without strips):\n");
905   printf("  : A-side - (Copper Rod shift) \n     "); 
906   for (Int_t i=0; i<36;i++) {
907     if (fCopperRodShiftA[i]!=0) {
908       printf("Rod%2d:%3.1fV ",i,fCopperRodShiftA[i]);
909       count++;
910     }
911     if (count==0&&i==35) 
912       printf("-> all at 0 V\n");
913     else if (i==35){
914       printf("\n");
915       count=0;
916     }
917   } 
918   printf("  : C-side - (Copper Rod shift) \n     "); 
919   for (Int_t i=0; i<36;i++) {
920     if (fCopperRodShiftC[i]!=0) {
921       printf("Rod%2d:%3.1fV ",i,fCopperRodShiftC[i]);
922       count++;
923     }
924     if (count==0&&i==35) 
925       printf("-> all at 0 V\n");
926     else if (i==35){
927       printf("\n");
928       count=0;
929     }
930   } 
931
932   if (opt.Contains("a")) { // Print all details
933     printf(" - T1: %1.4f, T2: %1.4f \n",fT1,fT2);
934     printf(" - C1: %1.4f, C0: %1.4f \n",fC1,fC0);
935   }
936
937   if (!fInitLookUp) AliError("Lookup table was not initialized! You should do InitFCVoltError3D() ...");
938
939 }