src/BDSXYMagField.cc

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

Generated on 27 Aug 2013 for BDSIM by  doxygen 1.4.7