StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StFtpcSlowSimField.cc
1 // $Id: StFtpcSlowSimField.cc,v 1.16 2007/05/15 14:35:18 jcs Exp $
2 // $Log: StFtpcSlowSimField.cc,v $
3 // Revision 1.16 2007/05/15 14:35:18 jcs
4 // update to be compatible with changes made to StFtpcTrackParams.cc
5 // use default microsecondsPerTimebin value from database if no RHIC clock info available
6 //
7 // Revision 1.15 2003/10/07 14:01:48 jcs
8 // remove double Stiostream.h include
9 //
10 // Revision 1.14 2003/09/02 17:58:16 perev
11 // gcc 3.2 updates + WarnOff
12 //
13 // Revision 1.13 2003/07/03 13:30:54 fsimon
14 // Implementation of cathode offset simulation:
15 // The inner radius (and thus the E-field) is changed according to
16 // phi of the cluster and the size of the offset.
17 // GetVelocityZ not inline anymore, since it got quite big
18 //
19 // Revision 1.12 2003/02/14 16:58:03 fsimon
20 // Add functionality that allows for different temperature corrections
21 // in west and east, important for embedding. Drift tables are created
22 // for east and west seperately.
23 //
24 // Revision 1.11 2002/09/13 13:44:55 fsimon
25 // Commented out anglefactor
26 //
27 // Revision 1.10 2002/04/19 22:24:12 perev
28 // fixes for ROOT/3.02.07
29 //
30 // Revision 1.9 2001/04/27 13:19:00 jcs
31 // cleanup comments
32 //
33 // Revision 1.8 2001/04/25 17:52:04 perev
34 // HPcorrs
35 //
36 // Revision 1.7 2001/04/24 12:54:59 oldi
37 // mParam->slowSimPressure() used instead of mParam->normalizedNowPressure().
38 //
39 // Revision 1.6 2001/04/02 12:04:33 jcs
40 // get FTPC calibrations,geometry from MySQL database and code parameters from StarDb/ftpc
41 //
42 // Revision 1.5 2001/03/19 15:53:10 jcs
43 // use ftpcDimensions from database
44 //
45 // Revision 1.4 2001/03/06 23:36:01 jcs
46 // use database instead of params
47 //
48 // Revision 1.3 2001/01/11 18:28:44 jcs
49 // use PhysicalConstants.h instead of math.h, remove print statement
50 //
51 // Revision 1.2 2000/11/27 14:08:00 hummler
52 // inplement tzero and lorentz angle correction factor
53 //
54 // Revision 1.1 2000/11/23 10:16:43 hummler
55 // New FTPC slow simulator in pure maker form
56 //
57 //
59 // Author: W.G.Gong
60 // Email: gong@mppmu.mpg.de
61 // Date: Oct 25, 1996
62 //
63 // Modifications:
64 // 02/27/98 Janet Seyboth correct definition of new arrays
66 
67 #include <Stiostream.h>
68 #include "PhysicalConstants.h"
69 
70 #include "StFtpcSlowSimField.hh"
71 #include "StFtpcClusterMaker/StFtpcParamReader.hh"
72 #include "StFtpcClusterMaker/StFtpcDbReader.hh"
73 #include "TMath.h"
74 
75 StFtpcSlowSimField::StFtpcSlowSimField(StFtpcParamReader *paramReader,
76  StFtpcDbReader *dbReader)
77 {
78  mParam=paramReader;
79  mDb = dbReader;
80  // inplementation of drift information from fcl_padtrans, which is
81  // more precise than that in ftpcSlowSimGas (includes calculated magfield)
82  // there's a job to do: fuse both tables into one!
83  innerRadius = mDb->sensitiveVolumeInnerRadius();
84  outerRadius = mDb->sensitiveVolumeOuterRadius();
85  angleFactor = mParam->lorentzAngleFactor();
86 
87  grid_point = new grid_data[mParam->numSlowSimGridPoints()];
88 
89  int i;
90  float cathodeVoltage = mParam->chamberCathodeVoltage();
91 
92  // grid size
93  del_r = (outerRadius - innerRadius)
94  / (float) (mParam->numSlowSimGridPoints()-1);
95  inverseDeltaRadius = 1/del_r; // '*' faster than '/' in later calculations
96  twoDeltaRadius = 2*del_r;
97 
98  int num_data = mParam->numberOfFssGasValues(); // number of data point
99  float * in_efield = new float[num_data];
100  float * in_velocity_z = new float[num_data];
101  float * in_diffusion_z = new float[num_data];
102  float * in_diffusion_x = new float[num_data];
103  float * in_diffusion_y = new float[num_data];
104  float * in_angle_lorentz = new float[num_data];
105  for ( i=0; i<num_data; i++) {
106  in_efield[i] = mParam->fssGasEField(i);
107  in_velocity_z[i] = mParam->fssGasVDrift(i);
108  in_diffusion_z[i] = mParam->fssGasDiffusionZ(i);
109  in_diffusion_x[i] = mParam->fssGasDiffusionX(i);
110  in_diffusion_y[i] = mParam->fssGasDiffusionY(i);
111  in_angle_lorentz[i] = mParam->fssGasLorentzAngle(i);
112  }
113 
114  float eff;
115  // big loop to define the field
116  for ( i=0; i<mParam->numSlowSimGridPoints(); i++) {
117 
118  grid_point[i].rhit = innerRadius + i * del_r;
119 
120  eff = fabs(cathodeVoltage) / ::log(outerRadius / innerRadius)
121  / grid_point[i].rhit;
122  grid_point[i].ef = eff;
123 
124  int index = Locate(num_data, in_efield, eff);
125 
126  grid_point[i].vel_z
127  = Interpolate(num_data,in_efield,in_velocity_z,index,eff);
128  float diffusionX=Interpolate(num_data,in_efield,in_diffusion_x,
129  index,eff);
130  float diffusionY=Interpolate(num_data,in_efield,in_diffusion_y,
131  index,eff);
132  float diffusionZ=Interpolate(num_data,in_efield,in_diffusion_z,
133  index,eff);
134  grid_point[i].diff_z
135  = diffusionZ*diffusionZ;
136  grid_point[i].diff_x
137  = diffusionX*diffusionY;
138  }
139 
140  // calculate drift velocity gradients
141 
142  for (i=mParam->numSlowSimGridPoints()-1; i>0; i--) {
143  grid_point[i].dlnv_dr
144  = ( 1. - grid_point[i-1].vel_z/grid_point[i].vel_z)
145  *inverseDeltaRadius;
146  }
147  grid_point[0].dlnv_dr = grid_point[1].dlnv_dr;
148  delete [] in_efield;
149  delete [] in_velocity_z;
150  delete [] in_diffusion_z;
151  delete [] in_diffusion_x;
152  delete [] in_diffusion_y;
153  delete [] in_angle_lorentz;
154 
155  radTimesField = mDb->radiusTimesField();
156  nPadrowPositions = mDb->numberOfPadrowsPerSide();
157  nMagboltzBins = mDb->numberOfMagboltzBins();
158  preciseEField = new float[nMagboltzBins];
159  inverseDriftVelocityWest = new float[nMagboltzBins*nPadrowPositions];
160  preciseLorentzAngleWest = new float[nMagboltzBins*nPadrowPositions];
161  inverseDriftVelocityEast = new float[nMagboltzBins*nPadrowPositions];
162  preciseLorentzAngleEast = new float[nMagboltzBins*nPadrowPositions];
163 
164  // use pressure and temperature corrections for each FTPC seperately
165 
166  // calculate drift velocity and lorentz angle for west
167 
168  // use temperature corrected pressure (set in StFtpcSlowSimMaker
169  //float deltaP = mParam->slowSimPressure()-mParam->standardPressure();
170  float deltaP = mParam->adjustedAirPressureWest() - mParam->standardPressure();
171 
172  {for(int i=0; i<nMagboltzBins; i++)
173  {
174  preciseEField[i] = mDb->magboltzEField(i);
175  for(int j=0; j<nPadrowPositions; j++)
176  {
177  inverseDriftVelocityWest[i+nMagboltzBins*j] =
178  1/ (mDb->magboltzVDrift(i,j)
179  + deltaP * mDb->magboltzdVDriftdP(i,j));
180  preciseLorentzAngleWest[i+nMagboltzBins*j] =
181  mDb->magboltzDeflection(i,j)
182  + deltaP * mDb->magboltzdDeflectiondP(i,j);
183  }
184  }}
185 
186  // calculate drift velocity and lorentz angle for east
187  deltaP = mParam->adjustedAirPressureEast() - mParam->standardPressure();
188 
189  {for(int i=0; i<nMagboltzBins; i++)
190  {
191  for(int j=0; j<nPadrowPositions; j++)
192  {
193  inverseDriftVelocityEast[i+nMagboltzBins*j] =
194  1/ (mDb->magboltzVDrift(i,j)
195  + deltaP * mDb->magboltzdVDriftdP(i,j));
196  preciseLorentzAngleEast[i+nMagboltzBins*j] =
197  mDb->magboltzDeflection(i,j)
198  + deltaP * mDb->magboltzdDeflectiondP(i,j);
199  }
200  }}
201  EFieldMin=preciseEField[0];
202  EFieldStep=preciseEField[1]-EFieldMin;
203  EFieldStepInverted= 1/EFieldStep;
204  EFieldStepInvConverted= EFieldStepInverted * degree;
205  finalVelocity = grid_point[mParam->numSlowSimGridPoints()-1].vel_z*10.;
206 
207  // fill variables for cathode offset
208  mOffsetCathodeWest = mDb->offsetCathodeWest();
209  mOffsetCathodeEast = mDb->offsetCathodeEast();
210  mAngleOffsetWest = mDb->angleOffsetWest();
211  mAngleOffsetEast = mDb->angleOffsetEast();
212 
213 
214 }
215 
216 StFtpcSlowSimField::~StFtpcSlowSimField() {
217  delete[] preciseEField;
218  delete[] inverseDriftVelocityWest;
219  delete[] preciseLorentzAngleWest;
220  delete[] inverseDriftVelocityEast;
221  delete[] preciseLorentzAngleEast;
222  delete[] grid_point;
223 }
224 
225 float StFtpcSlowSimField::Interpolate(const int npt, const float* x,
226  const float* y,const int ich,
227  const float xx)
228 {
229 //
230 // this subroutine will Interpolate the value (xx,yy) from
231 // the arrays {x(1:npt), y(1:npt)} at a given channel ich.
232 //
233  float x1[5];
234  float y1[5];
235  register int i;
236 
237  if (ich < 2) {
238  for ( i=0; i<2; i++) {
239  x1[i] = *(x+i) ;
240  y1[i] = *(y+i) ;
241  }
242  return InterpValue(2, x1, y1, xx);
243  }
244  else if (ich > npt-3) {
245  for ( i=0; i<2; i++) {
246  x1[i] = *(x+npt-1-i) ;
247  y1[i] = *(y+npt-1-i) ;
248  }
249  return InterpValue(2, x1, y1, xx);
250  }
251  else {
252  for ( i=0; i<5; i++) {
253  x1[i] = *(x+ich-2+i) ;
254  y1[i] = *(y+ich-2+i) ;
255  }
256  return InterpValue(5, x1, y1, xx);
257  }
258 }
259 
260 float StFtpcSlowSimField::InterpValue(const int npt, const float* x,
261  const float* y, const float xx)
262 {
263 //
264 // use Newton's method to Interpolate value at x
265 //
266  float term;
267  float sum = 0;
268 
269  for(register int i=0; i < npt; i++) {
270  term = y[i];
271  for(register int j=0; j < npt; j++) {
272  if (j != i) term *= (xx-x[j])/(x[i]-x[j]);
273  }
274  sum += term;
275  }
276  return sum;
277 }
278 
279 
280 
281 void StFtpcSlowSimField::GetVelocityZ(const float inverseRadius, const int padrow, const float phi, float *inverseVelocity, float *angle)
282 {
283 
284  // move cathode (standard: along x in pos direction
285  float xOff = 0;
286  float angleOff;
287  float newR;
288  float phis = phi - TMath::Pi()/2; // to get phi to run from 0 to 2 Pi
289 
290  if (padrow < 10) {
291  xOff = mOffsetCathodeWest;
292  angleOff = -mAngleOffsetWest; // this sign is not tested! Up to now, the Offset is 0!
293  phis -= TMath::Pi()/2;
294  }
295  else {
296  xOff = mOffsetCathodeEast;
297  angleOff = -mAngleOffsetEast;
298  }
299 
300 
301  if (xOff != 0) {
302  // rotate offset
303  phis -= angleOff;
304  if (phis < 0) phis += 2*TMath::Pi();
305  if (phis > 2*TMath::Pi()) phis -= 2*TMath::Pi();
306 
307  if (phis > TMath::Pi()) phis = 2 * TMath::Pi() - phis;
308 
309  if (phis == 0)
310  newR = innerRadius + xOff;
311  else if (phis == TMath::Pi())
312  newR = innerRadius - xOff;
313  else {
314  float asinSum = TMath::ASin(xOff/innerRadius * TMath::Sin(phis));
315  if (asinSum < 0 ) asinSum = asinSum* (-1);
316  newR = innerRadius/TMath::Sin(phis) * TMath::Sin(TMath::Pi() - phis - asinSum);
317  }
318  }
319  else
320  newR = innerRadius;
321 
322  int fieldPadrow = padrow;
323  if (padrow >= 10) fieldPadrow = padrow - 10; // bField symmetric, no diff east/west !
324  //float e_now=radTimesField * inverseRadius;
325  // e - Field corrected for changed cathode:
326  float e_now=radTimesField * inverseRadius * (::log(outerRadius / (innerRadius))/::log(outerRadius / newR));
327  int iLower= (int)((e_now-EFieldMin)*EFieldStepInverted);
328  int iUpper= iLower + 1;
329  int padrowIndex= nMagboltzBins*fieldPadrow;
330  float diffUp=preciseEField[iUpper]-e_now;
331  float diffDown=e_now-preciseEField[iLower];
332  iLower+=padrowIndex;
333  iUpper+=padrowIndex;
334  if (padrow < 10) {//west
335  *inverseVelocity = EFieldStepInverted*((inverseDriftVelocityWest[iUpper])*diffDown + (inverseDriftVelocityWest[iLower])*diffUp);
336  *angle = EFieldStepInvConverted*((preciseLorentzAngleWest[iUpper])*diffDown + (preciseLorentzAngleWest[iLower])*diffUp);//*angleFactor;
337  }
338  else {
339  *inverseVelocity = EFieldStepInverted*((inverseDriftVelocityEast[iUpper])*diffDown + (inverseDriftVelocityEast[iLower])*diffUp);
340  *angle = EFieldStepInvConverted*((preciseLorentzAngleEast[iUpper])*diffDown + (preciseLorentzAngleEast[iLower])*diffUp);//*angleFactor;
341  }
342 }
343 
344 
345 
346 void StFtpcSlowSimField::Output() const
347 {
348  ofstream fout("field.dat");
349  char space = ' ';
350  // print out the field value to check
351  for (int i=0; i<mParam->numSlowSimGridPoints(); i++) {
352  fout << grid_point[i].rhit << space
353  << grid_point[i].ef << space
354  << grid_point[i].vel_z << space
355  << grid_point[i].diff_z<< space
356  << grid_point[i].diff_x<< space
357  << grid_point[i].lorentz/degree << space
358  << grid_point[i].dlnv_dr
359  *mParam->lorentzAngleFactor()
360  << endl;
361  }
362 }
363