CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_9_patch3/src/MagneticField/VolumeBasedEngine/src/MagGeometry.cc

Go to the documentation of this file.
00001 /*
00002  *  See header file for a description of this class.
00003  *
00004  *  $Date: 2012/03/21 23:01:46 $
00005  *  $Revision: 1.20 $
00006  *  \author N. Amapane - INFN Torino
00007  */
00008 
00009 #include "MagneticField/VolumeBasedEngine/interface/MagGeometry.h"
00010 #include "MagneticField/VolumeGeometry/interface/MagVolume.h"
00011 #include "MagneticField/VolumeGeometry/interface/MagVolume6Faces.h"
00012 #include "MagneticField/Layers/interface/MagBLayer.h"
00013 #include "MagneticField/Layers/interface/MagESector.h"
00014 
00015 #include "Utilities/BinningTools/interface/PeriodicBinFinderInPhi.h"
00016 
00017 #include <FWCore/ParameterSet/interface/ParameterSet.h>
00018 
00019 #include "MagneticField/Layers/interface/MagVerbosity.h"
00020 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00021 
00022 using namespace std;
00023 using namespace edm;
00024 
00025 MagGeometry::MagGeometry(const edm::ParameterSet& config, std::vector<MagBLayer *> tbl,
00026                          std::vector<MagESector *> tes,
00027                          std::vector<MagVolume6Faces*> tbv,
00028                          std::vector<MagVolume6Faces*> tev) : 
00029   lastVolume(0), theBLayers(tbl), theESectors(tes), theBVolumes(tbv), theEVolumes(tev), geometryVersion(0)
00030 {
00031   
00032   cacheLastVolume = config.getUntrackedParameter<bool>("cacheLastVolume", true);
00033 
00034   // FIXME: wait geometryVersion to be propagated to all cfgs.
00035   if (config.exists("geometryVersion")) {
00036     geometryVersion = config.getParameter<int>("geometryVersion");
00037   } else {
00038     geometryVersion = 90322;
00039   }  
00040 
00041   vector<double> rBorders;
00042 
00043   for (vector<MagBLayer *>::const_iterator ilay = theBLayers.begin();
00044        ilay != theBLayers.end(); ++ilay) {
00045     if (verbose::debugOut) cout << "  Barrel layer at " << (*ilay)->minR() <<endl;
00046     //FIXME assume layers are already sorted in minR
00047     rBorders.push_back((*ilay)->minR());
00048   }
00049 
00050   theBarrelBinFinder = new MagBinFinders::GeneralBinFinderInR<double>(rBorders);
00051 
00052   if (verbose::debugOut) {
00053     for (vector<MagESector *>::const_iterator isec = theESectors.begin();
00054          isec != theESectors.end(); ++isec) {
00055       cout << "  Endcap sector at " << (*isec)->minPhi() << endl;
00056     }
00057   }
00058 
00059   //FIXME assume sectors are already sorted in phi
00060   //FIXME: PeriodicBinFinderInPhi gets *center* of first bin
00061   int nEBins = theESectors.size();
00062   theEndcapBinFinder = new PeriodicBinFinderInPhi<float>(theESectors.front()->minPhi()+Geom::pi()/nEBins, nEBins);
00063 
00064 }
00065 
00066 MagGeometry::~MagGeometry(){
00067   delete theBarrelBinFinder;
00068   delete theEndcapBinFinder;
00069 
00070   for (vector<MagBLayer *>::const_iterator ilay = theBLayers.begin();
00071        ilay != theBLayers.end(); ++ilay) {
00072     delete (*ilay);
00073   }
00074 
00075   for (vector<MagESector *>::const_iterator ilay = theESectors.begin();
00076        ilay != theESectors.end(); ++ilay) {
00077     delete (*ilay);
00078   }
00079 }
00080 
00081 
00082 // Return field vector at the specified global point
00083 GlobalVector MagGeometry::fieldInTesla(const GlobalPoint & gp) const {
00084   MagVolume * v = 0;
00085 
00086   
00087   v = findVolume(gp);
00088   if (v!=0) {
00089     return v->fieldInTesla(gp);
00090   }
00091   
00092   // Fall-back case: no volume found
00093   
00094   if (isnan(gp.mag())) {
00095     LogWarning("InvalidInput") << "Input value invalid (not a number): " << gp << endl;
00096       
00097   } else {
00098     LogWarning("MagneticField") << "MagGeometry::fieldInTesla: failed to find volume for " << gp << endl;
00099   }
00100   return GlobalVector();
00101 }
00102 
00103 
00104 // Linear search implementation (just for testing)
00105 MagVolume* 
00106 MagGeometry::findVolume1(const GlobalPoint & gp, double tolerance) const {  
00107 
00108   MagVolume6Faces * found = 0;
00109 
00110   if (inBarrel(gp)) { // Barrel
00111     for (vector<MagVolume6Faces*>::const_iterator v = theBVolumes.begin();
00112          v!=theBVolumes.end(); ++v){
00113       if ((*v)==0) { //FIXME: remove this check
00114         cout << endl << "***ERROR: MagGeometry::findVolume: MagVolume not set" << endl;
00115         continue;
00116       }
00117       if ((*v)->inside(gp,tolerance)) {
00118         found = (*v);
00119         break;
00120       }
00121     }
00122 
00123   } else { // Endcaps
00124     for (vector<MagVolume6Faces*>::const_iterator v = theEVolumes.begin();
00125          v!=theEVolumes.end(); ++v){
00126       if ((*v)==0) {  //FIXME: remove this check
00127         cout << endl << "***ERROR: MagGeometry::findVolume: MagVolume not set" << endl;
00128         continue;
00129       }
00130       if ((*v)->inside(gp,tolerance)) {
00131         found = (*v);
00132         break;
00133       }
00134     }
00135   }  
00136   
00137   return found;
00138 }
00139 
00140 // Use hierarchical structure for fast lookup.
00141 MagVolume* 
00142 MagGeometry::findVolume(const GlobalPoint & gp, double tolerance) const{
00143   // Check volume cache
00144   if (lastVolume!=0 && lastVolume->inside(gp)){
00145     return lastVolume;
00146   }
00147 
00148   MagVolume * result=0;
00149   if (inBarrel(gp)) { // Barrel
00150     double R = gp.perp();
00151     int bin = theBarrelBinFinder->binIndex(R);
00152     
00153     for (int bin1 = bin; bin1 >= max(0,bin-2); --bin1) {
00154       if (verbose::debugOut) cout << "Trying layer at R " << theBLayers[bin1]->minR()
00155                       << " " << R << endl ;
00156       result = theBLayers[bin1]->findVolume(gp, tolerance);
00157       if (verbose::debugOut) cout << "***In blayer " << bin1-bin << " " 
00158                       << (result==0? " failed " : " OK ") <<endl;
00159       if (result != 0) break;
00160     }
00161 
00162   } else { // Endcaps
00163     Geom::Phi<float> phi = gp.phi();
00164     int bin = theEndcapBinFinder->binIndex(phi);
00165     if (verbose::debugOut) cout << "Trying endcap sector at phi "
00166                     << theESectors[bin]->minPhi() << " " << phi << endl ;
00167     result = theESectors[bin]->findVolume(gp, tolerance);
00168     if (verbose::debugOut) cout << "***In guessed esector "
00169                     << (result==0? " failed " : " OK ") <<endl;
00170   }
00171 
00172 
00173   if (result==0 && tolerance < 0.0001) {
00174     // If search fails, retry with a 300 micron tolerance.
00175     // This is a hack for thin gaps on air-iron boundaries,
00176     // which will not be present anymore once surfaces are matched.
00177     if (verbose::debugOut) cout << "Increasing the tolerance to 0.03" <<endl;
00178     result = findVolume(gp, 0.03);
00179   }
00180 
00181   if (cacheLastVolume) lastVolume = result;
00182 
00183   return result;
00184 }
00185 
00186 
00187 
00188 
00189 bool MagGeometry::inBarrel(const GlobalPoint& gp) const {
00190   float Z = fabs(gp.z());
00191   float R = gp.perp();
00192 
00193   // FIXME: Get these dimensions from the builder. 
00194   if (geometryVersion>=90812) {
00195     return (Z<350. ||
00196             (R>172.4 && Z<633.89) || 
00197             (R>308.755 && Z<662.01));    
00198   } else {
00199     return (Z<350. ||
00200             (R>172.4 && Z<633.29) || 
00201             (R>308.755 && Z<661.01));
00202   }
00203 }
00204