CMS 3D CMS Logo

MagGeometry.cc
Go to the documentation of this file.
1 /*
2  * See header file for a description of this class.
3  *
4  * \author N. Amapane - INFN Torino
5  */
6 
12 
14 
17 
18 #include <iostream>
19 
20 using namespace std;
21 using namespace edm;
22 
23 namespace {
24  // A thread-local cache is accepted because MagneticField is used by several other ESProducts
25  // via member variable, MagneticField and the other ESProducts are widely used, and migrating
26  // all the uses of all those was deemed to have very high cost.
27  std::atomic<int> instanceCounter(0);
28  thread_local int localInstance = 0;
29  thread_local MagVolume const* lastVolume = nullptr;
30 } // namespace
31 
32 MagGeometry::MagGeometry(int geomVersion,
33  const std::vector<MagBLayer*>& tbl,
34  const std::vector<MagESector*>& tes,
35  const std::vector<MagVolume6Faces*>& tbv,
36  const std::vector<MagVolume6Faces*>& tev)
37  : MagGeometry(geomVersion,
38  reinterpret_cast<std::vector<MagBLayer const*> const&>(tbl),
39  reinterpret_cast<std::vector<MagESector const*> const&>(tes),
40  reinterpret_cast<std::vector<MagVolume6Faces const*> const&>(tbv),
41  reinterpret_cast<std::vector<MagVolume6Faces const*> const&>(tev)) {}
42 
43 MagGeometry::MagGeometry(int geomVersion,
44  const std::vector<MagBLayer const*>& tbl,
45  const std::vector<MagESector const*>& tes,
46  const std::vector<MagVolume6Faces const*>& tbv,
47  const std::vector<MagVolume6Faces const*>& tev)
48  : me_(++instanceCounter),
49  theBLayers(tbl),
50  theESectors(tes),
51  theBVolumes(tbv),
52  theEVolumes(tev),
53  cacheLastVolume(true),
54  geometryVersion(geomVersion) {
55  vector<double> rBorders;
56 
57  for (vector<MagBLayer const*>::const_iterator ilay = theBLayers.begin(); ilay != theBLayers.end(); ++ilay) {
58  LogTrace("MagGeoBuilder") << " Barrel layer at " << (*ilay)->minR() << endl;
59  //FIXME assume layers are already sorted in minR
60  rBorders.push_back((*ilay)->minR() * (*ilay)->minR());
61  }
62 
64 
65 #ifdef EDM_ML_DEBUG
66  for (vector<MagESector const*>::const_iterator isec = theESectors.begin(); isec != theESectors.end(); ++isec) {
67  LogTrace("MagGeoBuilder") << " Endcap sector at " << (*isec)->minPhi() << endl;
68  }
69 #endif
70 
71  //FIXME assume sectors are already sorted in phi
72  //FIXME: PeriodicBinFinderInPhi gets *center* of first bin
73  int nEBins = theESectors.size();
74  if (nEBins > 0)
75  theEndcapBinFinder = new PeriodicBinFinderInPhi<float>(theESectors.front()->minPhi() + Geom::pi() / nEBins, nEBins);
76 
77  // Compute barrel dimensions based on geometry version
78  // FIXME: it would be nice to derive these from the actual geometry in the builder, possibly adding some specification to the geometry.
79  switch (geomVersion >= 120812 ? 0 : (geomVersion >= 90812 ? 1 : 2)) {
80  case 0: // since 120812
81  theBarrelRsq1 = 172.400 * 172.400;
82  theBarrelRsq2 = 308.735 * 308.735;
83  theBarrelZ0 = 350.000;
84  theBarrelZ1 = 633.290;
85  theBarrelZ2 = 662.010;
86  break;
87  case 1: // version 90812 (no longer in use)
88  theBarrelRsq1 = 172.400 * 172.400;
89  theBarrelRsq2 = 308.755 * 308.755;
90  theBarrelZ0 = 350.000;
91  theBarrelZ1 = 633.890;
92  theBarrelZ2 = 662.010;
93  break;
94  case 2: // versions 71212, 90322
95  theBarrelRsq1 = 172.400 * 172.400;
96  theBarrelRsq2 = 308.755 * 308.755;
97  theBarrelZ0 = 350.000;
98  theBarrelZ1 = 633.290;
99  theBarrelZ2 = 661.010;
100  break;
101  }
102 
103  LogTrace("MagGeometry_cache") << "*** In MagGeometry ctor: me_=" << me_ << " instanceCounter=" << instanceCounter
104  << endl;
105 }
106 
108  if (theBarrelBinFinder != nullptr)
109  delete theBarrelBinFinder;
110  if (theEndcapBinFinder != nullptr)
111  delete theEndcapBinFinder;
112 
113  for (vector<MagBLayer const*>::const_iterator ilay = theBLayers.begin(); ilay != theBLayers.end(); ++ilay) {
114  delete (*ilay);
115  }
116 
117  for (vector<MagESector const*>::const_iterator ilay = theESectors.begin(); ilay != theESectors.end(); ++ilay) {
118  delete (*ilay);
119  }
120 }
121 
122 // Return field vector at the specified global point
124  MagVolume const* v = nullptr;
125 
126  v = findVolume(gp);
127  if (v != nullptr) {
128  return v->fieldInTesla(gp);
129  }
130 
131  // Fall-back case: no volume found
132 
133  if (edm::isNotFinite(gp.mag())) {
134  LogWarning("MagneticField") << "Input value invalid (not a number): " << gp << endl;
135 
136  } else {
137  LogWarning("MagneticField") << "MagGeometry::fieldInTesla: failed to find volume for " << gp << endl;
138  }
139  return GlobalVector();
140 }
141 
142 // Linear search implementation (just for testing)
144  MagVolume6Faces const* found = nullptr;
145 
146  int errCnt = 0;
147  if (inBarrel(gp)) { // Barrel
148  for (vector<MagVolume6Faces const*>::const_iterator v = theBVolumes.begin(); v != theBVolumes.end(); ++v) {
149  if ((*v) == nullptr) { //FIXME: remove this check
150  LogError("MagGeometry") << endl << "***ERROR: MagGeometry::findVolume: MagVolume for barrel not set" << endl;
151  ++errCnt;
152  if (errCnt < 3)
153  continue;
154  else
155  break;
156  }
157  if ((*v)->inside(gp, tolerance)) {
158  found = (*v);
159  break;
160  }
161  }
162 
163  } else { // Endcaps
164  for (vector<MagVolume6Faces const*>::const_iterator v = theEVolumes.begin(); v != theEVolumes.end(); ++v) {
165  if ((*v) == nullptr) { //FIXME: remove this check
166  LogError("MagGeometry") << endl << "***ERROR: MagGeometry::findVolume: MagVolume for endcap not set" << endl;
167  ++errCnt;
168  if (errCnt < 3)
169  continue;
170  else
171  break;
172  }
173  if ((*v)->inside(gp, tolerance)) {
174  found = (*v);
175  break;
176  }
177  }
178  }
179 
180  return found;
181 }
182 
183 // Use hierarchical structure for fast lookup.
185  // Clear volume cache if this is a new instance
186  if (me_ != localInstance) {
187  LogTrace("MagGeometry_cache") << "*** In MagGeometry::findVolume resetting cache: me=" << me_
188  << " localInstance=" << localInstance << endl;
189  localInstance = me_;
190  lastVolume = nullptr;
191  }
192 
193  if (lastVolume != nullptr && lastVolume->inside(gp)) {
194  return lastVolume;
195  }
196 
197  MagVolume const* result = nullptr;
198  if (inBarrel(gp)) { // Barrel
199  double aRsq = gp.perp2();
200  int bin = theBarrelBinFinder->binIndex(aRsq);
201 
202  // Search up to 3 layers inwards. This may happen for very thin layers.
203  for (int bin1 = bin; bin1 >= max(0, bin - 3); --bin1) {
204  LogTrace("MagGeometry") << "Trying layer at R " << theBLayers[bin1]->minR() << " " << sqrt(aRsq) << endl;
205  result = theBLayers[bin1]->findVolume(gp, tolerance);
206  LogTrace("MagGeometry") << "***In blayer " << bin1 - bin << " " << (result == nullptr ? " failed " : " OK ")
207  << endl;
208  if (result != nullptr)
209  break;
210  }
211 
212  } else { // Endcaps
213  Geom::Phi<float> phi = gp.phi();
214  if (theEndcapBinFinder != nullptr && !theESectors.empty()) {
216  LogTrace("MagGeometry") << "Trying endcap sector at phi " << theESectors[bin]->minPhi() << " " << phi << endl;
217  result = theESectors[bin]->findVolume(gp, tolerance);
218  LogTrace("MagGeometry") << "***In guessed esector " << (result == nullptr ? " failed " : " OK ") << endl;
219  } else
220  edm::LogError("MagGeometry") << "Endcap empty";
221  }
222 
223  if (result == nullptr && tolerance < 0.0001) {
224  // If search fails, retry with a 300 micron tolerance.
225  // This is a hack for thin gaps on air-iron boundaries,
226  // which will not be present anymore once surfaces are matched.
227  LogTrace("MagGeometry") << "Increasing the tolerance to 0.03" << endl;
228  result = findVolume(gp, 0.03);
229  }
230 
231  if (cacheLastVolume)
232  lastVolume = result;
233 
234  return result;
235 }
236 
238  double aZ = fabs(gp.z());
239  double aRsq = gp.perp2();
240 
241  return ((aZ < theBarrelZ0) || (aZ < theBarrelZ1 && aRsq > theBarrelRsq1) ||
242  (aZ < theBarrelZ2 && aRsq > theBarrelRsq2));
243 }
Surface::GlobalVector GlobalVector
Definition: MagGeometry.h:25
GlobalVector fieldInTesla(const GlobalPoint &gp) const
Return field vector at the specified global point.
Definition: MagGeometry.cc:123
double theBarrelRsq1
Definition: MagGeometry.h:77
bool inBarrel(const GlobalPoint &gp) const
Definition: MagGeometry.cc:237
int binIndex(T phi) const override
returns an index in the valid range for the bin that contains phi
constexpr bool isNotFinite(T x)
Definition: isFinite.h:9
const double tolerance
~MagGeometry()
Destructor.
Definition: MagGeometry.cc:107
double theBarrelZ2
Definition: MagGeometry.h:81
Log< level::Error, false > LogError
#define LogTrace(id)
double theBarrelZ0
Definition: MagGeometry.h:79
MagGeometry(int geomVersion, const std::vector< MagBLayer *> &, const std::vector< MagESector *> &, const std::vector< MagVolume6Faces *> &, const std::vector< MagVolume6Faces *> &)
Constructor.
Definition: MagGeometry.cc:32
std::vector< MagESector const * > theESectors
Definition: MagGeometry.h:64
T sqrt(T t)
Definition: SSEVec.h:19
PeriodicBinFinderInPhi< float > const * theEndcapBinFinder
Definition: MagGeometry.h:71
double theBarrelRsq2
Definition: MagGeometry.h:78
std::vector< MagBLayer const * > theBLayers
Definition: MagGeometry.h:63
MagVolume const * findVolume1(const GlobalPoint &gp, double tolerance=0.) const
Definition: MagGeometry.cc:143
MagVolume const * findVolume(const GlobalPoint &gp, double tolerance=0.) const
Find a volume.
Definition: MagGeometry.cc:184
std::vector< MagVolume6Faces const * > theBVolumes
Definition: MagGeometry.h:67
const int me_
Definition: MagGeometry.h:61
HLT enums.
std::vector< MagVolume6Faces const * > theEVolumes
Definition: MagGeometry.h:68
double theBarrelZ1
Definition: MagGeometry.h:80
Log< level::Warning, false > LogWarning
constexpr double pi()
Definition: Pi.h:31
int binIndex(T R) const override
Definition: MagBinFinders.h:62
MagBinFinders::GeneralBinFinderInR< double > const * theBarrelBinFinder
Definition: MagGeometry.h:70
bool cacheLastVolume
Definition: MagGeometry.h:73