00001 
00002 
00003 
00004 
00005 #include "globals.hh"
00006 #include "BDSXYMagField.hh"
00007 #include <fstream>
00008 #include <vector>
00009 #include "CLHEP/Vector/Rotation.h"
00010 
00011 G4double GetNearestValue(std::vector<struct XYFieldRecord> fieldValues, G4double x, G4double y,
00012                          G4double &bx,G4double &by, G4double &bz);
00013 
00014 BDSXYMagField::BDSXYMagField(G4String fname) :
00015   Bx(NULL), By(NULL), Bz(NULL), xHalf(0.0), yHalf(0.0), nX(0), nY(0), itsFileName(fname)
00016 {
00017 }
00018 
00019 BDSXYMagField::~BDSXYMagField()
00020 {
00021   
00022   if (Bx) {
00023     for(int i=0;i<nX;i++) {
00024       delete[] Bx[i];
00025     }
00026     delete[] Bx;
00027   }
00028   if (By) {
00029     for(int i=0;i<nX;i++) {
00030       delete[] By[i];
00031     }
00032     delete[] By;
00033   }
00034   if (Bz) {
00035     for(int i=0;i<nX;i++) {
00036       delete[] Bz[i];
00037     }
00038     delete[] Bz;
00039   }
00040 }
00041 
00042 G4bool  BDSXYMagField::DoesFieldChangeEnergy() const
00043 {
00044   return false;
00045 }
00046 
00047 G4int BDSXYMagField::ReadFile(G4String fname)
00048 {
00049 #ifdef BDSDEBUG
00050   G4cout<<"reading file "<<fname<<G4endl;
00051 #endif
00052   struct XYFieldRecord rec;
00053   
00054 
00055   
00056   std::ifstream bmapif;
00057   bmapif.open(fname.c_str());
00058   G4String exceptionString = "Unable to load field map file: " + fname;
00059   if(!bmapif) G4Exception(exceptionString.c_str(), "-1", FatalException, "");
00060 
00061   while(bmapif.good())
00062     {
00063       bmapif>>rec.x>>rec.y>>rec.Bx>>rec.By>>rec.Bz; 
00064       
00065       if(!bmapif.good()) break;
00066 #ifdef BDSDEBUG 
00067       G4cout<<"read: "<<rec.x<<" "<<rec.y<<" "<<rec.Bx<<" "<<rec.By<<" "<<rec.Bz<<" "<<G4endl;
00068 #endif
00069       itsFieldValues.push_back(rec);
00070     }
00071   
00072   bmapif.close();
00073 #ifdef BDSDEBUG
00074   G4cout<<"done"<<G4endl;
00075 #endif
00076   return 0;
00077 
00078 }
00079 
00080 
00081 void BDSXYMagField::Prepare(G4VPhysicalVolume *referenceVolume)
00082 {
00083 #ifdef BDSDEBUG
00084   G4cout<<"BDSXYMagField:: create XY field mesh"<<G4endl;
00085 #endif
00086   ReadFile(itsFileName);
00087 
00088   if( itsFieldValues.size() == 0 )
00089     {
00090       G4cerr<<"empty bmap file "<<itsFileName<<" exiting..."<<G4endl;
00091       exit(1);
00092     }
00093   
00094   const G4RotationMatrix* Rot= referenceVolume->GetFrameRotation();
00095   const G4ThreeVector Trans=referenceVolume->GetFrameTranslation();
00096   
00097   G4ThreeVector B;
00098   
00099   
00100   
00101   
00102   std::vector<struct XYFieldRecord>::iterator it, itt;
00103   
00104 
00105   double xmax=0, ymax=0;
00106 
00107   for(it=itsFieldValues.begin();it!=itsFieldValues.end();it++)
00108     {
00109       if( fabs((*it).x ) > xmax ) xmax = fabs((*it).x);
00110       if( fabs((*it).y ) > ymax) ymax = fabs((*it).y);
00111     }
00112 
00113 
00114   
00115   
00116   double hx=xmax, hxold=xmax; 
00117   double hy=ymax, hyold=ymax; 
00118 
00119   xHalf = xmax / 2;
00120   yHalf = ymax / 2;
00121   
00122   for(it=++itsFieldValues.begin();it!=itsFieldValues.end();it++)
00123     {
00124       
00125       for(itt=itsFieldValues.begin();itt!=itsFieldValues.end();itt++)
00126         {
00127 #ifdef BDSDEBUG
00128           G4cout<<(*it).x<<" "<<(*it).y<<" "<<" "<<(*it).Bx<<G4endl;
00129 #endif
00130           hxold = fabs((*it).x - (*itt).x);
00131           if( (hxold > 1.0e-11*CLHEP::m)&&(hxold<hx) ) hx = hxold;
00132           
00133           hyold = fabs((*it).y - (*itt).y);
00134           if( (hyold > 1.0e-11*CLHEP::m)&&(hyold<hy) ) hy = hyold;
00135           
00136         }
00137     }
00138   
00139   
00140 
00141   G4cout<<"h ="<<hx<<":"<<hy<<":"<<G4endl;
00142   G4cout<<"xmax ="<<xmax<<":"<<ymax<<":"<<G4endl;
00143 
00144 
00145   
00146 
00147   G4int nX = static_cast<int> ( 2*xHalf / hx ) + 1;
00148   G4int nY = static_cast<int> ( 2*yHalf / hy ) + 1;
00149   
00150 
00151   G4cout<<"N ="<<nX<<":"<<nY<<G4endl;
00152 
00153   AllocateMesh(nX,nY);
00154   
00155   SetOriginRotation(*Rot);
00156   SetOriginTranslation(Trans);
00157 
00158   for(int i=0; i<nX;i++)
00159     for(int j=0;j<nY;j++)
00160       {
00161         G4double bx=0., by=0., bz=0.;
00162         G4double x = i * hx - xHalf;
00163         G4double y = j * hy - yHalf;
00164         
00165         
00166         
00167         
00168         
00169         G4double dist = GetNearestValue(itsFieldValues,x,y,bx,by,bz);
00170         
00171         G4double tol = 100 * hx;
00172         
00173         G4cout << "dist, tol: " << dist << " " << tol << G4endl;
00174 
00175 
00176         if(dist < tol) {
00177           SetBx(i,j,bx * CLHEP::tesla);
00178           SetBy(i,j,by * CLHEP::tesla);
00179           SetBz(i,j,bz * CLHEP::tesla);
00180           
00181         } else {
00182           SetBx(i,j,0.);
00183           SetBy(i,j,0.);
00184           SetBz(i,j,0.);
00185         }
00186       }
00187   
00188   
00189   
00190   
00191   G4cout<<"writing test file"<<G4endl;
00192   
00193   std::ofstream testf("btest.dat");
00194   
00195   for(int i=0; i<nX;i++)
00196     for(int j=0;j<nY;j++)
00197       {
00198         testf<<i<<" "<<j<<" "" "<<
00199           GetBx(i,j)<<" "<<
00200           GetBy(i,j)<<" "<<
00201           GetBz(i,j)<<std::endl;
00202       }
00203   
00204   testf.close();
00205   
00206 }
00207 
00208 
00209 void BDSXYMagField::GetFieldValue(const G4double Point[4], G4double *Bfield ) const
00210 {
00211   G4double bx=0., by=0.;
00212 #if BDSDEBUG
00213   G4double bz=0.;
00214 #endif
00215   G4int i=0,j=0;
00216 
00217   G4ThreeVector local;
00218 
00219   if( (nX <= 0) || (nY<=0) )
00220     {
00221       G4cerr<<"BDSXYMagField::GetFieldValue> Error: no mesh"<<G4endl;
00222     }
00223   else
00224     {
00225       local[0] = Point[0] - translation[0];
00226       local[1] = Point[1] - translation[1];
00227       local[2] = Point[2] - translation[2];
00228 
00229       local *= Rotation();
00230 
00231       i = (G4int)(nX/2.0 + nX * local[0] / (2.0 * xHalf));
00232       j = (G4int)(nY/2.0 + nY * local[1] / (2.0 * yHalf));
00233 
00234       if( (i>=nX) || (j>=nY) || (i<0) || (j<0)){ 
00235         
00236         
00237       } else {
00238         bx = Bx[i][j];
00239         by = By[i][j];
00240 #if BDSDEBUG
00241         bz = Bz[i][j];
00242         G4cout << "Bx[" << i << "][" << j << "]=" << Bx[i][j] << G4endl;
00243         G4cout << "By[" << i << "][" << j << "]=" << By[i][j] << G4endl;
00244         G4cout << "Bz[" << i << "][" << j << "]=" << Bz[i][j] << G4endl;
00245         G4cout << "nX = " << nX << ", nY = " << nY << G4endl;
00246 #endif
00247       }
00248     }
00249 
00250   
00251   Bfield[0] = bx;
00252   Bfield[1] = by;
00253 
00254   
00255   Bfield[3] = 0;
00256   Bfield[4] = 0;
00257   Bfield[5] = 0;
00258 
00259 #ifdef BDSDEBUG
00260   G4cout<<" field value requested : "<<Point[0]<<" , "<<Point[1]<<" , "<<Point[2]<<" , "<<Point[3]<<" : "<<
00261     i<<" , "<<j<<" , "<<"    "<<local[0]<<" "<<local[1]<<" "<<local[2]<<" "<<bx<<" "<<by<<" "<<bz<<G4endl;
00262 #endif
00263 }
00264 
00265 int BDSXYMagField::AllocateMesh(int nx, int ny) 
00266 {
00267   nX = nx;
00268   nY = ny;
00269   
00270   Bx = new double*[nX];
00271   for(int i=0;i<nX;i++)
00272     {
00273       Bx[i] = new double[nY];
00274     }
00275   
00276   By = new double*[nX];
00277   for(int i=0;i<nX;i++)
00278     {
00279       By[i] = new double[nY];
00280     }
00281   
00282   Bz = new double*[nX];
00283   for(int i=0;i<nX;i++)
00284     {
00285       Bz[i] = new double[nY];
00286     }
00287   
00288   return 0;
00289 }
00290 
00291 inline
00292 void BDSXYMagField::SetBx(int i,int j,double val)
00293 {
00294   Bx[i][j] = val;
00295 }
00296 
00297 inline
00298 void BDSXYMagField::SetBy(int i,int j,double val)
00299 {
00300   By[i][j] = val;
00301 }
00302 
00303 
00304 inline
00305 void BDSXYMagField::SetBz(int i,int j,double val)
00306 {
00307   Bz[i][j] = val;
00308 }
00309 
00310 inline
00311 G4double BDSXYMagField::GetBx(int i,int j)
00312 {
00313   return Bx[i][j];
00314 }
00315 
00316 inline
00317 G4double BDSXYMagField::GetBy(int i,int j)
00318 {
00319   return By[i][j];
00320 }
00321 
00322 inline
00323 G4double BDSXYMagField::GetBz(int i,int j)
00324 {
00325   return Bz[i][j];
00326 }
00327 
00328 
00329 G4double GetNearestValue(std::vector<struct XYFieldRecord> fieldValues, G4double x, G4double y,
00330                          G4double &bx,G4double &by, G4double &bz)
00331 {
00332   std::vector<struct XYFieldRecord>::iterator it;
00333 
00334   G4double nearestDist = 10.e+10;
00335 
00336   for(it = fieldValues.begin(); it!=fieldValues.end();it++)
00337     {
00338       G4double dist = sqrt( (x-(*it).x)*(x-(*it).x) + (y-(*it).y)*(y-(*it).y));
00339       if (dist<nearestDist) {
00340         nearestDist = dist;
00341         bx = (*it).Bx;
00342         by = (*it).By;
00343         bz = (*it).Bz;
00344       }
00345     }
00346 
00347   return nearestDist;
00348 }
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359   
00360 
00361 
00362   
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388   
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399       
00400 
00401 
00402 
00403       
00404 
00405 
00406       
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427   
00428 
00429 
00430 
00431 
00432   
00433 
00434 
00435   
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457            
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475                
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493 
00494 
00495 
00496 
00497 
00498 
00499 
00500 
00501 
00502 
00503 
00504 
00505 
00506 
00507 
00508 
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518            
00519 
00520            
00521 
00522            
00523 
00524 
00525            
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550