| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

MagFieldTool.cpp

Go to the documentation of this file.
00001 // $Id: MagFieldTool.cpp,v 1.3 2008/10/28 15:43:27 cattanem Exp $
00002 // Include files 
00003 
00004 // from Gaudi
00005 #include "GaudiKernel/ToolFactory.h" 
00006 #include "GaudiKernel/SystemOfUnits.h" 
00007 
00008 // local
00009 #include "MagFieldTool.h"
00010 
00011 #include <fstream>
00012 #include <cstring> // for strtok with gcc 4.3
00013 
00014 
00015 //-----------------------------------------------------------------------------
00016 // Implementation file for class : MagFieldTool
00017 //
00018 // 2008-07-26 : Marco Cattaneo
00019 //-----------------------------------------------------------------------------
00020 
00021 // Declaration of the Tool Factory
00022 DECLARE_TOOL_FACTORY( MagFieldTool );
00023 
00024 
00025 //=============================================================================
00026 // Standard constructor, initializes variables
00027 //=============================================================================
00028 MagFieldTool::MagFieldTool( const std::string& type,
00029                             const std::string& name,
00030                             const IInterface* parent )
00031   : GaudiTool ( type, name , parent ),
00032     m_scaleFactor(0)
00033 {
00034   m_mapFileNames.push_back( "" );
00035   m_mapFileNames.push_back( "" );
00036   m_mapFileNames.push_back( "" );
00037   m_mapFileNames.push_back( "" );
00038   declareInterface<IMagFieldTool>(this);
00039 }
00040 //=============================================================================
00041 // Destructor
00042 //=============================================================================
00043 MagFieldTool::~MagFieldTool() {} 
00044 
00045 //=============================================================================
00046 // Update the cached field from the files theFiles scaled by scaleFactor
00047 //=============================================================================
00048 StatusCode MagFieldTool::updateMap( const std::vector<std::string>& theFiles,
00049                                     const double& scaleFactor ) 
00050 {
00051   // Check this is the right tool
00052   if( theFiles.size() != 4 )
00053     return Error( "Real field map requires four input files" );
00054     
00055   // If nothing has changed, return
00056   if( scaleFactor == m_scaleFactor &&
00057       theFiles[0] == m_mapFileNames[0] &&
00058       theFiles[1] == m_mapFileNames[1] &&
00059       theFiles[2] == m_mapFileNames[2] &&
00060       theFiles[3] == m_mapFileNames[3] ) {
00061     debug() << "Update called but nothing has changed, returning..." << endmsg;
00062     return StatusCode::SUCCESS;
00063   }
00064   
00065   // If the field map file has changed, re-read it and apply the scale factor
00066   // Reread also if previous scale factor was tiny, to avoid precision loss
00067   if( theFiles[0] != m_mapFileNames[0] ||
00068       theFiles[1] != m_mapFileNames[1] ||
00069       theFiles[2] != m_mapFileNames[2] ||
00070       theFiles[3] != m_mapFileNames[3] ||
00071       fabs(m_scaleFactor) < 1.e-6 ) {
00072     StatusCode sc = readFiles( theFiles, scaleFactor );
00073     if( sc.isFailure() ) return sc;
00074     m_mapFileNames[0] = theFiles[0];
00075     m_mapFileNames[1] = theFiles[1];
00076     m_mapFileNames[2] = theFiles[2];
00077     m_mapFileNames[3] = theFiles[3];
00078     m_scaleFactor = scaleFactor;
00079     info() << "Map scaled by factor " << m_scaleFactor << endmsg;
00080   }
00081   else {
00082     // Only the scale factor has changed, rescale
00083     double rescaleFactor = scaleFactor / m_scaleFactor;
00084     rescale( rescaleFactor );
00085     m_scaleFactor = scaleFactor;
00086     info() << "Map scaled by factor " << m_scaleFactor << endmsg;
00087   }
00088   return StatusCode::SUCCESS;
00089 }
00090 
00091 
00092 //=============================================================================
00093 // Read the field map files and scale by scaleFactor
00094 //=============================================================================
00095 StatusCode MagFieldTool::readFiles( const std::vector<std::string>& theFiles,
00096                                     const double& scaleFactor )
00097 {
00098 
00099   for(int ifile=0;ifile<4;ifile++) {
00100     std::ifstream infile( theFiles[ifile].c_str() );
00101   
00102     if ( infile ) {
00103       info() << "Opened magnetic field file : " << theFiles[ifile] << endmsg;
00104     
00105     // Skip the header till PARAMETER
00106       char line[ 255 ];
00107       do{
00108         infile.getline( line, 255 );
00109       } while( line[0] != 'P' );
00110     
00111       // Get the PARAMETER
00112       std::string sPar[2];
00113       char* token = strtok( line, " " );
00114       int ip = 0;
00115       do{
00116         if ( token ) { sPar[ip] = token; token = strtok( NULL, " " );} 
00117         else continue;
00118         ip++;
00119       } while ( token != NULL );
00120       long int npar = atoi( sPar[1].c_str() );
00121 
00122       // Skip the header till GEOMETRY
00123       do{
00124         infile.getline( line, 255 );
00125       } while( line[0] != 'G' );
00126     
00127       // Skip any comment before GEOMETRY 
00128       do{
00129         infile.getline( line, 255 );
00130       } while( line[0] != '#' );
00131     
00132       // Get the GEOMETRY
00133       infile.getline( line, 255 );
00134       std::string sGeom[7];
00135       token = strtok( line, " " );
00136       int ig = 0;
00137       do{
00138         if ( token ) { sGeom[ig] = token; token = strtok( NULL, " " );} 
00139         else continue; 
00140         ig++;  
00141       } while (token != NULL);
00142 
00143       // Grid dimensions are given in cm in CDF file. Convert to CLHEP units
00144       m_Dxyz[0] = atof( sGeom[0].c_str() ) * Gaudi::Units::cm;
00145       m_Dxyz[1] = atof( sGeom[1].c_str() ) * Gaudi::Units::cm;
00146       m_Dxyz[2] = atof( sGeom[2].c_str() ) * Gaudi::Units::cm;
00147       m_Nxyz[0] = atoi( sGeom[3].c_str() );
00148       m_Nxyz[1] = atoi( sGeom[4].c_str() );
00149       m_Nxyz[2] = atoi( sGeom[5].c_str() );
00150       m_zOffSet = atof( sGeom[6].c_str() ) * Gaudi::Units::cm;
00151     
00152       m_Q_quadr[ifile].clear();
00153       m_Q_quadr[ifile].reserve(npar - 7);
00154       // Number of lines with data to be read
00155       long int nlines = ( npar - 7 ) / 3;
00156     
00157       // Check number of lines with data read in the loop
00158       long int ncheck = 0;
00159     
00160       // Skip comments and fill a vector of magnetic components for the
00161       // x, y and z positions given in GEOMETRY
00162     
00163       while( infile ) {
00164         // parse each line of the file, 
00165         // comment lines begin with '#' in the cdf file
00166         infile.getline( line, 255 );
00167         if ( line[0] == '#' ) continue;
00168         std::string sFx, sFy, sFz; 
00169         char* token = strtok( line, " " );
00170         if ( token ) { sFx = token; token = strtok( NULL, " " );} else continue;
00171         if ( token ) { sFy = token; token = strtok( NULL, " " );} else continue;
00172         if ( token ) { sFz = token; token = strtok( NULL, " " );} else continue;
00173         if ( token != NULL ) continue;
00174       
00175         // Field values are given in gauss in CDF file. Convert to CLHEP units
00176         double fx = atof( sFx.c_str() ) * Gaudi::Units::gauss * scaleFactor;
00177         double fy = atof( sFy.c_str() ) * Gaudi::Units::gauss * scaleFactor;
00178         double fz = atof( sFz.c_str() ) * Gaudi::Units::gauss * scaleFactor;
00179       
00180         // Add the magnetic field components of each point to 
00181         // sequentialy in a vector 
00182         m_Q_quadr[ifile].push_back( fx );
00183         m_Q_quadr[ifile].push_back( fy );
00184         m_Q_quadr[ifile].push_back( fz );
00185         // counts after reading and filling to match the number of lines
00186         ncheck++; 
00187       }
00188       infile.close();
00189       if ( nlines != ncheck ) {
00190         return Error( " Number of points in field map does not match" );
00191       }
00192     }
00193     else {
00194       return Error( "Unable to open magnetic field file :" + theFiles[ifile]);
00195     }
00196   }
00197 
00198   // Update the map limits
00199   for (int iC = 0; iC< 3; ++iC ){
00200     m_min_FL[iC] = 0.0;
00201     m_max_FL[iC] = m_min_FL[iC]+( m_Nxyz[iC]-1 )* m_Dxyz[iC];
00202   } // iC
00203   
00204   return StatusCode::SUCCESS;
00205 }
00206 
00207 //=============================================================================
00208 // Rescale the existing field map by rescaleFactor
00209 //=============================================================================
00210 void MagFieldTool::rescale( const double& rescaleFactor ) 
00211 {
00212   for(int ifile=0;ifile<4;ifile++) {
00213     for ( std::vector<double>::iterator Q  = m_Q_quadr[ifile].begin();
00214                                         Q != m_Q_quadr[ifile].end(); ++Q ) {
00215       *Q = (*Q) * rescaleFactor;
00216     }
00217   }
00218 }
00219 
00220 //=============================================================================
00221 // Return the field vector fvec at the point xyz
00222 //=============================================================================
00223 void MagFieldTool::fieldVector( const Gaudi::XYZPoint& r,
00224                                 Gaudi::XYZVector& bf ) const 
00225 {
00226 
00227   bf.SetXYZ( 0.0, 0.0, 0.0 );
00228 
00230   double z = r.z() - m_zOffSet;
00231   if( !(z >= m_min_FL[2] && z < m_max_FL[2]) )  return;
00232   double x = fabs( r.x() );  
00233   if( !(x >= m_min_FL[0] && x < m_max_FL[0]) )  return;
00234   double y = fabs( r.y() );
00235   if( !(y >= m_min_FL[1] && y < m_max_FL[1]) )  return;
00236   int i = int( x/m_Dxyz[0]);
00237   int j = int( y/m_Dxyz[1] );
00238   int k = int( z/m_Dxyz[2] );
00239   
00240   int ijk000 = 3*( m_Nxyz[0]*( m_Nxyz[1]*k     + j )     + i );
00241   int ijk001 = 3*( m_Nxyz[0]*( m_Nxyz[1]*(k+1) + j )     + i );
00242   int ijk010 = 3*( m_Nxyz[0]*( m_Nxyz[1]*k     + j + 1 ) + i );
00243   int ijk011 = 3*( m_Nxyz[0]*( m_Nxyz[1]*(k+1) + j + 1)  + i );
00244   int ijk100 = 3*( m_Nxyz[0]*( m_Nxyz[1]*k     + j)      + i + 1 );
00245   int ijk101 = 3*( m_Nxyz[0]*( m_Nxyz[1]*(k+1) + j)      + i + 1 );
00246   int ijk110 = 3*( m_Nxyz[0]*( m_Nxyz[1]*k     + j + 1)  + i + 1 );
00247   int ijk111 = 3*( m_Nxyz[0]*( m_Nxyz[1]*(k+1) + j + 1 ) + i + 1 );
00248 
00249 
00250   
00251   // auxiliary variables defined at the vertices of the cube that
00252   // contains the (x, y, z) point where the field is interpolated
00253 
00254   double cx000,cx001,cx010,cx011,cx100,cx101,cx110,cx111,
00255          cy000,cy001,cy010,cy011,cy100,cy101,cy110,cy111,
00256          cz000,cz001,cz010,cz011,cz100,cz101,cz110,cz111;
00257 
00258   int iquadr=999;
00259     
00260   if(r.x() >=0)
00261     if( r.y() >=0) 
00262       iquadr=0;
00263     else
00264       iquadr=2;
00265   else
00266     if(r.y() >=0)
00267       iquadr=1;
00268     else
00269       iquadr=3;
00270 
00271 
00272   cx000 = (m_Q_quadr[iquadr])[ ijk000 ];
00273   cx001 = (m_Q_quadr[iquadr])[ ijk001 ];
00274   cx010 = (m_Q_quadr[iquadr])[ ijk010 ];
00275   cx011 = (m_Q_quadr[iquadr])[ ijk011 ];
00276   cx100 = (m_Q_quadr[iquadr])[ ijk100 ];
00277   cx101 = (m_Q_quadr[iquadr])[ ijk101 ];
00278   cx110 = (m_Q_quadr[iquadr])[ ijk110 ];
00279   cx111 = (m_Q_quadr[iquadr])[ ijk111 ];
00280   cy000 = (m_Q_quadr[iquadr])[ ijk000+1 ];
00281   cy001 = (m_Q_quadr[iquadr])[ ijk001+1 ];
00282   cy010 = (m_Q_quadr[iquadr])[ ijk010+1 ];
00283   cy011 = (m_Q_quadr[iquadr])[ ijk011+1 ];
00284   cy100 = (m_Q_quadr[iquadr])[ ijk100+1 ];
00285   cy101 = (m_Q_quadr[iquadr])[ ijk101+1 ];
00286   cy110 = (m_Q_quadr[iquadr])[ ijk110+1 ];
00287   cy111 = (m_Q_quadr[iquadr])[ ijk111+1 ];
00288   cz000 = (m_Q_quadr[iquadr])[ ijk000+2 ];
00289   cz001 = (m_Q_quadr[iquadr])[ ijk001+2 ];
00290   cz010 = (m_Q_quadr[iquadr])[ ijk010+2 ];
00291   cz011 = (m_Q_quadr[iquadr])[ ijk011+2 ];
00292   cz100 = (m_Q_quadr[iquadr])[ ijk100+2 ];
00293   cz101 = (m_Q_quadr[iquadr])[ ijk101+2 ];
00294   cz110 = (m_Q_quadr[iquadr])[ ijk110+2 ];
00295   cz111 = (m_Q_quadr[iquadr])[ ijk111+2 ];
00296   
00297   double hx1 = ( x-i*m_Dxyz[0] )/m_Dxyz[0];
00298   double hy1 = ( y-j*m_Dxyz[1] )/m_Dxyz[1];
00299   double hz1 = ( z-k*m_Dxyz[2] )/m_Dxyz[2];
00300   double hx0 = 1.0-hx1;
00301   double hy0 = 1.0-hy1;
00302   double hz0 = 1.0-hz1;
00303 
00304   double h000 = hx0*hy0*hz0;
00305   if( fabs(h000) > 0.0 &&
00306       cx000 > 9.0e5 && cy000 > 9.0e5 && cz000 > 9.0e5) return;
00307  
00308   double h001 = hx0*hy0*hz1;
00309   if( fabs(h001) > 0.0 && 
00310       cx001 > 9.0e5 && cy001 > 9.0e5 && cz001 > 9.0e5) return;
00311 
00312   double h010 = hx0*hy1*hz0;
00313   if( fabs(h010) > 0.0 && 
00314       cx010 > 9.0e5 && cy010 > 9.0e5 && cz010 > 9.0e5) return;
00315 
00316   double h011 = hx0*hy1*hz1;
00317   if( fabs(h011) > 0.0 && 
00318       cx011 > 9.0e5 && cy011 > 9.0e5 && cz011 > 9.0e5) return;
00319 
00320   double h100 = hx1*hy0*hz0;
00321   if( fabs(h100) > 0.0 && 
00322       cx100 > 9.0e5 && cy100 > 9.0e5 && cz100 > 9.0e5) return;
00323  
00324   double h101 = hx1*hy0*hz1;
00325   if( fabs(h101) > 0.0 && 
00326       cx101 > 9.0e5 && cy101 > 9.0e5 && cz101 > 9.0e5) return;
00327  
00328   double h110 = hx1*hy1*hz0;
00329   if( fabs(h110) > 0.0 && 
00330       cx110 > 9.0e5 && cy110 > 9.0e5 && cz110 > 9.0e5) return;
00331 
00332   double h111 = hx1*hy1*hz1;
00333   if( fabs(h111) > 0.0 && 
00334       cx111 > 9.0e5 && cy111 > 9.0e5 && cz111 > 9.0e5) return;
00335 
00336   bf.SetX ( cx000*h000 + cx001*h001 + cx010*h010 + cx011*h011 +
00337             cx100*h100 + cx101*h101 + cx110*h110 + cx111*h111);
00338   bf.SetY ( cy000*h000 + cy001*h001 + cy010*h010 + cy011*h011 +
00339             cy100*h100 + cy101*h101 + cy110*h110 + cy111*h111 );
00340   bf.SetZ ( cz000*h000 + cz001*h001 + cz010*h010 + cz011*h011 +
00341             cz100*h100 + cz101*h101 + cz110*h110 + cz111*h111 );
00342 
00343   if( r.x() < 0. && r.y() >= 0. ){
00344     bf.SetX( -bf.x() );
00345   }
00346   else if(  r.x() < 0. &&  r.y()  < 0. ){
00347     bf.SetZ( -bf.z() );
00348   }
00349   else if( r.x() >= 0. && r.y() < 0. ){    
00350     bf.SetX( -bf.x() );
00351     bf.SetZ( -bf.z() );
00352   } 
00353   return;
00354 }
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:04:54 2011 for Magnet by doxygen 1.4.7