Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMagneticFieldMapParameterized.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DMagneticFieldMapParameterized.cc
4 // Created: Tue Oct 20 14:06:19 EDT 2009
5 // Creator: davidl (on Darwin harriet.jlab.org 9.8.0 i386)
6 //
7 
8 #include <cmath>
9 using namespace std;
10 
11 #include <JANA/JParameterManager.h>
12 using namespace jana;
13 
15 
16 
17 // Chebyshev polynomial functions
18 #define T0() (1)
19 #define T1(x_1) (x_1)
20 #define T2(x_2) (2*x_2-1)
21 #define T3(x_1,x_3) (4*x_3-3*x_1)
22 #define T4(x_2,x_4) (8*x_4-8*x_2+1)
23 #define T5(x_5,x_3,x_1) (16*x_5-20*x_3+5*x_1)
24 #define T6(x_6,x_4,x_2) (32*x_6-48*x_4+18*x_2-1)
25 #define T7(x_7,x_5,x_3,x_1) (64*x_7-112*x_5+56*x_3-7*x_1)
26 #define T8(x_8,x_6,x_4,x_2) (128*x_8-256*x_6+160*x_4-32*x_2+1)
27 #define T9(x_9,x_7,x_5,x_3,x_1) (256*x_9-576*x_7+432*x_5-120*x_3+9*x_1)
28 
29 // First derivative of Chebyshev polynomial functions
30 #define dT0dx(x) (0)
31 #define dT1dx(x) (1)
32 #define dT2dx(x) (2*2*pow(x,2-1))
33 #define dT3dx(x) (3*4*pow(x,3-1)-3)
34 #define dT4dx(x) (4*8*pow(x,4-1)-2*8*pow(x,2-1))
35 #define dT5dx(x) (5*16*pow(x,5-1)-3*20*pow(x,3-1)+5)
36 #define dT6dx(x) (6*32*pow(x,6-1)-4*48*pow(x,4-1)+2*18*pow(x,2-1))
37 #define dT7dx(x) (7*64*pow(x,7-1)-5*112*pow(x,5-1)+3*56*pow(x,3-1)-7)
38 #define dT8dx(x) (8*128*pow(x,8-1)-6*256*pow(x,6-1)+4*160*pow(x,4-1)-2*32*pow(x,2-1))
39 #define dT9dx(x) (9*256*pow(x,9-1)-7*576*pow(x,7-1)+5*432*pow(x,5-1)-3*120*pow(x,3-1)+9)
40 
41 //---------------------------------
42 // DMagneticFieldMapParameterized (Constructor)
43 //---------------------------------
45 {
46  int32_t runnumber = 1;
47  jcalib = japp->GetJCalibration(runnumber);
48 
49  JParameterManager *jparms = japp->GetJParameterManager();
50  jparms->SetDefaultParameter("BFIELD_MAP", namepath);
51 
52  Init(jcalib, namepath);
53 }
54 
55 //---------------------------------
56 // DMagneticFieldMapParameterized (Constructor)
57 //---------------------------------
58 DMagneticFieldMapParameterized::DMagneticFieldMapParameterized(jana::JCalibration *jcalib, string namepath)
59 {
60  Init(jcalib, namepath);
61 }
62 
63 //---------------------------------
64 // ~DMagneticFieldMapParameterized (Destructor)
65 //---------------------------------
67 {
68 
69 }
70 
71 //---------------------------------
72 // Init
73 //---------------------------------
74 void DMagneticFieldMapParameterized::Init(jana::JCalibration *jcalib, string namepath)
75 {
76  this->jcalib = jcalib;
77 
78  // First, get the parameters specifying the number of sections and their ranges in z, r
79  vector<map<string, string> > sections_map;
80  jcalib->Get(namepath, sections_map);
81 
82  // Loop over entries in the master list and read in those tables
83  for(unsigned int k=0; k<sections_map.size(); k++){
84  map<string, string> &vals = sections_map[k];
85 
86  Dsection section;
87  section.namepath = vals["namepath"];
88  section.Bi = vals["Bi"];
89  section.section = atoi(vals["sec"].c_str());
90  section.zmin = atof(vals["zmin"].c_str());
91  section.zmax = atof(vals["zmax"].c_str());
92  section.zmid = atof(vals["zmid"].c_str());
93  section.znorm = atof(vals["znorm"].c_str());
94  section.rmid = atof(vals["rmid"].c_str());
95  section.rnorm = atof(vals["rnorm"].c_str());
96 
97  // Get parameters for this section
98  jcalib->Get(section.namepath, section.pp);
99  section.order1 = section.pp.size() - 1;
100  section.order2 = section.pp[0].size() - 1;
101 
102  cout<<"---- parameterized B-field section ---------------"<<endl;
103  cout<<"namepath = "<<section.namepath<<endl;
104  cout<<" Bi = "<<section.Bi<<endl;
105  cout<<" section = "<<section.section<<endl;
106  cout<<" zmin = "<<section.zmin<<endl;
107  cout<<" zmax = "<<section.zmax<<endl;
108  cout<<" zmid = "<<section.zmid<<endl;
109  cout<<" znorm = "<<section.znorm<<endl;
110  cout<<" rmid = "<<section.rmid<<endl;
111  cout<<" rnorm = "<<section.rnorm<<endl;
112  cout<<" order1 = "<<section.order1<<endl;
113  cout<<" order2 = "<<section.order1<<endl;
114 
115  // Here we need to transform the order1 by order2 matrix that is in pp
116  // using the matrix of Chebyshev coefficients into the similarly
117  // dimensioned matrix that will be used. This is to save all of the
118  // CPU to recalculate this on every access.
119 
120  // Fill non-zero values of C1 with Chebyshev coefficients (from the definition of
121  // the Chebyshev polynomials). We use the switch here to fill in only elements
122  // for a matrix of order (order1+1) (note there are not breaks). The remaining
123  // elements are zero.
124  unsigned int &order1 = section.order1;
125  DMatrix C1(order1+1, order1+1);
126  C1.Zero();
127  switch(order1){
128  case 9: C1(9,1)= +9; C1(9,3)=-120; C1(9,5)=+432; C1(9,7)=-576; C1(9,9)=+256;
129  case 8: C1(8,0)= +1; C1(8,2)= -32; C1(8,4)=+160; C1(8,6)=-256; C1(8,8)=+128;
130  case 7: C1(7,1)= -7; C1(7,3)= +56; C1(7,5)=-112; C1(7,7)= +64;
131  case 6: C1(6,0)= -1; C1(6,2)= +18; C1(6,4)= -48; C1(6,6)= +32;
132  case 5: C1(5,1)= +5; C1(5,3)= -20; C1(5,5)= +16;
133  case 4: C1(4,0)= +1; C1(4,2)= -8; C1(4,4)= +8;
134  case 3: C1(3,1)= -3; C1(3,3)= +4;
135  case 2: C1(2,0)= -1; C1(2,2)= +2;
136  case 1: C1(1,1)= +1;
137  case 0: C1(0,0)= +1;
138  }
139  TMatrixD C1_t(TMatrixD::kTransposed, C1);
140 
141  // Do the same for C2 which is an (order2+1) x (order2+1) matrix
142  unsigned int &order2 = section.order2;
143  DMatrix C2(order2+1, order2+1);
144  C2.Zero();
145  switch(order2){
146  case 9: C2(9,1)= +9; C2(9,3)=-120; C2(9,5)=+432; C2(9,7)=-576; C2(9,9)=+256;
147  case 8: C2(8,0)= +1; C2(8,2)= -32; C2(8,4)=+160; C2(8,6)=-256; C2(8,8)=+128;
148  case 7: C2(7,1)= -7; C2(7,3)= +56; C2(7,5)=-112; C2(7,7)= +64;
149  case 6: C2(6,0)= -1; C2(6,2)= +18; C2(6,4)= -48; C2(6,6)= +32;
150  case 5: C2(5,1)= +5; C2(5,3)= -20; C2(5,5)= +16;
151  case 4: C2(4,0)= +1; C2(4,2)= -8; C2(4,4)= +8;
152  case 3: C2(3,1)= -3; C2(3,3)= +4;
153  case 2: C2(2,0)= -1; C2(2,2)= +2;
154  case 1: C2(1,1)= +1;
155  case 0: C2(0,0)= +1;
156  }
157 
158  // Make matrix of fit parameters
159  DMatrix P(order2+1, order1+1);
160  for(unsigned int i=0; i<=order1; i++){
161  for(unsigned int j=0; j<=order2; j++){
162  P(j, i) = section.pp[i][j];
163  }
164  }
165 
166  // Multiply out the matrices and store the final one with the section
167  section.Q.ResizeTo(P);
168  section.Q = C1_t*P*C2;
169 
170  // Copy Q matrix into more efficient format
171  section.cc = section.pp;
172  for(unsigned int i=0; i<=order1; i++){
173  for(unsigned int j=0; j<=order2; j++){
174  section.cc[i][j] = section.Q(j,i);
175  }
176  }
177 
178  // Add this section object to list
179  string type = vals["Bi"];
180  if(type=="Bx")sections_Bx.push_back(section);
181  if(type=="Bz")sections_Bz.push_back(section);
182  }
183 }
184 
186  DVector3 &Bout)const{
187  double Bx,By,Bz;
188  GetField(pos.x(),pos.y(),pos.z(),Bx,By,Bz);
189  Bout.SetXYZ(Bx,By,Bz);
190 }
191 
192 //---------------------------------
193 // GetField
194 //---------------------------------
195 void DMagneticFieldMapParameterized::GetField(double x, double y, double z, double &Bx, double &By, double &Bz, int method) const
196 {
197  // default
198  Bx = By = Bz = 0.0;
199  double Br = 0.0;
200 
201  double r = sqrt(x*x + y*y);
202 
203  // Find Bx Dsection object for this z value
204  for(unsigned int i=0; i<sections_Bx.size(); i++){
205  if(sections_Bx[i].IsInRange(z)){
206  Br = sections_Bx[i].Eval(r,z);
207  break;
208  }
209  }
210 
211  // Find Bz Dsection object for this z value
212  for(unsigned int i=0; i<sections_Bz.size(); i++){
213  if(sections_Bz[i].IsInRange(z)){
214  Bz = sections_Bz[i].Eval(r,z);
215  break;
216  }
217  }
218 
219  // Convert Br to Bx and By
220  if(r!=0.0){
221  Bx = Br*x/r;
222  By = Br*y/r;
223  }
224 }
225 //---------------------------------
226 // Get the z-component of the magnetic field
227 //---------------------------------
228 double DMagneticFieldMapParameterized::GetBz(double x, double y, double z)const
229 {
230 
231  double r = sqrt(x*x + y*y);
232 
233  // Find Bz Dsection object for this z value
234  for(unsigned int i=0; i<sections_Bz.size(); i++){
235  if(sections_Bz[i].IsInRange(z)){
236  return (sections_Bz[i].Eval(r,z));
237  }
238  }
239  return 0.;
240 }
241 
242 
243 //---------------------------------
244 // Eval
245 //---------------------------------
246 double DMagneticFieldMapParameterized::Dsection::Eval(double &r, double &z) const
247 {
248  // Evaluate the value (either Bz or Bx) at the specified r,z values
249 
250  // Initialize value.
251  double Bi = 0.0;
252 
253  // Convert to "normalized" coordinates (where
254  // values range from -1 to +1).
255  double r_prime = (r-rmid)/rnorm;
256  double z_prime = (z-zmid)/znorm;
257 
258 #if 0
259  // Calculate powers of "r" used by Chebyshev functions
260  double &r_1 = r_prime;
261  double r_2 = r_1*r_1;
262  double r_3 = r_2*r_1;
263  double r_4 = r_3*r_1;
264  double r_5 = r_4*r_1;
265  double r_6 = r_5*r_1;
266  double r_7 = r_6*r_1;
267  double r_8 = r_7*r_1;
268  double r_9 = r_8*r_1;
269 
270  // Calculate powers of "z" used by Chebyshev functions
271  double &z_1 = z_prime;
272  double z_2 = z_1*z_1;
273  double z_3 = z_2*z_1;
274  double z_4 = z_3*z_1;
275  double z_5 = z_4*z_1;
276  double z_6 = z_5*z_1;
277  double z_7 = z_6*z_1;
278  double z_8 = z_7*z_1;
279  double z_9 = z_8*z_1;
280 
281  // Calculate each parameter based on r_prime and then
282  // add the term based on z_prime to Bi.
283  for(unsigned int i=0; i<order1; i++){
284 
285  // Calculate the 1st level parameter from the 2nd
286  // level parameters. Note that this funny switch actually
287  // does the sum of 2nd level poly.
288  const double *my_pp = &pp[i][0];
289  double p = my_pp[0]*T0();
290  switch(order2){
291  case 9: p += my_pp[9]*T9(r_9,r_7,r_5,r_3,r_1);
292  case 8: p += my_pp[8]*T8(r_8,r_6,r_4,r_2);
293  case 7: p += my_pp[7]*T7(r_7,r_5,r_3,r_1);
294  case 6: p += my_pp[6]*T6(r_6,r_4,r_2);
295  case 5: p += my_pp[5]*T5(r_5,r_3,r_1);
296  case 4: p += my_pp[4]*T4(r_4,r_2);
297  case 3: p += my_pp[3]*T3(r_3,r_1);
298  case 2: p += my_pp[2]*T2(r_2);
299  case 1: p += my_pp[1]*T1(r_1);
300  }
301 
302  // Add the i-th poly term to Bi
303  switch(i){
304  case 0: Bi += p*T0(); break;
305  case 1: Bi += p*T1(z_1); break;
306  case 2: Bi += p*T2(z_2); break;
307  case 3: Bi += p*T3(z_3,z_1); break;
308  case 4: Bi += p*T4(z_4,z_2); break;
309  case 5: Bi += p*T5(z_5,z_3,z_1); break;
310  case 6: Bi += p*T6(z_6,z_4,z_2); break;
311  case 7: Bi += p*T7(z_7,z_5,z_3,z_1); break;
312  case 8: Bi += p*T8(z_8,z_6,z_4,z_2); break;
313  case 9: Bi += p*T9(z_9,z_7,z_5,z_3,z_1); break;
314  }
315  }
316 #else
317 
318  double zz = 1;
319  for(unsigned int i=1; i<=order2; i++){
320  const double *col_ptr = &cc[i][0];
321  double v = *col_ptr++;
322  double rr = 1;
323  for(unsigned int j=1; j<=order1; j++, col_ptr++){
324  rr*=r_prime;
325  v+=(*col_ptr)*rr;
326  }
327 
328  zz*=z_prime;
329  Bi += v*zz;
330  }
331 
332 #if 0
333  // Form matrix of r_prime raised to powers from 0 to order2
334  DMatrix R(order2+1, 1);
335  double rr= R(0,0) = 1;
336  for(unsigned int i=1; i<=order2; i++)R(i,0)=(rr*=r_prime);
337 
338  // Form matrix of z_prime raised to powers from 0 to order1
339  DMatrix Z(1,order1+1);
340  double zz= Z(0,0) = 1;
341  for(unsigned int i=1; i<=order1; i++)Z(0,i)=(zz*=z_prime);
342 
343  // Multiply R and Z vectors using parameters matrix
344  DMatrix B = Q*R;
345  Bi = B(0,0);
346 #endif
347 #endif
348 //_DBG_<<"Bi="<<Bi<<" B(0,0)="<<B(0,0)<<endl;
349 
350  return Bi;
351 }
352 
353 //---------------------------------
354 // GetFieldGradient
355 //---------------------------------
357  double &dBxdx, double &dBxdy,
358  double &dBxdz,
359  double &dBydx, double &dBydy,
360  double &dBydz,
361  double &dBzdx, double &dBzdy,
362  double &dBzdz) const
363 {
364 
365 }
366 
367 //---------------------------------
368 // GetFieldBicubic
369 //---------------------------------
370 void DMagneticFieldMapParameterized::GetFieldBicubic(double x,double y,double z, double &Bx,double &By,double &Bz) const
371 {
372  // Since we calculate the gradient analytically here, a bicubic
373  // interpolation will not give a better result than what is
374  // returned by the GetFieldGradient method.
375  GetField(x,y,z,Bx, By, Bz);
376 }
377 
378 //---------------------------------
379 // GetFieldAndGradient
380 //---------------------------------
382  double &Bx,
383  double &By,
384  double &Bz,
385  double &dBxdx,
386  double &dBxdy,
387  double &dBxdz,
388  double &dBydx,
389  double &dBydy,
390  double &dBydz,
391  double &dBzdx,
392  double &dBzdy,
393  double &dBzdz) const
394 {
395  // Just defer to the individual functions here.
396  GetField(x,y,z,Bx, By, Bz);
397  GetFieldGradient(x, y, z, dBxdx, dBxdy, dBxdz, dBydx, dBydy, dBydz, dBzdx, dBzdy, dBzdz);
398 }
399 
TMatrixD DMatrix
Definition: DMatrix.h:14
#define T7
Definition: md5_t.h:7
TVector3 DVector3
Definition: DVector3.h:14
virtual void GetFieldAndGradient(double x, double y, double z, double &Bx, double &By, double &Bz, double &dBxdx, double &dBxdy, double &dBxdz, double &dBydx, double &dBydy, double &dBydz, double &dBzdx, double &dBzdy, double &dBzdz) const
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
#define y
#define T1
Definition: md5_t.h:1
#define T9
Definition: md5_t.h:9
void GetField(const DVector3 &pos, DVector3 &Bout) const
#define T4
Definition: md5_t.h:4
JApplication * japp
#define T6
Definition: md5_t.h:6
virtual void GetFieldBicubic(double x, double y, double z, double &Bx, double &By, double &Bz) const
#define T8
Definition: md5_t.h:8
#define T3
Definition: md5_t.h:3
virtual void GetFieldGradient(double x, double y, double z, double &dBxdx, double &dBxdy, double &dBxdz, double &dBydx, double &dBydy, double &dBydz, double &dBzdx, double &dBzdy, double &dBzdz) const
double GetBz(double x, double y, double z) const
#define T5
Definition: md5_t.h:5
double sqrt(double)
#define T2
Definition: md5_t.h:2
DMagneticFieldMapParameterized(jana::JApplication *japp, string namepath="Magnets/Solenoid/solenoid_1500_poisson_20090814_01_params")
void Init(jana::JCalibration *jcalib, string namepath)