CMS 3D CMS Logo

MagGeometry.cc

Go to the documentation of this file.
00001 /*
00002  *  See header file for a description of this class.
00003  *
00004  *  $Date: 2009/03/03 13:07:49 $
00005  *  $Revision: 1.17 $
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 "Utilities/Timing/interface/TimingReport.h"
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)
00031 {
00032   
00033   cacheLastVolume = config.getUntrackedParameter<bool>("cacheLastVolume", true);
00034   v_85l = (config.getParameter<std::string>("version")=="grid_85l_030919");
00035 
00036   vector<double> rBorders;
00037 
00038   for (vector<MagBLayer *>::const_iterator ilay = theBLayers.begin();
00039        ilay != theBLayers.end(); ++ilay) {
00040     if (verbose::debugOut) cout << "  Barrel layer at " << (*ilay)->minR() <<endl;
00041     //FIXME assume layers are already sorted in minR
00042     rBorders.push_back((*ilay)->minR());
00043   }
00044 
00045   theBarrelBinFinder = new MagBinFinders::GeneralBinFinderInR<double>(rBorders);
00046 
00047   if (verbose::debugOut) {
00048     for (vector<MagESector *>::const_iterator isec = theESectors.begin();
00049          isec != theESectors.end(); ++isec) {
00050       cout << "  Endcap sector at " << (*isec)->minPhi() << endl;
00051     }
00052   }
00053 
00054   //FIXME assume sectors are already sorted in phi
00055   //FIXME: PeriodicBinFinderInPhi gets *center* of first bin
00056   theEndcapBinFinder = new PeriodicBinFinderInPhi<float>(theESectors.front()->minPhi()+Geom::pi()/12., 12);
00057 
00058 }
00059 
00060 MagGeometry::~MagGeometry(){
00061   delete theBarrelBinFinder;
00062   delete theEndcapBinFinder;
00063 
00064   for (vector<MagBLayer *>::const_iterator ilay = theBLayers.begin();
00065        ilay != theBLayers.end(); ++ilay) {
00066     delete (*ilay);
00067   }
00068 
00069   for (vector<MagESector *>::const_iterator ilay = theESectors.begin();
00070        ilay != theESectors.end(); ++ilay) {
00071     delete (*ilay);
00072   }
00073 }
00074 
00075 
00076 // Return field vector at the specified global point
00077 GlobalVector MagGeometry::fieldInTesla(const GlobalPoint & gp) const {
00078   MagVolume * v = 0;
00079 
00080   // Map version 85l is Z-symmetric; -> implement Z reflection
00081   if (v_85l && gp.z()>0) { 
00082     GlobalPoint gpSym(gp.x(), gp.y(), -gp.z());
00083     // Check volume cache
00084     v = findVolume(gpSym);
00085 
00086     if (v!=0) {
00087       GlobalVector bresult = v->fieldInTesla(gpSym);
00088       return GlobalVector(-bresult.x(), -bresult.y(), bresult.z());
00089     }
00090     
00091   } else { // No reflection
00092     v = findVolume(gp);
00093     if (v!=0) {
00094       return v->fieldInTesla(gp);
00095     }
00096   }
00097   
00098   // Fall-back case: no volume found
00099   
00100   if (isnan(gp.mag())) {
00101     LogWarning("InvalidInput") << "Input value invalid (not a number): " << gp << endl;
00102       
00103   } else {
00104     LogWarning("MagneticField") << "MagGeometry::fieldInTesla: failed to find volume for " << gp << endl;
00105   }
00106   return GlobalVector();
00107 }
00108 
00109 
00110 // Linear search implementation (just for testing)
00111 MagVolume* 
00112 MagGeometry::findVolume1(const GlobalPoint & gp, double tolerance) const {  
00113 
00114   MagVolume6Faces * found = 0;
00115 
00116   if (inBarrel(gp)) { // Barrel
00117     for (vector<MagVolume6Faces*>::const_iterator v = theBVolumes.begin();
00118          v!=theBVolumes.end(); ++v){
00119       if ((*v)==0) { //FIXME: remove this check
00120         cout << endl << "***ERROR: MagGeometry::findVolume: MagVolume not set" << endl;
00121         continue;
00122       }
00123       if ((*v)->inside(gp,tolerance)) {
00124         found = (*v);
00125         break;
00126       }
00127     }
00128 
00129   } else { // Endcaps
00130     for (vector<MagVolume6Faces*>::const_iterator v = theEVolumes.begin();
00131          v!=theEVolumes.end(); ++v){
00132       if ((*v)==0) {  //FIXME: remove this check
00133         cout << endl << "***ERROR: MagGeometry::findVolume: MagVolume not set" << endl;
00134         continue;
00135       }
00136       if ((*v)->inside(gp,tolerance)) {
00137         found = (*v);
00138         break;
00139       }
00140     }
00141   }  
00142   
00143   return found;
00144 }
00145 
00146 // Use hierarchical structure for fast lookup.
00147 MagVolume* 
00148 MagGeometry::findVolume(const GlobalPoint & gp, double tolerance) const{
00149   // Check volume cache
00150   if (lastVolume!=0 && lastVolume->inside(gp)){
00151     return lastVolume;
00152   }
00153 
00154   MagVolume * result=0;
00155   if (inBarrel(gp)) { // Barrel
00156     double R = gp.perp();
00157     int bin = theBarrelBinFinder->binIndex(R);
00158     
00159     for (int bin1 = bin; bin1 >= max(0,bin-2); --bin1) {
00160       if (verbose::debugOut) cout << "Trying layer at R " << theBLayers[bin1]->minR()
00161                       << " " << R << endl ;
00162       result = theBLayers[bin1]->findVolume(gp, tolerance);
00163       if (verbose::debugOut) cout << "***In blayer " << bin1-bin << " " 
00164                       << (result==0? " failed " : " OK ") <<endl;
00165       if (result != 0) break;
00166     }
00167 
00168   } else { // Endcaps
00169     Geom::Phi<float> phi = gp.phi();
00170     int bin = theEndcapBinFinder->binIndex(phi);
00171     if (verbose::debugOut) cout << "Trying endcap sector at phi "
00172                     << theESectors[bin]->minPhi() << " " << phi << endl ;
00173     result = theESectors[bin]->findVolume(gp, tolerance);
00174     if (verbose::debugOut) cout << "***In guessed esector "
00175                     << (result==0? " failed " : " OK ") <<endl;
00176   }
00177 
00178 
00179   if (result==0 && tolerance < 0.0001) {
00180     // If search fails, retry with a 300 micron tolerance.
00181     // This is a hack for thin gaps on air-iron boundaries,
00182     // which will not be present anymore once surfaces are matched.
00183     if (verbose::debugOut) cout << "Increasing the tolerance to 0.03" <<endl;
00184     result = findVolume(gp, 0.03);
00185   }
00186 
00187   if (cacheLastVolume) lastVolume = result;
00188 
00189   return result;
00190 }
00191 
00192 
00193 
00194 
00195 bool MagGeometry::inBarrel(const GlobalPoint& gp) const {
00196   float Z = fabs(gp.z());
00197   float R = gp.perp();
00198 
00199   // FIXME: Get these dimensions from the builder. 
00200   // For this we can wait the next generation of tables, when the picture 
00201   // may be more complicated
00202   if (v_85l){
00203     return (Z<634.49 || (R>308.755 && Z<661.01));
00204   } else {
00205     return (Z<350. ||
00206             (R>172.4 && Z<633.29) || 
00207             (R>308.755 && Z<661.01));
00208   }
00209 }
00210 
00211 
00212 bool MagGeometry::isZSymmetric() const {
00213   return v_85l;
00214 }
00215 

Generated on Tue Jun 9 17:40:38 2009 for CMSSW by  doxygen 1.5.4