00001
00002
00003
00004
00005 #include "GaudiKernel/ToolFactory.h"
00006 #include "GaudiKernel/SystemOfUnits.h"
00007
00008
00009 #include "MagFieldTool.h"
00010
00011 #include <fstream>
00012 #include <cstring>
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 DECLARE_TOOL_FACTORY( MagFieldTool );
00023
00024
00025
00026
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
00042
00043 MagFieldTool::~MagFieldTool() {}
00044
00045
00046
00047
00048 StatusCode MagFieldTool::updateMap( const std::vector<std::string>& theFiles,
00049 const double& scaleFactor )
00050 {
00051
00052 if( theFiles.size() != 4 )
00053 return Error( "Real field map requires four input files" );
00054
00055
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
00066
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
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
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
00106 char line[ 255 ];
00107 do{
00108 infile.getline( line, 255 );
00109 } while( line[0] != 'P' );
00110
00111
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
00123 do{
00124 infile.getline( line, 255 );
00125 } while( line[0] != 'G' );
00126
00127
00128 do{
00129 infile.getline( line, 255 );
00130 } while( line[0] != '#' );
00131
00132
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
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
00155 long int nlines = ( npar - 7 ) / 3;
00156
00157
00158 long int ncheck = 0;
00159
00160
00161
00162
00163 while( infile ) {
00164
00165
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
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
00181
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
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
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 }
00203
00204 return StatusCode::SUCCESS;
00205 }
00206
00207
00208
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
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
00252
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 }