Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 2006-07, 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 : /// \class AliTPCCalibVdrift
18 : ///
19 : /// Class describing the Vdrift dependencies on E,T,P and GasComposition
20 : ///
21 : /// \author Stefan Rossegger, Haavard Helstrup
22 :
23 : #include "TSystem.h"
24 : #include "TObject.h"
25 : #include "TMath.h"
26 : #include "AliTPCTempMap.h"
27 : #include "AliTPCSensorTempArray.h"
28 :
29 : #include "AliTPCCalibVdrift.h"
30 :
31 : /// \cond CLASSIMP
32 24 : ClassImp(AliTPCCalibVdrift)
33 : /// \endcond
34 :
35 : namespace paramDefinitions {
36 :
37 : // Standard Conditions used as origin in the Magbolz simulations
38 : // Dimesions E [kV/cm], T [K], P [TORR], Cco2 [%], Cn2 [%]
39 : const Double_t kstdE = 400;
40 : const Double_t kstdT = 293;
41 : const Double_t kstdP = 744;
42 : const Double_t kstdCco2 = 9.52;
43 : const Double_t kstdCn2 = 4.76;
44 : // Driftvelocity at Standardcontitions [cm/microSec]
45 : const Double_t kstdVdrift = 2.57563;
46 :
47 : // Vdrift dependencies simulated with Magbolz [%(Vdrift)/[unit]]
48 : const Double_t kdvdE = 0.24;
49 : const Double_t kdvdT = 0.30;
50 : const Double_t kdvdP = -0.13;
51 : const Double_t kdvdCco2 = -6.60;
52 : const Double_t kdvdCn2 = -1.74;
53 : // 2nd order effect Taylor expansion
54 : const Double_t kdvdE2nd = -0.00107628;
55 : const Double_t kdvdT2nd = -0.00134441;
56 : const Double_t kdvdP2nd = 0.000135325;
57 : const Double_t kdvdCco22nd = 0.328761;
58 : const Double_t kdvdCn22nd = 0.151605;
59 :
60 : const Double_t torrTokPascal = 0.750061683;
61 :
62 : Double_t krho = 0.934246; // density of TPC-Gas [kg/m^3]
63 : // method of calculation: weighted average
64 : Double_t kg = 9.81;
65 :
66 : //
67 : // Nominal value obtained from 2008 data
68 : //
69 : const Double_t kKelvin =273.15; // degree to Kelvin
70 : const Double_t kNominalTemp =19.03; // mean between A and C side in degree
71 : const Double_t kNominalPress =973.9; // pressure sensor - in mbar-
72 : // calibDB->GetPressure(tstamp,irun,1)
73 : }
74 :
75 :
76 : using namespace paramDefinitions;
77 :
78 : AliTPCCalibVdrift::AliTPCCalibVdrift():
79 0 : TNamed(),
80 0 : fSensTemp(0),
81 0 : fSensPres(0),
82 0 : fTempMap(0),
83 0 : fSensGasComp(0),
84 0 : fNominalTemp(0), // nominal temperature in Kelvin
85 0 : fNominalPress(0) // nominal pressure in mbar
86 0 : {
87 : /// default constructor
88 :
89 0 : }
90 :
91 : AliTPCCalibVdrift::AliTPCCalibVdrift(AliTPCSensorTempArray *SensTemp, AliDCSSensor *SensPres, TObject *SensGasComp):
92 0 : TNamed(),
93 0 : fSensTemp(0),
94 0 : fSensPres(0),
95 0 : fTempMap(0),
96 0 : fSensGasComp(0),
97 0 : fNominalTemp(0), // nominal temperature in Kelvin
98 0 : fNominalPress(0) // nominal pressure in mbar
99 0 : {
100 : /// Standard constructor
101 :
102 0 : fSensTemp = SensTemp;
103 0 : fSensPres = SensPres;
104 0 : if (fSensTemp) {
105 0 : fTempMap = new AliTPCTempMap(fSensTemp);
106 0 : } else {
107 0 : fTempMap = 0;
108 : }
109 0 : fSensGasComp = SensGasComp;
110 0 : fNominalTemp = kNominalTemp;
111 0 : fNominalPress= kNominalPress;
112 0 : }
113 :
114 : //_____________________________________________________________________________
115 : AliTPCCalibVdrift::AliTPCCalibVdrift(const AliTPCCalibVdrift& source) :
116 0 : TNamed(source),
117 0 : fSensTemp(source.fSensTemp),
118 0 : fSensPres(source.fSensPres),
119 0 : fTempMap(source.fTempMap),
120 0 : fSensGasComp(source.fSensGasComp),
121 0 : fNominalTemp(source.fNominalTemp), // nominal temperature in Kelvin
122 0 : fNominalPress(source.fNominalPress) // nominal pressure in mbar
123 :
124 0 : {
125 : /// Copy constructor
126 :
127 0 : }
128 :
129 : //_____________________________________________________________________________
130 : AliTPCCalibVdrift& AliTPCCalibVdrift::operator=(const AliTPCCalibVdrift& source){
131 : /// assignment operator
132 :
133 0 : if (&source == this) return *this;
134 0 : new (this) AliTPCCalibVdrift(source);
135 :
136 0 : return *this;
137 0 : }
138 :
139 : //_____________________________________________________________________________
140 : AliTPCCalibVdrift::~AliTPCCalibVdrift()
141 0 : {
142 : /// AliTPCCalibVdrift destructor
143 :
144 0 : }
145 :
146 : //_____________________________________________________________________________
147 : Double_t AliTPCCalibVdrift::GetPTRelative(UInt_t absTimeSec, Int_t side){
148 : /// Get Relative difference of p/T for given time stamp
149 : /// absTimeSec - absolute time in secounds
150 : /// side: 0 - A side | 1 - C side
151 :
152 0 : TTimeStamp tstamp(absTimeSec);
153 :
154 0 : if (!fSensPres||!fSensTemp) return 0;
155 0 : Double_t pressure = fSensPres->GetValue(tstamp);
156 0 : TLinearFitter * fitter = fTempMap->GetLinearFitter(3,side,tstamp);
157 0 : if (!fitter) return 0;
158 0 : TVectorD vec;
159 0 : fitter->GetParameters(vec);
160 0 : delete fitter;
161 0 : if (vec[0]<10) return 0;
162 : //
163 : //
164 : //
165 0 : Double_t temperature = vec[0]; //vec[0] temeperature
166 0 : Double_t tpnom = (fNominalTemp+kKelvin)/(fNominalPress);
167 0 : Double_t tpmeasured = (temperature+kKelvin)/(pressure);
168 0 : Double_t result = (tpmeasured-tpnom)/tpnom;
169 :
170 : return result;
171 :
172 0 : }
173 :
174 :
175 : //_____________________________________________________________________________
176 : Double_t AliTPCCalibVdrift::VdriftLinearHyperplaneApprox(Double_t dE, Double_t dT, Double_t dP, Double_t dCco2, Double_t dCn2)
177 : {
178 : /// Returns approximated value for the driftvelocity change (in percent)
179 : /// based on a Hyperplane approximation (~ Taylorapproximation of 2nd order)
180 :
181 0 : Double_t termE = dE*kdvdE + TMath::Power(dE,2)*kdvdE2nd;
182 0 : Double_t termT = dT*kdvdT + TMath::Power(dT,2)*kdvdT2nd;
183 0 : Double_t termP = dP*kdvdP + TMath::Power(dP,2)*kdvdP2nd;
184 0 : Double_t termCo2 = dCco2*kdvdCco2 + TMath::Power(dCco2,2)*kdvdCco22nd;
185 0 : Double_t termN2 = dCn2*kdvdCn2 + TMath::Power(dCn2,2)*kdvdCn22nd;
186 :
187 0 : Double_t vdChange = termE+termT+termP+termCo2+termN2;
188 :
189 0 : return vdChange;
190 :
191 : }
192 :
193 : //_____________________________________________________________________________
194 :
195 : Double_t AliTPCCalibVdrift::GetVdriftNominal()
196 : {
197 : /// returns nominal Driftvelocity at StandardConditions
198 :
199 0 : return kstdVdrift;
200 : }
201 :
202 : //_____________________________________________________________________________
203 :
204 : Double_t AliTPCCalibVdrift::GetVdriftChange(Double_t x, Double_t y, Double_t z, UInt_t absTimeSec)
205 : {
206 : /// Calculates Vdrift change in percent of Vdrift_nominal
207 : /// (under nominal conditions) at x,y,z at absolute time (in sec)
208 :
209 0 : TTimeStamp tstamp(absTimeSec);
210 :
211 : // Get E-field Value --------------------------
212 : Double_t dE = 0.23; // StandardOffset if CE is set to 100kV
213 :
214 : // Get Temperature Value ----------------------
215 0 : AliTPCTempMap *tempMap = fTempMap;
216 : Double_t dT = 0;
217 0 : if (fTempMap) {
218 0 : Double_t tempValue = tempMap->GetTemperature(x, y, z, tstamp);
219 0 : dT = tempValue + 273.15 - kstdT;
220 0 : }
221 :
222 : // Get Main Pressure Value ---------------------
223 : Double_t dP = 0;
224 0 : if (fSensPres==0) {
225 : // Just the pressure drop over the TPC height
226 0 : dP = - krho*kg*y/10000*torrTokPascal;
227 0 : } else {
228 : // pressure sensors plus additional 0.4mbar overpressure within the TPC
229 0 : Double_t pressure = fSensPres->GetValue(tstamp) + 0.4;
230 : // calculate pressure drop according to height in TPC and transform to
231 : // TORR (with simplified hydrostatic formula)
232 0 : dP = (pressure - krho*kg*y/10000) * torrTokPascal - kstdP;
233 : }
234 :
235 : // Get GasComposition
236 : // FIXME: include Goofy values for CO2 and N2 conzentration out of OCDB
237 : // Goofy not yet reliable ...
238 : Double_t dCco2 = 0;
239 : Double_t dCn2 = 0;
240 :
241 : // Calculate change in drift velocity in terms of Vdrift_nominal
242 0 : Double_t vdChange = VdriftLinearHyperplaneApprox(dE, dT, dP, dCco2, dCn2);
243 :
244 : return vdChange;
245 :
246 0 : }
247 :
248 : //_____________________________________________________________________________
249 :
250 : Double_t AliTPCCalibVdrift::GetMeanZVdriftChange(Double_t x, Double_t y, UInt_t absTimeSec)
251 : {
252 : /// Calculates Meanvalue in z direction of Vdrift change in percent
253 : /// of Vdrift_nominal (under standard conditions) at position x,y,absTimeSec
254 : /// with help of 'nPopints' base points
255 :
256 : Int_t nPoints = 5;
257 :
258 : Double_t vdriftSum = 0;
259 :
260 0 : for (Int_t i = 0; i<nPoints; i++) {
261 0 : Double_t z = (Double_t)i/(nPoints-1)*500-250;
262 0 : vdriftSum = vdriftSum + GetVdriftChange(x, y, z, absTimeSec);
263 : }
264 :
265 0 : Double_t meanZVdrift = vdriftSum/nPoints;
266 :
267 0 : return meanZVdrift;
268 :
269 : }
270 :
271 : //_____________________________________________________________________________
272 :
273 : TGraph *AliTPCCalibVdrift::MakeGraphMeanZVdriftChange(Double_t x, Double_t y, Int_t nPoints)
274 : {
275 : /// Make graph from start time to end time of Mean Drift Velocity in
276 : /// Z direction at given x and y position
277 :
278 0 : UInt_t startTime = fSensTemp->GetStartTime();
279 0 : UInt_t endTime = fSensTemp->GetEndTime();
280 :
281 0 : UInt_t stepTime = (endTime - startTime)/nPoints;
282 :
283 :
284 0 : Double_t *xvec = new Double_t[nPoints];
285 0 : Double_t *yvec = new Double_t[nPoints];
286 :
287 0 : for (Int_t ip=0; ip<nPoints; ip++) {
288 0 : xvec[ip] = startTime+ip*stepTime;
289 0 : yvec[ip] = GetMeanZVdriftChange(x, y, fSensTemp->GetStartTime().GetSec() + ip*stepTime);
290 : }
291 :
292 0 : TGraph *graph = new TGraph(nPoints,xvec,yvec);
293 :
294 0 : delete [] xvec;
295 0 : delete [] yvec;
296 :
297 0 : graph->GetXaxis()->SetTimeDisplay(1);
298 0 : graph->GetXaxis()->SetLabelOffset(0.02);
299 0 : graph->GetXaxis()->SetTimeFormat("#splitline{%d/%m}{%H:%M}");
300 :
301 0 : return graph;
302 0 : }
|