00001
00007
00008 #include "Riostream.h"
00009 #include "GaudiKernel/SvcFactory.h"
00010 #include "GaudiKernel/ISvcLocator.h"
00011 #include "GaudiKernel/MsgStream.h"
00012 #include "GaudiKernel/SystemOfUnits.h"
00013
00014 #include "AnalyticFieldSvc.h"
00015
00016
00017 #include "GaudiKernel/Vector3DTypes.h"
00018 #include "GaudiKernel/Point3DTypes.h"
00019
00020 #include "MagVec.h"
00021 #include "MagMat.h"
00022
00023
00024 #include <cstdlib>
00025 #include <fstream>
00026 #include <cstring>
00027
00028
00029 #define NREG 15
00030
00031
00032
00033 DECLARE_SERVICE_FACTORY( AnalyticFieldSvc );
00034
00035
00036
00037
00038 AnalyticFieldSvc::AnalyticFieldSvc( const std::string& name,
00039 ISvcLocator* svc ) : Service( name, svc )
00040 {
00041
00042 m_nREG =0;
00043 m_nREGmin =0;
00044 m_nREGmax =0;
00045
00046
00047
00048
00049
00050
00051
00052 m_constFieldVector.push_back( 0. );
00053 m_constFieldVector.push_back( 0. );
00054 m_constFieldVector.push_back( 0. );
00055
00056
00057 declareProperty( "BxMapFile",m_filename[0] = "BxMapFileNotSet");
00058 declareProperty( "ByMapFile",m_filename[1] = "ByMapFileNotSet");
00059 declareProperty( "BzMapFile",m_filename[2] = "BzMapFileNotSet");
00060 declareProperty( "UseConstantField", m_useConstField = false );
00061 declareProperty( "ConstantFieldVector", m_constFieldVector );
00062 declareProperty( "ScaleFactor", m_scaleFactor = 1. );
00063 declareProperty( "ZOffSet", m_zOffSet = -50.);
00064
00065 }
00066
00067
00068
00069 AnalyticFieldSvc::~AnalyticFieldSvc()
00070 {
00071 }
00072
00073
00074
00075
00076 StatusCode AnalyticFieldSvc::initialize()
00077 {
00078 MsgStream log(msgSvc(), name());
00079 StatusCode status = Service::initialize();
00080 if( status.isFailure() ) return status;
00081
00082 if( m_useConstField ) {
00083 log << MSG::WARNING << "using constant magnetic field with field vector "
00084 << m_constFieldVector << " (Tesla)" << endmsg;
00085 return StatusCode::SUCCESS;
00086 }
00087
00088 if( 1. != m_scaleFactor ) {
00089 log << MSG::WARNING << "Field map will be scaled by a factor = "
00090 << m_scaleFactor << endmsg;
00091 }
00092
00093 status = GetParam();
00094 if ( status.isSuccess() ) {
00095 log << MSG::DEBUG << "B maps read successfully" << endreq;
00096
00097 return status;
00098 }
00099 else {
00100 log << MSG::DEBUG << "B maps failed" << endreq;
00101 return StatusCode::FAILURE;
00102 }
00103
00104
00105
00106
00107 }
00108
00109
00110
00111
00112 StatusCode AnalyticFieldSvc::finalize()
00113 {
00114 MsgStream log( msgSvc(), name() );
00115 StatusCode status = Service::finalize();
00116
00117 ClearMaps();
00118
00119
00120 if ( status.isSuccess() )
00121 log << MSG::INFO << "Service finalized successfully" << endreq;
00122 return status;
00123 }
00124
00125
00126
00127
00128 StatusCode AnalyticFieldSvc::queryInterface( const InterfaceID& riid,
00129 void** ppvInterface )
00130 {
00131 StatusCode sc = StatusCode::FAILURE;
00132 if ( ppvInterface ) {
00133 *ppvInterface = 0;
00134
00135 if ( riid == IMagneticFieldSvc::interfaceID() ) {
00136 *ppvInterface = static_cast<IMagneticFieldSvc*>(this);
00137 sc = StatusCode::SUCCESS;
00138 addRef();
00139 }
00140 else
00141 sc = Service::queryInterface( riid, ppvInterface );
00142 }
00143 return sc;
00144 }
00145
00146
00147
00148
00149
00150
00151 StatusCode AnalyticFieldSvc::GetParam() {
00152 StatusCode sc = StatusCode::FAILURE;
00153
00154 MsgStream log( msgSvc(), name() );
00155
00156 for(int ifile=0;ifile<3;ifile++) {
00157
00158 char line[ 255 ];
00159
00160
00161
00162 std::ifstream infile( m_filename[ifile].c_str() );
00163
00164
00165
00166
00167 if (!infile) {
00168 log << MSG::ERROR << "Unable to open BMap : "
00169 << m_filename[ifile] << endreq;
00170
00171 }
00172
00173
00174 if (infile) {
00175 sc = StatusCode::SUCCESS;
00176 log << MSG::INFO << "BMap opened successfully : " << m_filename[ifile]
00177 << endreq;
00178
00179
00180 do{
00181 infile.getline( line, 255 );
00182 } while( line[0] != 'N' || line[1] !='R');
00183
00184
00185
00186 int nmap = 0;
00187
00188 char* token = strtok( line, " " );
00189 do{
00190
00191 if ( token ) {
00192 if (nmap==1) m_nREG = atoi(token);
00193 token = strtok( NULL, " ");
00194 }
00195 else continue;
00196 nmap++;
00197 } while (token != NULL);
00198
00199 std::cout<<" READ NUMBER OF REGIONS m_nREG: "<<m_nREG<<std::endl;
00200 if (ifile==0) Bxmap.reserve(m_nREG);
00201 if (ifile==1) Bymap.reserve(m_nREG);
00202 if (ifile==2) Bzmap.reserve(m_nREG);
00203 if (ifile==0) {zmin.reserve(m_nREG);
00204 zmax.reserve(m_nREG);
00205 }
00206
00207
00208
00209 do{
00210 infile.getline( line, 255 );
00211 } while( line[0] != 'N' || line[1] !='Y');
00212
00213 token = strtok( line, " " );
00214 nmap=0;
00215
00216
00217 do{
00218
00219 if ( token ) {
00220 if (nmap==1) m_nREGmin = atoi(token);
00221 if (nmap==2) m_nREGmax = atoi(token);
00222 token = strtok( NULL, " ");
00223 }
00224 else continue;
00225 nmap++;
00226 } while (token != NULL);
00227
00228 std::cout<<" FIRST REGION WITH Y30: "<<m_nREGmin<<std::endl;
00229 std::cout<<" LAST REGION WITH Y30: "<<m_nREGmax<<std::endl;
00230
00231
00232 do{
00233 infile.getline( line, 255 );
00234 } while( line[0] != 'M' && line[1] !='I');
00235
00236
00237
00238
00239 std::string* sZmin = new std::string[m_nREG];
00240
00241 token = strtok( line, " " );
00242 int izmin = 0;
00243
00244
00245 do{
00246
00247 if ( token ) {
00248 if (izmin>0) sZmin[izmin-1] = token;
00249 token = strtok( NULL, " ");
00250 }
00251 else continue;
00252 izmin++;
00253 } while (token != NULL);
00254
00255 for(int w=0;w<m_nREG;w++) {
00256
00257 zmin[w] = atof( sZmin[w].c_str() ) ;
00258 }
00259
00260
00261
00262 do{
00263 infile.getline( line, 255 );
00264 } while( line[0] != 'M' && line[1] !='A');
00265
00266
00267
00268 std::string* sZmax = new std::string[NREG];
00269
00270 token = strtok( line, " " );
00271 int izmax = 0;
00272 do{
00273 if ( token ) {
00274
00275 if (izmax>0) sZmax[izmax-1] = token;
00276 token = strtok( NULL, " ");
00277 }
00278 else continue;
00279 izmax++;
00280 } while (token != NULL);
00281
00282
00283
00284 for(int x=0;x<m_nREG;x++) {
00285
00286 zmax[x] = atof( sZmax[x].c_str() ) ;
00287 }
00288
00289
00290 for(int k=0;k<m_nREG;k++) {
00291
00292
00293 do{
00294 infile.getline( line, 255 );
00295 } while( line[0] != 'R' );
00296
00297
00298
00299 std::string sTerms[4];
00300 char* token = strtok( line, " " );
00301 int ip = 0;
00302 do{
00303 if ( token ) { sTerms[ip] = token; token = strtok( NULL, " " );}
00304 else continue;
00305 ip++;
00306 } while ( token != NULL );
00307
00308 int nterms = atoi( sTerms[1].c_str() );
00309 int nterms2 = 0;
00310 if (m_nREGmax>0 && k>=(m_nREGmin-1) && k<=(m_nREGmax-1)) nterms2 = atoi( sTerms[3].c_str() );
00311
00312 log << MSG::INFO <<" REGION NUMBER: "<<k<<endreq;
00313
00314 log << MSG::INFO << "NTERMS " << nterms << endreq;
00315 if (m_nREGmax>0 && k>=(m_nREGmin-1) && k<=(m_nREGmax-1)) log << MSG::INFO << "NTERMS FOR Y>YMAX-30 REGION: " << nterms2 << endreq;
00316 MagMat* temp = new MagMat(nterms+2,4);
00317
00318
00319 for(int l=0;l<nterms+3;l++) {
00320
00321 infile.getline( line, 255 );
00322 if ( line[0] == '#' ) continue;
00323 std::string sPowx, sPowy, sPowz, sCoef;
00324 char* token = strtok( line, " " );
00325 if ( token ) { sPowx = token; token = strtok( NULL, " " );} else continue;
00326 if ( token ) { sPowy = token; token = strtok( NULL, " " );} else continue;
00327 if ( token ) { sPowz = token; token = strtok( NULL, " " );} else continue;
00328 if ( token ) { sCoef = token; token = strtok( NULL, " " );} else continue;
00329 if ( token != NULL ) continue;
00330
00331 double Powx = atof( sPowx.c_str() );
00332 double Powy = atof( sPowy.c_str() );
00333 double Powz = atof( sPowz.c_str() );
00334 double Coef = atof( sCoef.c_str() );
00335
00336
00337
00338
00339
00340
00341 if (l>0) {
00342 (*temp)[l-1][0]= Powx ;
00343 (*temp)[l-1][1]= Powy ;
00344 (*temp)[l-1][2]= Powz ;
00345 (*temp)[l-1][3]= Coef ;
00346 }
00347
00348
00349 }
00350
00351 if (ifile ==0) Bxmap.push_back(temp);
00352 if (ifile ==1) Bymap.push_back(temp);
00353 if (ifile ==2) Bzmap.push_back(temp);
00354
00355
00356 if (m_nREGmax>0 && k>=(m_nREGmin-1) && k<=(m_nREGmax-1)) {
00357
00358 MagMat* temp2 = new MagMat(nterms2+2,4);
00359
00360 infile.getline( line, 255 );
00361
00362
00363 for(int l=0;l<nterms2+2;l++) {
00364
00365
00366 infile.getline( line, 255 );
00367 if ( line[0] == '#' ) continue;
00368 std::string sPowx, sPowy, sPowz, sCoef;
00369 char* token = strtok( line, " " );
00370 if ( token ) { sPowx = token; token = strtok( NULL, " " );} else continue;
00371 if ( token ) { sPowy = token; token = strtok( NULL, " " );} else continue;
00372 if ( token ) { sPowz = token; token = strtok( NULL, " " );} else continue;
00373 if ( token ) { sCoef = token; token = strtok( NULL, " " );} else continue;
00374 if ( token != NULL ) continue;
00375
00376 double Powx = atof( sPowx.c_str() );
00377 double Powy = atof( sPowy.c_str() );
00378 double Powz = atof( sPowz.c_str() );
00379 double Coef = atof( sCoef.c_str() );
00380
00381
00382
00383
00384
00385
00386
00387
00388 (*temp2)[l][0]= Powx ;
00389 (*temp2)[l][1]= Powy ;
00390 (*temp2)[l][2]= Powz ;
00391 (*temp2)[l][3]= Coef ;
00392
00393
00394
00395 }
00396
00397 if (ifile ==0) Bxmap.push_back(temp2);
00398 if (ifile ==1) Bymap.push_back(temp2);
00399 if (ifile ==2) Bzmap.push_back(temp2);
00400
00401 }
00402
00403
00404
00405
00406 }
00407
00408 delete sZmin;
00409 delete sZmax;
00410 infile.close();
00411 }
00412
00413 }
00414
00415 return sc;
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 StatusCode AnalyticFieldSvc::fieldVector(const Gaudi::XYZPoint& r,
00581 Gaudi::XYZVector& b ) const {
00582
00583 Bcalculation(r,b);
00584
00585 return StatusCode::SUCCESS;
00586 }
00587
00588
00589
00590
00591 void AnalyticFieldSvc::Bcalculation (const Gaudi::XYZPoint& point,
00592 Gaudi::XYZVector& bf ) const {
00593
00594
00595 bf.SetXYZ(0,0,0);
00596
00597 if( m_useConstField ) {
00598 bf.SetXYZ( m_constFieldVector[0]*Gaudi::Units::tesla,
00599 m_constFieldVector[1]*Gaudi::Units::tesla,
00600 m_constFieldVector[2]*Gaudi::Units::tesla );
00601 return;
00602 }
00603
00604 MagVec coord(3);
00605
00606 coord[0]=fabs(point.x())/Gaudi::Units::m;
00607 coord[1]=fabs(point.y())/Gaudi::Units::m;
00608 coord[2]=point.z()/Gaudi::Units::m;
00609
00610 int iReg = 0;
00611
00612
00613 for (int iz=0;iz <m_nREG;iz++) {
00614
00615 iReg=iz;
00616
00617 bool condZ = zmin[iz]<=point.z()/Gaudi::Units::cm && point.z()/Gaudi::Units::cm<zmax[iz] && coord[0]<(fabs(coord[2])*tan(0.3)) && coord[1]<(fabs(coord[2])*tan(0.25));
00618
00619
00620 if (m_nREGmax>0 && iz>=(m_nREGmin-1) && iz<=(m_nREGmax-1)) {
00621 iReg = 2*iz-(m_nREGmin-1);
00622 if (fabs(coord[1]) > (*(Bxmap[iReg]))[1][1]) iReg++;
00623 }
00624
00625 if(m_nREGmax>0 && iz>=m_nREGmax) iReg = iz+(m_nREGmax-m_nREGmin+1);
00626
00627
00628 if (condZ) {
00629
00630
00631 bf.SetXYZ(EvaluateField(coord,*(Bxmap[iReg])),EvaluateField(coord,*(Bymap[iReg])),EvaluateField(coord,*(Bzmap[iReg])));
00632
00633 }
00634
00635 }
00636
00637 bf*=Gaudi::Units::tesla;
00638
00639 if( point.x() < 0. && point.y() >= 0. ){
00640 bf.SetX( -bf.x() );
00641 }
00642 else if( point.x() < 0. && point.y() < 0. ){
00643 bf.SetZ( -bf.z() );
00644 }
00645 else if( point.x() >= 0. && point.y() < 0. ){
00646 bf.SetX( -bf.x() );
00647 bf.SetZ( -bf.z() );
00648 }
00649
00650 return ;
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 double AnalyticFieldSvc::EvaluateField(MagVec& pos, MagMat& bmap) const{
00710
00711 double returnValue = bmap[0][3];
00712 int i = 0, j = 0, k = 0;
00713 for (i = 2; i < bmap.nrow(); i++) {
00714
00715 double term = bmap[i][3];
00716 for (j = 0; j < 3; j++) {
00717
00718 int power = int(bmap[i][j]);
00719 double p1 = 1, p2 = 0, p3 = 0, r = 0;
00720 double v = 1 + 2. / (bmap[1][j] - bmap[0][j]) * (pos[j] - bmap[1][j]);
00721
00722 switch(power) {
00723 case 1: r = 1; break;
00724 case 2: r = v; break;
00725 default:
00726 p2 = v;
00727 for (k = 3; k <= power; k++) {
00728 p3 = p2 * v;
00729 p3 = 2 * v * p2 - p1;
00730 p1 = p2; p2 = p3;
00731 }
00732 r = p3;
00733 }
00734
00735 term *= r;
00736 }
00737
00738 returnValue += term;
00739 }
00740
00741 return returnValue;
00742
00743 }
00744
00745
00746
00747
00748
00749
00750 void AnalyticFieldSvc::ClearMaps()
00751 {
00752
00753
00754 for (std::vector<MagMat*>::const_iterator iMatBx = Bxmap.begin();
00755 iMatBx != Bxmap.end();++iMatBx) {
00756 delete (*iMatBx);
00757 }
00758
00759 for (std::vector<MagMat*>::const_iterator iMatBy = Bymap.begin();
00760 iMatBy != Bymap.end();++iMatBy) {
00761 delete (*iMatBy);
00762 }
00763
00764 for (std::vector<MagMat*>::const_iterator iMatBz = Bzmap.begin();
00765 iMatBz != Bzmap.end();++iMatBz) {
00766 delete (*iMatBz);
00767 }
00768
00769 }
00770