CMS 3D CMS Logo

volumeHandle.cc
Go to the documentation of this file.
1 // #include "Utilities/Configuration/interface/Architecture.h"
2 
3 /*
4  * See header file for a description of this class.
5  *
6  * \author N. Amapane - INFN Torino
7  */
8 
15 
20 
21 #include "CLHEP/Units/GlobalSystemOfUnits.h"
22 
24 
25 #include <string>
26 #include <iterator>
27 #include <iomanip>
28 #include <iostream>
29 #include <boost/lexical_cast.hpp>
30 
31 using namespace SurfaceOrientation;
32 using namespace std;
33 
34 
36  delete refPlane;
37 }
38 
40  : name(fv.logicalPart().name().name()),
41  copyno(fv.copyno()),
42  magVolume(nullptr),
43  masterSector(1),
44  theRN(0.),
45  theRMin(0.),
46  theRMax(0.),
47  refPlane(nullptr),
48  solid(fv.logicalPart().solid()),
49  center_(GlobalPoint(fv.translation().x()/cm,
50  fv.translation().y()/cm,
51  fv.translation().z()/cm)),
52  expand(expand2Pi),
53  isIronFlag(false)
54 {
55  // ASSUMPTION: volume names ends with "_NUM" where NUM is the volume number
56  string volName = name;
57  volName.erase(0,volName.rfind('_')+1);
58  volumeno =boost::lexical_cast<unsigned short>(volName);
59 
60  for (int i=0; i<6; ++i) {
61  isAssigned[i] = false;
62  }
63 
64 
66  cout.precision(7);
67  }
68 
69 
70  referencePlane(fv);
71 
72  if (solid.shape() == ddbox) {
73  buildBox(fv);
74  } else if (solid.shape() == ddtrap) {
75  buildTrap(fv);
76  } else if (solid.shape() == ddcons) {
77  buildCons(fv);
78  } else if (solid.shape() == ddtubs) {
79  buildTubs(fv);
80  } else if (solid.shape() == ddpseudotrap) {
81  buildPseudoTrap(fv);
82  } else if (solid.shape() == ddtrunctubs) {
83  buildTruncTubs(fv);
84  } else {
85  cout << "volumeHandle ctor: Unexpected solid: " << (int) solid.shape() << endl;
86  }
87 
88 
89  // NOTE: Table name and master sector are no longer taken from xml!
90 // DDsvalues_type sv(fv.mergedSpecifics());
91 
92 // { // Extract the name of associated field file.
93 // std::vector<std::string> temp;
94 // std::string pname = "table";
95 // DDValue val(pname);
96 // DDsvalues_type sv(fv.mergedSpecifics());
97 // if (DDfetch(&sv,val)) {
98 // temp = val.strings();
99 // if (temp.size() != 1) {
100 // cout << "*** WARNING: volume has > 1 SpecPar " << pname << endl;
101 // }
102 // magFile = temp[0];
103 
104 // string find="[copyNo]";
105 // std::size_t j;
106 // for ( ; (j = magFile.find(find)) != string::npos ; ) {
107 // stringstream conv;
108 // conv << setfill('0') << setw(2) << copyno;
109 // string repl;
110 // conv >> repl;
111 // magFile.replace(j, find.length(), repl);
112 // }
113 
114 // } else {
115 // cout << "*** WARNING: volume does not have a SpecPar " << pname << endl;
116 // cout << " DDsvalues_type: " << fv.mergedSpecifics() << endl;
117 // }
118 // }
119 
120 // { // Extract the number of the master sector.
121 // std::vector<double> temp;
122 // const std::string pname = "masterSector";
123 // DDValue val(pname);
124 // if (DDfetch(&sv,val)) {
125 // temp = val.doubles();
126 // if (temp.size() != 1) {
127 // cout << "*** WARNING: volume has > 1 SpecPar " << pname << endl;
128 // }
129 // masterSector = int(temp[0]+.5);
130 // } else {
131 // if (MagGeoBuilderFromDDD::debug) {
132 // cout << "Volume does not have a SpecPar " << pname
133 // << " using: " << copyno << endl;
134 // cout << " DDsvalues_type: " << fv.mergedSpecifics() << endl;
135 // }
136 // masterSector = copyno;
137 // }
138 // }
139 
140  // Get material for this volume
141  if (fv.logicalPart().material().name().name() == "Iron") isIronFlag=true;
142 
143 
145  cout << " RMin = " << theRMin <<endl;
146  cout << " RMax = " << theRMax <<endl;
147 
148  if (theRMin < 0 || theRN < theRMin || theRMax < theRN)
149  cout << "*** WARNING: wrong RMin/RN/RMax , shape: " << (int) shape() << endl;
150 
151  cout << "Summary: " << name << " " << copyno
152  << " Shape= " << (int) shape()
153  << " trasl " << center()
154  << " R " << center().perp()
155  << " phi " << center().phi()
156  << " magFile " << magFile
157  << " Material= " << fv.logicalPart().material().name()
158  << " isIron= " << isIronFlag
159  << " masterSector= " << masterSector << std::endl;
160 
161  cout << " Orientation of surfaces:";
162  std::string sideName[3] = {"positiveSide", "negativeSide", "onSurface"};
163  for (int i=0; i<6; ++i) {
164  cout << " " << i << ":" << sideName[surfaces[i]->side(center_,0.3)];
165  }
166  cout << endl;
167  }
168 }
169 
170 
172  return center_;
173 }
174 
176  // The refPlane is the "main plane" for the solid. It corresponds to the
177  // x,y plane in the DDD local frame, and defines a frame where the local
178  // coordinates are the same as in DDD.
179  // In the geometry version 85l_030919, this plane is normal to the
180  // beam line for all volumes but pseudotraps, so that global R is along Y,
181  // global phi is along -X and global Z along Z:
182  //
183  // Global(for vol at pi/2) Local
184  // +R (+Y) +Y
185  // +phi(-X) -X
186  // +Z +Z
187  //
188  // For pseudotraps the refPlane is parallel to beam line and global R is
189  // along Z, global phi is along +-X and and global Z along Y:
190  //
191  // Global(for vol at pi/2) Local
192  // +R (+Y) +Z
193  // +phi(-X) +X
194  // +Z +Y
195  //
196  // Note that the frame is centered in the DDD volume center, which is
197  // inside the volume for DDD boxes and (pesudo)trapezoids, on the beam line
198  // for tubs, cons and trunctubs.
199 
200  // In geometry version 1103l, trapezoids have X and Z in the opposite direction
201  // than the above. Boxes are either oriented as described above or in some case
202  // have opposite direction for Y and X.
203 
204  // The global position
205  Surface::PositionType & posResult = center_;
206 
207  // The reference plane rotation
208  DD3Vector x, y, z;
209  fv.rotation().GetComponents(x,y,z);
211  if (x.Cross(y).Dot(z) < 0.5) {
212  cout << "*** WARNING: Rotation is not RH "<< endl;
213  }
214  }
215 
216  // The global rotation
218  rotResult(float(x.X()),float(x.Y()),float(x.Z()),
219  float(y.X()),float(y.Y()),float(y.Z()),
220  float(z.X()),float(z.Y()),float(z.Z()));
221 
222  refPlane = new GloballyPositioned<float>(posResult, rotResult);
223 
224  // Check correct orientation
226 
227  cout << "Refplane pos " << refPlane->position() << endl;
228 
229  // See comments above for the conventions for orientation.
230  LocalVector globalZdir(0.,0.,1.); // Local direction of the axis along global Z
231  if (solid.shape() == ddpseudotrap) {
232  globalZdir = LocalVector(0.,1.,0.);
233  }
234  if (refPlane->toGlobal(globalZdir).z()<0.) {
235  globalZdir=-globalZdir;
236  }
237 
238  float chk = refPlane->toGlobal(globalZdir).dot(GlobalVector(0,0,1));
239  if (chk < .999) cout << "*** WARNING RefPlane check failed!***"
240  << chk << endl;
241  }
242 }
243 
244 
245 
247  double deltaPhi,
248  double zhalf,
249  double rCentr) {
250  // This is 100% equal for cons and tubs!!!
251 
252  GlobalVector planeXAxis = refPlane->toGlobal(LocalVector( 1, 0, 0));
253  GlobalVector planeYAxis = refPlane->toGlobal(LocalVector( 0, 1, 0));
254  GlobalVector planeZAxis = refPlane->toGlobal(LocalVector( 0, 0, 1));
255 
256  // Local Y axis of the faces at +-phi.
257  GlobalVector y_phiplus = refPlane->toGlobal(LocalVector(cos(startPhi+deltaPhi),
258  sin(startPhi+deltaPhi),0.));
259  GlobalVector y_phiminus = refPlane->toGlobal(LocalVector(cos(startPhi),
260  sin(startPhi),0.));
261 
262  Surface::RotationType rot_Z(planeXAxis,planeYAxis);
263  Surface::RotationType rot_phiplus(planeZAxis, y_phiplus);
264  Surface::RotationType rot_phiminus(planeZAxis, y_phiminus);
265 
266  GlobalPoint pos_zplus(center_.x(),center_.y(),center_.z()+zhalf);
267  GlobalPoint pos_zminus(center_.x(),center_.y(),center_.z()-zhalf);
268  // BEWARE: in this case, the origin for phiplus,phiminus surfaces is
269  // at radius R and not on a plane passing by center_ orthogonal to the radius.
270  GlobalPoint pos_phiplus(refPlane->toGlobal(LocalPoint(rCentr*cos(startPhi+deltaPhi),rCentr*sin(startPhi+deltaPhi),0.)));
271  GlobalPoint pos_phiminus(refPlane->toGlobal(LocalPoint(rCentr*cos(startPhi),
272  rCentr*sin(startPhi),
273  0.)));
274  surfaces[zplus] = new Plane(pos_zplus, rot_Z);
275  surfaces[zminus] = new Plane(pos_zminus, rot_Z);
276  surfaces[phiplus] = new Plane(pos_phiplus, rot_phiplus);
277  surfaces[phiminus] = new Plane(pos_phiminus, rot_phiminus);
278 
280  cout << "Actual Center at: " << center_ << " R " << center_.perp()
281  << " phi " << center_.phi() << endl;
282  cout << "RN " << theRN << endl;
283 
284  cout << "pos_zplus " << pos_zplus << " "
285  << pos_zplus.perp() << " " << pos_zplus.phi() << endl
286  << "pos_zminus " << pos_zminus << " "
287  << pos_zminus.perp() << " " << pos_zminus.phi() << endl
288  << "pos_phiplus " << pos_phiplus << " "
289  << pos_phiplus.perp() << " " << pos_phiplus.phi() <<endl
290  << "pos_phiminus " << pos_phiminus << " "
291  << pos_phiminus.perp() << " " << pos_phiminus.phi() <<endl;
292 
293  cout << "y_phiplus " << y_phiplus << endl;
294  cout << "y_phiminus " << y_phiminus << endl;
295 
296  cout << "rot_Z " << surfaces[zplus]->toGlobal(LocalVector(0.,0.,1.)) << endl
297  << "rot_phi+ " << surfaces[phiplus]->toGlobal(LocalVector(0.,0.,1.))
298  << " phi " << surfaces[phiplus]->toGlobal(LocalVector(0.,0.,1.)).phi()
299  << endl
300  << "rot_phi- " << surfaces[phiminus]->toGlobal(LocalVector(0.,0.,1.))
301  << " phi " << surfaces[phiminus]->toGlobal(LocalVector(0.,0.,1.)).phi()
302  << endl;
303  }
304 
305 // // Check ordering.
307  if (pos_zplus.z() < pos_zminus.z()) {
308  cout << "*** WARNING: pos_zplus < pos_zminus " << endl;
309  }
310  if (Geom::Phi<float>(pos_phiplus.phi()-pos_phiminus.phi()) < 0. ) {
311  cout << "*** WARNING: pos_phiplus < pos_phiminus " << endl;
312  }
313  }
314 }
315 
316 
317 
319 {
320  //Check for null comparison
321  if (&s1==(surfaces[which_side]).get()){
322  if (MagGeoBuilderFromDDD::debug) cout << " sameSurface: OK (same ptr)" << endl;
323  return true;
324  }
325 
326  const float maxtilt = 0.999;
327 
328  const Surface & s2 = *(surfaces[which_side]);
329  // Try with a plane.
330  const Plane * p1 = dynamic_cast<const Plane*>(&s1);
331  if (p1!=nullptr) {
332  const Plane * p2 = dynamic_cast<const Plane*>(&s2);
333  if (p2==nullptr) {
334  if (MagGeoBuilderFromDDD::debug) cout << " sameSurface: different types" << endl;
335  return false;
336  }
337 
338  if ( (fabs(p1->normalVector().dot(p2->normalVector())) > maxtilt)
339  && (fabs((p1->toLocal(p2->position())).z()) < tolerance) ) {
340  if (MagGeoBuilderFromDDD::debug) cout << " sameSurface: OK "
341  << fabs(p1->normalVector().dot(p2->normalVector()))
342  << " " << fabs((p1->toLocal(p2->position())).z()) << endl;
343  return true;
344  } else{
345  if (MagGeoBuilderFromDDD::debug) cout << " sameSurface: not the same: "
346  << p1->normalVector() << p1->position() << endl
347  << " "
348  << p2->normalVector() << p2->position() << endl
349  << fabs(p1->normalVector().dot(p2->normalVector()))
350  << " " << (p1->toLocal(p2->position())).z()<< endl;
351  return false;
352  }
353  }
354 
355  // Try with a cylinder.
356  const Cylinder * cy1 = dynamic_cast<const Cylinder*>(&s1);
357  if (cy1!=nullptr) {
358  const Cylinder * cy2 = dynamic_cast<const Cylinder*>(&s2);
359  if (cy2==nullptr) {
360  if (MagGeoBuilderFromDDD::debug) cout << " sameSurface: different types" << endl;
361  return false;
362  }
363  // Assume axis is the same!
364  if (fabs(cy1->radius() - cy2->radius()) < tolerance) {
365  return true;
366  } else {
367  return false;
368  }
369  }
370 
371  // Try with a cone.
372  const Cone * co1 = dynamic_cast<const Cone*>(&s1);
373  if (co1!=nullptr) {
374  const Cone * co2 = dynamic_cast<const Cone*>(&s2);
375  if (co2==nullptr) {
376  if (MagGeoBuilderFromDDD::debug) cout << " sameSurface: different types" << endl;
377  return false;
378  }
379  // FIXME
380  if (fabs(co1->openingAngle()-co2->openingAngle()) < maxtilt
381  && (co1->vertex()-co2->vertex()).mag() < tolerance) {
382  return true;
383  } else {
384  return false;
385  }
386  }
387 
388  if (MagGeoBuilderFromDDD::debug) cout << " sameSurface: unknown surfaces..." << endl;
389  return false;
390 }
391 
392 
393 
395 {
396  //Check for null assignment
397  if (&s1==(surfaces[which_side]).get()){
398  isAssigned[which_side] = true;
399  return true;
400  }
401 
402  if (!sameSurface(s1,which_side)){
403  cout << "***ERROR: setSurface: trying to assign a surface that does not match destination surface. Skipping." << endl;
404  const Surface & s2 = *(surfaces[which_side]);
405  //FIXME: Just planes for the time being!!!
406  const Plane * p1 = dynamic_cast<const Plane*>(&s1);
407  const Plane * p2 = dynamic_cast<const Plane*>(&s2);
408  if (p1!=nullptr && p2 !=nullptr)
409  cout << p1->normalVector() << p1->position() << endl
410  << p2->normalVector() << p2->position() << endl;
411  return false;
412  }
413 
414 
415  if (isAssigned[which_side]) {
416  if (&s1!=(surfaces[which_side]).get()){
417  cout << "*** WARNING volumeHandle::setSurface: trying to reassign a surface to a different surface instance" << endl;
418  return false;
419  }
420  } else {
421  surfaces[which_side] = &s1;
422  isAssigned[which_side] = true;
423  if (MagGeoBuilderFromDDD::debug) cout << " Volume " << name << " # " << copyno << " Assigned: " << (int) which_side << endl;
424  return true;
425  }
426 
427  return false; // let the compiler be happy
428 }
429 
430 
431 
432 const Surface &
434  return *(surfaces[which_side]);
435 }
436 
437 
438 
439 const Surface &
441  assert(which_side >=0 && which_side <6);
442  return *(surfaces[which_side]);
443 }
444 
445 
446 std::vector<VolumeSide>
448  std::vector<VolumeSide> result;
449  for (int i=0; i<6; ++i){
450  // If this is just a master volume out of wich a 2pi volume
451  // should be built (e.g. central cylinder), skip the phi boundaries.
452  if (expand && (i==phiplus || i==phiminus)) continue;
453 
454  // FIXME: Skip null inner degenerate cylindrical surface
455  if (solid.shape() == ddtubs && i == SurfaceOrientation::inner && theRMin < 0.001) continue;
456 
457  ReferenceCountingPointer<Surface> s = const_cast<Surface*> (surfaces[i].get());
458  result.push_back(VolumeSide(s, GlobalFace(i),
459  surfaces[i]->side(center_,0.3)));
460  }
461  return result;
462 }
463 
464 void MagGeoBuilderFromDDD::volumeHandle::printUniqueNames(handles::const_iterator begin, handles::const_iterator end, bool uniq) {
465  std::vector<std::string> names;
466  for (handles::const_iterator i = begin;
467  i != end; ++i){
468  if (uniq) names.push_back((*i)->name);
469  else names.push_back((*i)->name+":"+std::to_string((*i)->copyno));
470  }
471 
472  sort(names.begin(),names.end());
473  if (uniq) {
474  std::vector<std::string>::iterator i = unique(names.begin(),names.end());
475  int nvols = int(i - names.begin());
476  cout << nvols << " ";
477  copy(names.begin(), i, ostream_iterator<std::string>(cout, " "));
478  } else {
479  cout << names.size() << " ";
480  copy(names.begin(), names.end(), ostream_iterator<std::string>(cout, " "));
481  }
482  cout << endl;
483 }
484 
485 
486 #include "MagneticField/GeomBuilder/src/buildBox.icc"
487 #include "MagneticField/GeomBuilder/src/buildTrap.icc"
488 #include "MagneticField/GeomBuilder/src/buildTubs.icc"
489 #include "MagneticField/GeomBuilder/src/buildCons.icc"
490 #include "MagneticField/GeomBuilder/src/buildPseudoTrap.icc"
491 #include "MagneticField/GeomBuilder/src/buildTruncTubs.icc"
unsigned short copyno
copy number
Definition: volumeHandle.h:62
void buildBox(const DDExpandedView &fv)
const DDRotationMatrix & rotation() const
The absolute rotation of the current node.
Definition: Cone.h:17
void buildPhiZSurf(double startPhi, double deltaPhi, double zhalf, double rCentr)
const N & name() const
Definition: DDBase.h:78
T perp() const
Definition: PV3DBase.h:72
static const HistoName names[]
def copy(args, dbName)
GloballyPositioned< float > * refPlane
Definition: volumeHandle.h:155
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
void buildTubs(const DDExpandedView &fv)
GlobalVector normalVector() const
Definition: Plane.h:41
std::vector< VolumeSide > sides() const
The surfaces and they orientation, as required to build a MagVolume.
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
T y() const
Definition: PV3DBase.h:63
void buildPseudoTrap(const DDExpandedView &fv)
const GlobalPoint & center() const
Return the center of the volume.
PreciseFloatType< T, U >::Type dot(const Vector3DBase< U, FrameTag > &v) const
Definition: Vector3DBase.h:107
#define nullptr
std::string name
Name of the volume.
Definition: volumeHandle.h:56
DDSolidShape shape() const
Shape of the solid.
Definition: volumeHandle.h:97
Definition: Plane.h:17
GlobalPoint vertex() const
Global position of the cone vertex.
Definition: Cone.h:55
Scalar radius() const
Radius of the cylinder.
Definition: Cylinder.h:67
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > DD3Vector
A DD Translation is currently implemented with Root Vector3D.
Definition: DDTranslation.h:6
LocalPoint toLocal(const GlobalPoint &gp) const
def unique(seq, keepstr=True)
Definition: tier0.py:24
T z() const
Definition: PV3DBase.h:64
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
std::string magFile
Name of magnetic field table file.
Definition: volumeHandle.h:58
DDSolidShape shape(void) const
The type of the solid.
Definition: DDSolid.cc:144
void buildCons(const DDExpandedView &fv)
#define end
Definition: vmac.h:39
void referencePlane(const DDExpandedView &fv)
double p2[4]
Definition: TauolaWrapper.h:90
volumeHandle(const DDExpandedView &fv, bool expand2Pi=false)
Definition: volumeHandle.cc:39
Surface::LocalVector LocalVector
Definition: volumeHandle.h:29
unsigned short volumeno
volume number
Definition: volumeHandle.h:60
GlobalPoint toGlobal(const LocalPoint &lp) const
static void printUniqueNames(handles::const_iterator begin, handles::const_iterator end, bool uniq=true)
Just for debugging...
const Surface & surface(int which_side) const
Get the current surface on specified side.
#define begin
Definition: vmac.h:32
double p1[4]
Definition: TauolaWrapper.h:89
void buildTrap(const DDExpandedView &fv)
int masterSector
The sector for which an interpolator for this class of volumes should be built.
Definition: volumeHandle.h:111
const DDLogicalPart & logicalPart() const
The logical-part of the current node in the expanded-view.
T x() const
Definition: PV3DBase.h:62
const PositionType & position() const
Provides an exploded view of the detector (tree-view)
bool setSurface(const Surface &s1, Sides which_side)
Assign a shared surface perorming sanity checks.
bool sameSurface(const Surface &s1, Sides which_side, float tolerance=0.01)
Find out if two surfaces are the same physical surface.
const std::string & name() const
Returns the name.
Definition: DDName.cc:90
const DDMaterial & material(void) const
Returns a reference object of the material this LogicalPart is made of.
Global3DVector GlobalVector
Definition: GlobalVector.h:10
Geom::Theta< float > openingAngle() const
Angle of the cone.
Definition: Cone.h:58
void buildTruncTubs(const DDExpandedView &fv)