CMS 3D CMS Logo

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