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

In This Package:

MagFieldToolDC06.cpp

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