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

Generated on Wed Mar 5 17:25:23 2008 for BDSIM by  doxygen 1.5.3