00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "KalFitAlg/coil/Bfield.h"
00015
00016
00017 #include "CLHEP/Matrix/Vector.h"
00018 #include "CLHEP/Matrix/Matrix.h"
00019 #include "CLHEP/Matrix/SymMatrix.h"
00020 #include "CLHEP/Vector/ThreeVector.h"
00021 #include "CLHEP/Geometry/Point3D.h"
00022 #ifndef ENABLE_BACKWARDS_COMPATIBILITY
00023 typedef HepGeom::Point3D<double> HepPoint3D;
00024 #endif
00025
00026
00027
00028 using CLHEP::HepVector;
00029 using CLHEP::Hep3Vector;
00030 using CLHEP::HepMatrix;
00031 using CLHEP::HepSymMatrix;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 Bfield *
00049 Bfield::_field[200] = {0};
00050
00051 Bfield *
00052 Bfield::getBfield(int imap) {
00053 if (! _field[imap]) _field[imap] = new Bfield(imap);
00054 return _field[imap];
00055 }
00056
00057
00058 Bfield::Bfield(int imap) {
00059 std::cout << std::endl;
00060 std::cout << "***********************************************" << std::endl;
00061 std::cout << " Bfield class MAP ID = " << imap << std::endl;
00062 std::cout << " #### R < 174 cm, -152 < Z < 246 cm #### " << std::endl;
00063 std::cout << " C++ version 1.00 " << std::endl;
00064 std::cout << "***********************************************" << std::endl;
00065
00066 const double uniformBz[10] = {0, 15, 14.5, 14, 13, 12.5, 12, 11, 10, 15.5};
00067
00068
00069 for(int i=0; i<175; i++)
00070 for(int j=0; j<399; j++) {
00071 _Bz[i][j] = 0;
00072 _Br[i][j] = 0;
00073 _Bz[i][j] = 0;
00074 if(i<101 && j<163) {
00075 _BzQR[i][j] = 0;
00076 _BrQR[i][j] = 0;
00077 _BphiQR[i][j] = 0;
00078 }
00079 }
00080 for(int i=0; i<17; i++)
00081 for(int j=0; j<51; j++)
00082 for(int k=0; k<52; k++) {
00083 _BzQL[i][j][k] = 0;
00084 _BrQL[i][j][k] = 0;
00085 _BphiQL[i][j][k] =0;
00086 }
00087
00088
00089 _fieldID = imap;
00090
00091
00092
00093 if(imap<10){
00094
00095
00096
00097 m_Bx = 0.;
00098 m_By = 0.;
00099 m_Bz = uniformBz[imap];
00100 m_Bfld.setX((double) m_Bx);
00101 m_Bfld.setY((double) m_By);
00102 m_Bfld.setZ((double) m_Bz);
00103 std::cout << "Bfield class >> creating uniform B field with id = " << imap;
00104 std::cout << ", (Bx,By,Bz) = "<<m_Bfld<<std::endl;
00105 } else {
00106
00107
00108
00109 std::cout << "Bfield class >> loading non-uniform B field map" << std::endl;
00110
00111
00112
00113
00114
00115
00116
00117
00118 updateCache(0., 0., 0.);
00119 }
00120 std::cout << std::endl;
00121
00122 }
00123
00124
00125
00126 const Hep3Vector &
00127 Bfield::fieldMap(double x, double y, double z) const {
00128
00129 if(_fieldID > 10){
00130 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00131 }
00132
00133 return m_Bfld;
00134 }
00135
00136 const Hep3Vector &
00137 Bfield::fieldMap(const HepPoint3D &xyz) const{
00138
00139 if(_fieldID > 10){
00140 double x = xyz.x();
00141 double y = xyz.y();
00142 double z = xyz.z();
00143 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00144 }
00145
00146 return m_Bfld;
00147 }
00148
00149 void
00150 Bfield::fieldMap(double *position, double *field) {
00151 if(_fieldID > 10){
00152 double x = position[0];
00153 double y = position[1];
00154 double z = position[2];
00155 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00156 }
00157 field[0] = m_Bx;
00158 field[1] = m_By;
00159 field[2] = m_Bz;
00160 return;
00161 }
00162
00163 double
00164 Bfield::bx(double x, double y, double z) const {
00165
00166 if(_fieldID > 10){
00167 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00168 }
00169
00170 return m_Bx;
00171 }
00172
00173 double
00174 Bfield::by(double x, double y, double z) const {
00175
00176 if(_fieldID > 10){
00177 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00178 }
00179
00180 return m_By;
00181 }
00182
00183 double
00184 Bfield::bz(double x, double y, double z) const {
00185
00186 if(_fieldID > 10){
00187 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00188 }
00189
00190 return m_Bz;
00191 }
00192
00193 double
00194 Bfield::bx(const HepPoint3D &xyz) const{
00195
00196 if(_fieldID > 10){
00197 double x = xyz.x();
00198 double y = xyz.y();
00199 double z = xyz.z();
00200 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00201 }
00202
00203 return m_Bx;
00204 }
00205
00206 double
00207 Bfield::by(const HepPoint3D &xyz) const{
00208
00209 if(_fieldID > 10){
00210 double x = xyz.x();
00211 double y = xyz.y();
00212 double z = xyz.z();
00213 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00214 }
00215
00216 return m_By;
00217 }
00218
00219 double
00220 Bfield::bz(const HepPoint3D &xyz) const{
00221
00222 if(_fieldID > 10){
00223 double x = xyz.x();
00224 double y = xyz.y();
00225 double z = xyz.z();
00226 if(x != m_x || y != m_y || z != m_z) updateCache(x, y, z);
00227 }
00228 return m_Bz;
00229 }
00230
00231 void
00232 Bfield::updateCache(double x, double y, double z) const{
00233
00234
00235
00236 if( _fieldID <= 10 ) return;
00237
00238 double PI = 3.14159;
00239
00240
00241 double r = (double)sqrt((double)x*(double)x + (double)y*(double)y);
00242 double phi = (double)atan2((double)y, (double)x);
00243
00244
00245 double zmm = z * 10.;
00246 double rmm = r * 10.;
00247
00248 int tz = (int) (( zmm + 1520.)/10.);
00249 int tr = (int) (rmm/10.);
00250
00251
00252 double bz = 0., br = 0., bphi = 0.;
00253
00254 if(zmm >= -1520. && zmm < 2460. && rmm >= 0. && rmm < 1740.){
00255 if(_Bz[tr][tz] && _Bz[tr][tz+1]){
00256 double pz = (zmm + 1520.)/10.- (double)tz;
00257 double pr = rmm/10.- (double)tr;
00258
00259
00260 bz = (_Bz[tr][tz]*(1.- pz)+_Bz[tr][tz+1]*pz)*(1.-pr)+
00261 (_Bz[tr+1][tz]*(1.-pz)+_Bz[tr+1][tz+1]*pz)*pr;
00262
00263 br = (_Br[tr][tz]*(1.-pz)+_Br[tr][tz+1]*pz)*(1.-pr)+
00264 (_Br[tr+1][tz]*(1.-pz)+_Br[tr+1][tz+1]*pz)*pr;
00265
00266 bphi = (_Bphi[tr][tz]*(1.-pz)+_Bphi[tr][tz+1]*pz)*(1.-pr)+
00267 (_Bphi[tr+1][tz]*(1.-pz)+_Bphi[tr+1][tz+1]*pz)*pr;
00268
00269 if(_fieldID == 21) {
00270
00271
00272
00273 if( zmm>=800. && zmm < 2420. && rmm < 1000. ) {
00274 int tqz = (int)( (zmm-800.)/10. );
00275 bz += (((_BzQR[tr][tqz]*(1.-pz)+_BzQR[tr][tqz+1]*pz)*(1.-pr)
00276 +(_BzQR[tr+1][tqz]*(1.-pz)+_BzQR[tr+1][tqz+1]*pz)*pr)
00277 *(double)sin((double)(2.*phi+2./180.*(double)PI)));
00278 br += (((_BrQR[tr][tqz]*(1.-pz)+_BrQR[tr][tqz+1]*pz)*(1.-pr)
00279 +(_BrQR[tr+1][tqz]*(1.-pz)+_BrQR[tr+1][tqz+1]*pz)*pr)
00280 *(double)sin((double)(2.*phi+2./180.*(double)PI)));
00281 bphi += (((_BphiQR[tr][tqz]*(1.-pz)
00282 +_BphiQR[tr][tqz+1]*pz)*(1.-pr)
00283 +(_BphiQR[tr+1][tqz]*(1.-pz)
00284 +_BphiQR[tr+1][tqz+1]*pz)*pr)
00285 *(double)cos((double)(2.*phi+2./180.*(double)PI)));
00286 }
00287
00288
00289
00290 if(zmm<=-500. && zmm>-1520. && rmm<1000.) {
00291 int tqz = (int)((-zmm-500.)/20.);
00292 int tqr = (int)(tr/2.);
00293 pz = (pz+(double)( tz-(int)(tz/2.)*2. ))/2.;
00294 pr = ( pr + (double)(tr-tqr*2) )/2.;
00295 double f = 1.;
00296
00297
00298
00299
00300
00301
00302
00303 double phi_tmp = phi;
00304 if( phi_tmp < (PI/2.) && phi_tmp >= (-PI/2.) ) {
00305 phi_tmp = PI-phi_tmp;
00306 f =-1.;
00307 } else if( phi_tmp < -PI/2. ) {
00308 phi_tmp = 2.*PI+phi_tmp;
00309 }
00310 double pphi = ( phi_tmp-PI/2. )/(11.25/180.*PI);
00311 int tphi = (int)pphi;
00312 pphi -= (double)tphi;
00313 if (tphi >= 16) tphi -= 16;
00314
00315 bz += f*
00316 (((_BzQL[tphi][tqr][tqz]*(1.-pz)+_BzQL[tphi][tqr][tqz+1]*pz)
00317 *(1-pr)+(_BzQL[tphi][tqr+1][tqz]*(1.-pz)
00318 +_BzQL[tphi][tqr+1][tqz+1]*pz)*pr)*(1.-pphi)
00319 +((_BzQL[tphi+1][tqr][tqz]*(1.-pz)
00320 +_BzQL[tphi+1][tqr][tqz+1]*pz)*(1.-pr)
00321 +(_BzQL[tphi+1][tqr+1][tqz]*(1.-pz)
00322 +_BzQL[tphi+1][tqr+1][tqz+1]*pz)*pr)*pphi);
00323 br += f*
00324 (((_BrQL[tphi][tqr][tqz]*(1.- pz)
00325 +_BrQL[tphi][tqr][tqz+1]*pz)*(1.-pr)
00326 +(_BrQL[tphi][tqr+1][tqz]*(1.-pz)
00327 +_BrQL[tphi][tqr+1][tqz+1]*pz)*pr)*(1-pphi)
00328 +((_BrQL[tphi+1][tqr][tqz]*(1.- pz)
00329 +_BrQL[tphi+1][tqr][tqz+1]*pz)*(1.-pr)
00330 +(_BrQL[tphi+1][tqr+1][tqz]*(1.-pz)
00331 +_BrQL[tphi+1][tqr+1][tqz+1]*pz)*pr)*pphi);
00332 bphi += f*
00333 (((_BphiQL[tphi][tqr][tqz]*(1.- pz)
00334 +_BphiQL[tphi][tqr][tqz+1]*pz)*(1.-pr)
00335 +(_BphiQL[tphi][tqr+1][tqz]*(1.-pz)
00336 +_BphiQL[tphi][tqr+1][tqz+1]*pz)*pr)*(1.-pphi)
00337 +((_BphiQL[tphi+1][tqr][tqz]*(1.- pz)
00338 +_BphiQL[tphi+1][tqr][tqz+1]*pz)*(1.-pr)
00339 +(_BphiQL[tphi+1][tqr+1][tqz]*(1.-pz)
00340 +_BphiQL[tphi+1][tqr+1][tqz+1]*pz)*pr)*pphi);
00341 }
00342 }
00343 } else {
00344 bz=0.;
00345 br=0.;
00346 bphi=0.;
00347 }
00348 } else if(zmm>=-1520. && zmm<=2460. && rmm<=0. && rmm<=1740.){
00349 if(tz == 246) tz=tz-1;
00350 if(tr == 174) tr=tr-1;
00351 double pz= (zmm + 1520.)/10.- (double)tz;
00352 double pr= rmm/10.- (double)tr;
00353 bz = (_Bz[tr][tz]*(1.- pz)+_Bz[tr][tz+1]*pz)*(1.-pr)+
00354 (_Bz[tr+1][tz]*(1.-pz)+_Bz[tr+1][tz+1]*pz)*pr;
00355
00356 br = (_Br[tr][tz]*(1.-pz)+_Br[tr][tz+1]*pz)*(1.-pr)+
00357 (_Br[tr+1][tz]*(1.-pz)+_Br[tr+1][tz+1]*pz)*pr;
00358
00359 bphi = (_Bphi[tr][tz]*(1.-pz)+_Bphi[tr][tz+1]*pz)*(1.-pr)+
00360 (_Bphi[tr+1][tz]*(1.-pz)+_Bphi[tr+1][tz+1]*pz)*pr;
00361 } else {
00362 bz =0.;
00363 br =0.;
00364 bphi =0.;
00365 }
00366
00367
00368
00369 double Bmag_xy = (double)sqrt(br*br + bphi*bphi);
00370 double Bphi_rp = (double)atan2( (double)bphi, (double)br );
00371 m_Bx = Bmag_xy * (double)cos((double)phi + Bphi_rp)/1000.;
00372 m_By = Bmag_xy * (double)sin((double)phi + Bphi_rp)/1000.;
00373
00374
00375 m_Bz = bz/1000.;
00376 m_x = x;
00377 m_y = y;
00378 m_z = z;
00379 m_Bfld.setX((double) m_Bx);
00380 m_Bfld.setY((double) m_By);
00381 m_Bfld.setZ((double) m_Bz);
00382 }
00383
00384
00385
00386
00387
00388
00389
00390 extern "C"
00391 void init_bfield_(int *imap) {
00392
00393
00394 (void) Bfield::getBfield(*imap);
00395
00396
00397
00398 return;
00399 }
00400
00401
00402 extern "C"
00403 void get_bfield_(int *imap, double *pos, double *field, int *error) {
00404 Bfield *thisMap = Bfield::getBfield(*imap);
00405
00406 if( thisMap != 0 ) {
00407 thisMap->fieldMap(pos,field);
00408 *error = 0;
00409 }
00410 else *error = 1;
00411 return;
00412 }