/scratch0/jsnuveri/BDSIM/BDSIMgit/bdsim/src/BDSXYMagField.cc

00001 /* BDSIM code.
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   // release the b-map memory
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   // Open the file for reading.
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 // create a field mesh in the "world" coordinates from list of field values
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   // determine mesh physical dimensions
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   //determine mesh step - minimum distance between measurement points
00115   
00116   double hx=xmax, hxold=xmax; //, hxmax=0;
00117   double hy=ymax, hyold=ymax; //, hymax=0;
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   //  hxmax = hx; hymax = hy;
00140 
00141   G4cout<<"h ="<<hx<<":"<<hy<<":"<<G4endl;
00142   G4cout<<"xmax ="<<xmax<<":"<<ymax<<":"<<G4endl;
00143 
00144 
00145   // allocate mesh
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         // find the closest measured point
00166         // if the point is further than ... set to zero 
00167         // has to be replaced by proper interpolation
00168         
00169         G4double dist = GetNearestValue(itsFieldValues,x,y,bx,by,bz);
00170         
00171         G4double tol = 100 * hx;// dummy
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   // dump the field mes for test
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         // outside mesh dimensions
00236         // 0 field
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   // b-field
00251   Bfield[0] = bx;
00252   Bfield[1] = by;
00253 
00254   // e-field
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 // code for 3d interpolation
00354 
00355 // // create a field mesh in the "world" coordinates from list of field values
00356 // void BDSXYMagField::Prepare(G4VPhysicalVolume *referenceVolume)
00357 // {
00358 //   G4cout<<"BDSXYMagField:: create XY field mesh"<<G4endl;
00359   
00360 //   const G4RotationMatrix* Rot=referenceVolume->GetFrameRotation();
00361 //   const G4ThreeVector Trans=referenceVolume->GetFrameTranslation();
00362   
00363 //   G4ThreeVector B;
00364 
00365 
00366 //   // mesh physical dimensions
00367 
00368 
00369 //   std::vector<struct XYFieldRecord>::iterator it, itt;
00370 
00371 
00372 //   double xmax=0, ymax=0;
00373 
00374 //   for(it=itsFieldValues.begin();it!=itsFieldValues.end();it++)
00375 //     {
00376 //       if( fabs((*it).x ) > xmax ) xmax = fabs((*it).x);
00377 //       if( fabs((*it).y ) > ymax) ymax = fabs((*it).y);
00378 //     }
00379 
00380 //   itsField->xHalf = xmax;
00381 //   itsField->yHalf = ymax;
00382 //   itsField->zHalf = (zmax > 0) ? zmax : itsLength/2;
00383 
00384 //   G4double elementSizeX = itsField->xHalf;
00385 //   G4double elementSizeY = itsField->yHalf;
00386 
00387 //   //determine mesh step - minimum distance between measurement points
00388   
00389 //   double hx=elementSizeX*2, hxold=elementSizeX*2, hxmax=0;
00390 //   double hy=elementSizeY*2, hyold=elementSizeY*2, hymax=0;
00391 //   double hz=itsLength, hzold=itsLength, hzmax=0;
00392 
00393 
00394 //   for(it=++itsFieldValues.begin();it!=itsFieldValues.end();it++)
00395 //     {
00396 
00397 //       for(itt=itsFieldValues.begin();itt!=itsFieldValues.end();itt++)
00398 //      {
00399       
00400 //        //G4cout<<(*it).x<<" "<<(*it).y<<" "<<(*it).z<<" "<<(*it).Bx<<G4endl;
00401 //             hxold = fabs((*it).x - (*itt).x);
00402 //             if( (hxold > 1.0e-1)&&(hxold<hx) ) hx = hxold;
00403       
00404 //             hyold = fabs((*it).y - (*itt).y);
00405 //             if( (hyold > 1.0e-1)&&(hyold<hy) ) hy = hyold;
00406       
00407 //             hzold = fabs((*it).z - (*itt).z);
00408 //             if( (hzold > 1.0e-1)&&(hzold<hz) ) hz = hzold;
00409 //      }
00410 //     }
00411 
00412 //   hxmax = hx;
00413 //   hymax = hy;
00414 //   hzmax = hz;
00415 
00416 //   G4cout<<"h ="<<hx<<":"<<hy<<":"<<hz<<G4endl;
00417 //   G4cout<<"xmax ="<<xmax<<":"<<ymax<<":"<<zmax<<G4endl;
00418 
00419 
00420 //   // allocate mesh
00421 
00422 
00423 //   G4int nX = static_cast<int> ( 2*elementSizeX / hx ) + 1;
00424 //   G4int nY = static_cast<int> ( 2*elementSizeY / hy ) + 1;
00425 //   G4int nZ = static_cast<int> ( itsLength / hz ) + 1;
00426 
00427   
00428 
00429 //   G4cout<<"N ="<<nX<<":"<<nY<<G4endl;
00430 
00431 //   AllocateMesh(nX,nY);
00432   
00433 //   SetOriginRotation(Rot);
00434 //   SetOriginTranslation(Trans);
00435   
00436 //   itsField->AllocateMesh(nX,nY,nZ);
00437 
00438 
00439 //   G4double rmax = 0.6 * sqrt(hxmax*hxmax + hymax*hymax + hzmax*hzmax);
00440 
00441 //    // transverse maps
00442 //   if (nZ ==2) rmax = sqrt(hxmax*hxmax + hymax*hymax);
00443 
00444 //   G4cout<<"rmax ="<<rmax<<G4endl;
00445 
00446 //   G4double x, y, z;
00447 //   std::vector<struct FieldRecord> vals;
00448 //   std::vector<double> rs;
00449 
00450 //   for(int i=0; i<nX;i++)
00451 //      for(int j=0;j<nY;j++)
00452 //        for(int k=0; k<nZ;k++)
00453 //       {
00454 //         x =  i * hx - elementSizeX;
00455 //         y =  j * hy - elementSizeY;
00456 //         z =  k * hz - itsLength/2;
00457            
00458 //         //G4cout<<" x="<<x<<" y="<<y<<" z="<<z<<G4endl;
00459 //         //G4cout<<" i="<<i<<" j="<<j<<" k="<<k<<G4endl;
00460 
00461 //         for(it=itsFieldValues.begin();it!=itsFieldValues.end();it++)
00462 //           {
00463 //             G4double r = sqrt( ((*it).x-x)*((*it).x-x) +
00464 //                                ((*it).y-y)*((*it).y-y) + 
00465 //                                ((*it).z-z)*((*it).z-z) );
00466 
00467 //             // transverse maps
00468 //             if (nZ ==2) r = sqrt( ((*it).x-x)*((*it).x-x) +
00469 //                                   ((*it).y-y)*((*it).y-y));
00470 
00471 //             if(r < 1.e-3) r = 1.e-3;
00472 
00473 //             //G4cout<<"trying "<<(*it).x<<" "<<(*it).y<<" "<<(*it).z<<G4endl;
00474 //             //G4cout<<"r="<<r<<G4endl;
00475                
00476 //             if( r < rmax  )
00477 //               {
00478 //                 //G4cout<<"yes"<<G4endl;
00479 
00480 //                 vals.push_back((*it));
00481 //                 rs.push_back(r);
00482 //               }
00483 //           }
00484 
00485 //         //compute weighted means
00486 
00487 //         G4int N = rs.size();
00488 
00489 //         G4double bxmean=0, bymean=0,bzmean=0,rmean=0;
00490 
00491 //         //G4cout<<"computing mean...N="<<N<<G4endl;
00492 
00493 //         for(int npt=0;npt<N;npt++)
00494 //           {
00495 //             //G4cout<<"npt="<<npt<<G4endl;
00496 
00497 //             bxmean += vals[npt].Bx / ( rs[npt] * rs[npt]* rs[npt] );
00498 //             bymean += vals[npt].By / ( rs[npt] * rs[npt]* rs[npt] );
00499 //             bzmean += vals[npt].Bz / ( rs[npt] * rs[npt]* rs[npt] );
00500 
00501 //             rmean += 1/( rs[npt] * rs[npt]* rs[npt] );
00502 //           }
00503 
00504 //         if( N >0 )
00505 //           {
00506 //             bxmean /= (rmean);
00507 //             bymean /= (rmean);
00508 //             bzmean /= (rmean);
00509 //           }
00510 //         else
00511 //           {
00512 //             bxmean = 0;
00513 //             bymean = 0;
00514 //             bzmean = 0;
00515 //           }
00516 //         //G4cout<<"writing values..."<<i<<" "<<j<<" "<<k<<G4endl;
00517 //         //G4cout<<"x"<<G4endl;
00518            
00519 //         itsField->SetBx(i,j,k,bxmean * CLHEP::tesla);
00520            
00521 //         itsField->SetBy(i,j,k,bymean * CLHEP::tesla);
00522            
00523 //         itsField->SetBz(i,j,k,bzmean * CLHEP::tesla);
00524 
00525            
00526 
00527 //         vals.clear();
00528 //         rs.clear();
00529 //       }
00530 
00531 
00532 //   // dump the field mes for test
00533 
00534 //   G4cout<<"writing test file"<<G4endl;
00535 
00536 //   ofstream testf("btest.dat");
00537 
00538 //    for(int i=0; i<nX;i++)
00539 //      for(int j=0;j<nY;j++)
00540 //        for(int k=0; k<nZ;k++)
00541 //       {
00542 //         testf<<i<<" "<<j<<" "<<k<<" "<<
00543 //           itsField->GetBx(i,j,k)<<" "<<
00544 //           itsField->GetBy(i,j,k)<<" "<<
00545 //           itsField->GetBz(i,j,k)<<endl;
00546 //       }
00547 
00548 //    testf.close();
00549 
00550 // }

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7