CMS 3D CMS Logo

DDPixFwdBlades.cc
Go to the documentation of this file.
1 /*
2  == CMS Forward Pixels Geometry ==
3  Algorithm for placing one-per-blade components.
4 */
5 
18 #include <CLHEP/Vector/ThreeVector.h>
19 #include <CLHEP/Vector/Rotation.h>
20 #include <CLHEP/Vector/RotationInterfaces.h>
21 #include <CLHEP/Units/GlobalPhysicalConstants.h>
22 #include <CLHEP/Units/SystemOfUnits.h>
23 
24 #include <cmath>
25 #include <algorithm>
26 #include <map>
27 #include <string>
28 #include <vector>
29 
30 /*
31 
32 == CMS Forward Pixels Geometry ==
33 
34  @version 3.02.01 May 30, 2006
35  @created Dmitry Onoprienko
36 
37 == ALGORITHM DESCRIPTION: ==
38 
39  Algorithm for placing one-per-blade components
40  Also computes parameters necessary for defining the "nipple" geometry.
41 
42 == Parameters : ==
43 
44  "Endcap" - +1 if placing the child volume into +Z disk, -1 if placing into -Z disk.
45  "Child" - name of a child volume being places (should be in the form "file:volume")
46  In no child name is given, the algorithm simply calculates Nipple parameters.
47  "ChildRotation" - rotation of the child volume with respect to the "blade frame". [OPTIONAL]
48  "ChildTranslation" - vector defining translation of the child volume with respect to the
49  "blade frame". [OPTIONAL]
50  "FlagString" - string of 24 characters, used to indicate blades into which the child volume
51  should be placed. [OPTIONAL]
52  "FlagSelector" - 1 character string, key to interpreting "FlagString".
53  Positions in "BladeFlag" that have this character will get the child volume.
54 
55  If "Child" parameter is omitted, the algorithm computes rotation needed for describing
56  coolant "nipples" but does not do any placements.
57 
58  If "Child" is "PixelForwardNippleZPlus" or "PixelForwardNippleZMinus" and no rotation or translation
59  is supplied, correct rotations and translations are automatically computed.
60 
61  Blade frame: origin on the axis of the blade at a distance "ancorRadius" from the beam line
62  (it therefore coincides with the ancor point of a blade).
63  Y along blade axis pointing away from beam line, Z perpendicular to blade plane and pointing away from IP.
64  (That assumes the axes of ZPlus disk are aligned with CMS global reference frame, and ZMinus disk
65  is rotated around Y by 180 degrees.)
66 
67 == Example of use : ==
68 
69 <Algorithm name="track:DDPixFwdBlades">
70  <rParent name="pixfwdDisk:PixelForwardDiskZMinus"/>
71  <Numeric name="Endcap" value="-1." />
72  <String name="Child" value="pixfwdPanel:PixelForwardPanel4Left"/>
73  <Vector name="ChildTranslation" type="numeric" nEntries="3"> 0., -[pixfwdPanel:AncorY], [zPanel] </Vector>
74  <String name="ChildRotation" value="pixfwdCommon:Y180"/>
75  <String name="FlagString" value="LRRRRLRRRRRRLRRRRLRRRRRR" /> <!-- Panel Layout ZMinus 4 -->
76  <String name="FlagSelector" value="L" />
77 </Algorithm>
78 
79 */
80 
81 using namespace std;
82 
83 class DDPixFwdBlades : public DDAlgorithm {
84 public:
86  ~DDPixFwdBlades() override;
87 
88  void initialize(const DDNumericArguments& nArgs,
89  const DDVectorArguments& vArgs,
90  const DDMapArguments& mArgs,
91  const DDStringArguments& sArgs,
92  const DDStringVectorArguments& vsArgs) override;
93 
94  void execute(DDCompactView& cpv) override;
95 
96 private:
97  int nBlades; // Number of blades
98  double bladeAngle; // Angle of blade rotation around axis perpendicular to beam
99  double zPlane; // Common shift in Z for all blades (with respect to disk center plane)
100  double bladeZShift; // Shift in Z between the axes of two adjacent blades
101 
102  double ancorRadius; // Distance from beam line to ancor point defining center of "blade frame"
103 
104  // Coordinates of Nipple ancor points J and K in "blade frame" :
105 
106  double jX;
107  double jY;
108  double jZ;
109  double kX;
110  double kY;
111  double kZ;
112 
113  double endcap; // +1 for Z Plus endcap disks, -1 for Z Minus endcap disks
114 
115  string flagString; // String of flags
116  string flagSelector; // Character that means "yes" in flagString
117 
118  string childName; // Child volume name
119 
120  vector<double> childTranslationVector; // Child translation with respect to "blade frame"
121  string childRotationName; // Child rotation with respect to "blade frame"
122  string idNameSpace; //Namespace of this and ALL sub-parts
123 
124  map<string, int> copyNumbers;
125 
126  CLHEP::HepRotation* nippleRotationZPlus;
127  CLHEP::HepRotation* nippleRotationZMinus;
128  double nippleTranslationX, nippleTranslationY, nippleTranslationZ;
129 
130  int issueCopyNumber();
131  void computeNippleParameters(double endcap);
132 };
133 
136 
138  const DDVectorArguments& vArgs,
139  const DDMapArguments&,
140  const DDStringArguments& sArgs,
141  const DDStringVectorArguments&) {
142  if (nArgs.find("Endcap") != nArgs.end()) {
143  endcap = nArgs["Endcap"];
144  } else {
145  endcap = 1.;
146  }
147 
148  if (sArgs.find("FlagString") != sArgs.end()) {
149  flagString = sArgs["FlagString"];
150  flagSelector = sArgs["FlagSelector"];
151  } else {
152  flagString = "YYYYYYYYYYYYYYYYYYYYYYYY";
153  flagSelector = "Y";
154  }
155 
156  if (sArgs.find("Child") != sArgs.end()) {
157  childName = sArgs["Child"];
158  } else {
159  childName = "";
160  }
161 
162  if (vArgs.find("ChildTranslation") != vArgs.end()) {
163  childTranslationVector = vArgs["ChildTranslation"];
164  } else {
165  childTranslationVector = vector<double>(3, 0.);
166  }
167 
168  if (sArgs.find("ChildRotation") != sArgs.end()) {
169  childRotationName = sArgs["ChildRotation"];
170  } else {
171  childRotationName = "";
172  }
173 
174  idNameSpace = DDCurrentNamespace::ns();
175 
176  // -- Input geometry parameters : -----------------------------------------------------
177 
178  nBlades = 24; // Number of blades
179  bladeAngle = 20. * CLHEP::deg; // Angle of blade rotation around its axis
180  zPlane = 0.; // Common shift in Z for all blades (with respect to disk center plane)
181  bladeZShift = 6. * CLHEP::mm; // Shift in Z between the axes of two adjacent blades
182 
183  ancorRadius = 54.631 * CLHEP::mm; // Distance from beam line to ancor point defining center of "blade frame"
184 
185  // Coordinates of Nipple ancor points J and K in "blade frame" :
186 
187  jX = -16.25 * CLHEP::mm;
188  jY = 96.50 * CLHEP::mm;
189  jZ = 1.25 * CLHEP::mm;
190  kX = 16.25 * CLHEP::mm;
191  kY = 96.50 * CLHEP::mm;
192  kZ = -1.25 * CLHEP::mm;
193 
194  // -- Static initialization : -----------------------------------------------------------
195 
196  nippleRotationZPlus = nullptr;
197  nippleRotationZMinus = nullptr;
198  nippleTranslationX = 0.;
199  nippleTranslationY = 0.;
200  nippleTranslationZ = 0.;
201 
202  copyNumbers.clear();
203 
204  edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades: Initialize with endcap " << endcap << " FlagString " << flagString
205  << " FlagSelector " << flagSelector << " Child " << childName << " ChildTranslation "
206  << childTranslationVector[0] << ":" << childTranslationVector[1] << ":"
207  << childTranslationVector[2] << " ChildRotation " << childRotationName << " NameSpace "
208  << idNameSpace << "\n nBlades " << nBlades << " bladeAngle " << bladeAngle
209  << " zPlane " << zPlane << " bladeZShift " << bladeZShift << " ancorRadius "
210  << ancorRadius << " jX|jY|jZ " << jX << ":" << jY << ":" << jZ << " kX|kY|kZ " << kX
211  << ":" << kY << ":" << kZ;
212 }
213 
215  // -- Compute Nipple parameters if not already computed :
216 
217  if (!nippleRotationZPlus) {
218  computeNippleParameters(1.); // Z Plus endcap
219  computeNippleParameters(-1.); // Z Minus endcap
220  }
221  if (childName.empty())
222  return;
223 
224  // -- Signed versions of blade angle and z-shift :
225 
226  double effBladeAngle = -endcap * bladeAngle;
227  double effBladeZShift = endcap * bladeZShift;
228 
229  // -- Names of mother and child volumes :
230 
231  DDName mother = parent().name();
232  DDName child(DDSplit(childName).first, DDSplit(childName).second);
233 
234  // -- Get translation and rotation from "blade frame" to "child frame", if any :
235 
236  CLHEP::HepRotation childRotMatrix = CLHEP::HepRotation();
237  if (!childRotationName.empty()) {
238  DDRotation childRotation = DDRotation(DDName(DDSplit(childRotationName).first, DDSplit(childRotationName).second));
239  // due to conversion to ROOT::Math::Rotation3D -- Michael Case
240  DD3Vector x, y, z;
241  childRotation.rotation().GetComponents(x, y, z); // these are the orthonormal columns.
242  CLHEP::HepRep3x3 tr(x.X(), y.X(), z.X(), x.Y(), y.Y(), z.Y(), x.Z(), y.Z(), z.Z());
243  childRotMatrix = CLHEP::HepRotation(tr);
244  } else if (childName == "pixfwdNipple:PixelForwardNippleZPlus") {
245  childRotMatrix = *nippleRotationZPlus;
246  } else if (childName == "pixfwdNipple:PixelForwardNippleZMinus") {
247  childRotMatrix = *nippleRotationZMinus;
248  }
249 
250  CLHEP::Hep3Vector childTranslation;
251  if (childName == "pixfwdNipple:PixelForwardNippleZPlus") {
252  childTranslation = CLHEP::Hep3Vector(nippleTranslationX, nippleTranslationY, nippleTranslationZ);
253  } else if (childName == "pixfwdNipple:PixelForwardNippleZMinus") {
254  childTranslation = CLHEP::Hep3Vector(-nippleTranslationX, nippleTranslationY, nippleTranslationZ);
255  } else {
256  childTranslation =
257  CLHEP::Hep3Vector(childTranslationVector[0], childTranslationVector[1], childTranslationVector[2]);
258  }
259 
260  // Create a matrix for rotation around blade axis (to "blade frame") :
261 
262  CLHEP::HepRotation bladeRotMatrix(CLHEP::Hep3Vector(0., 1., 0.), effBladeAngle);
263 
264  // Cycle over Phi positions, placing copies of the child volume :
265 
266  double deltaPhi = (360. / nBlades) * CLHEP::deg;
267  int nQuarter = nBlades / 4;
268  double zShiftMax = effBladeZShift * ((nQuarter - 1) / 2.);
269 
270  for (int iBlade = 0; iBlade < nBlades; iBlade++) {
271  // check if this blade position should be skipped :
272 
273  if (flagString[iBlade] != flagSelector[0])
274  continue;
275  int copy = issueCopyNumber();
276 
277  // calculate Phi and Z shift for this blade :
278 
279  double phi = (iBlade + 0.5) * deltaPhi - 90. * CLHEP::deg;
280  int iQuarter = iBlade % nQuarter;
281  double zShift = -zShiftMax + iQuarter * effBladeZShift;
282 
283  // compute rotation matrix from mother to blade frame :
284 
285  CLHEP::HepRotation rotMatrix(CLHEP::Hep3Vector(0., 0., 1.), phi);
286  rotMatrix *= bladeRotMatrix;
287 
288  // convert translation vector from blade frame to mother frame, and add Z shift :
289 
290  CLHEP::Hep3Vector translation = rotMatrix(childTranslation + CLHEP::Hep3Vector(0., ancorRadius, 0.));
291  translation += CLHEP::Hep3Vector(0., 0., zShift + zPlane);
292 
293  // create DDRotation for placing the child if not already existent :
294 
296  string rotstr = mother.name() + DDSplit(childName).first + to_string(copy);
297  rotation = DDRotation(DDName(rotstr, idNameSpace));
298  edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades: Rotation " << rotstr << " : " << rotation;
299 
300  if (!rotation) {
301  rotMatrix *= childRotMatrix;
302  rotation = DDrot(DDName(rotstr, idNameSpace),
303  make_unique<DDRotationMatrix>(rotMatrix.xx(),
304  rotMatrix.xy(),
305  rotMatrix.xz(),
306  rotMatrix.yx(),
307  rotMatrix.yy(),
308  rotMatrix.yz(),
309  rotMatrix.zx(),
310  rotMatrix.zy(),
311  rotMatrix.zz()));
312  }
313  // position the child :
314 
315  DDTranslation ddtran(translation.x(), translation.y(), translation.z());
316  cpv.position(child, mother, copy, ddtran, rotation);
317  edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades::Position " << child << " copy " << copy << " in " << mother
318  << " with translation " << ddtran << " and rotation " << rotation;
319  }
320 
321  // End of cycle over Phi positions
322 }
323 
325  if (copyNumbers.count(childName) == 0)
326  copyNumbers[childName] = 0;
327  return ++copyNumbers[childName];
328 }
329 
330 // -- Calculating Nipple parameters : ---------------------------------------------------
331 
333  double effBladeAngle = endcap * bladeAngle;
334 
335  CLHEP::Hep3Vector jC; // Point J in the "cover" blade frame
336  CLHEP::Hep3Vector kB; // Point K in the "body" blade frame
337  string rotNameNippleToCover;
338  string rotNameCoverToNipple;
339  string rotNameNippleToBody;
340 
341  if (endcap > 0.) {
342  jC = CLHEP::Hep3Vector(jX, jY + ancorRadius, jZ);
343  kB = CLHEP::Hep3Vector(kX, kY + ancorRadius, kZ);
344  rotNameNippleToCover = "NippleToCoverZPlus";
345  rotNameCoverToNipple = "CoverToNippleZPlus";
346  rotNameNippleToBody = "NippleToBodyZPlus";
347  } else {
348  jC = CLHEP::Hep3Vector(-jX, jY + ancorRadius, jZ);
349  kB = CLHEP::Hep3Vector(-kX, kY + ancorRadius, kZ);
350  rotNameNippleToCover = "NippleToCoverZMinus";
351  rotNameCoverToNipple = "CoverToNippleZMinus";
352  rotNameNippleToBody = "NippleToBodyZMinus";
353  }
354 
355  // Z-shift from "cover" to "body" blade frame:
356 
357  CLHEP::Hep3Vector tCB(bladeZShift * sin(effBladeAngle), 0., bladeZShift * cos(effBladeAngle));
358 
359  // Rotation from "cover" blade frame into "body" blade frame :
360 
361  double deltaPhi = endcap * (360. / nBlades) * CLHEP::deg;
362  CLHEP::HepRotation rCB(CLHEP::Hep3Vector(1. * sin(effBladeAngle), 0., 1. * cos(effBladeAngle)), deltaPhi);
363 
364  // Transform vector k into "cover" blade frame :
365 
366  CLHEP::Hep3Vector kC = rCB * (kB + tCB);
367 
368  // Vector JK in the "cover" blade frame:
369 
370  CLHEP::Hep3Vector jkC = kC - jC;
371  double jkLength = jkC.mag();
372  DDConstant JK(DDName("JK", "pixfwdNipple"), make_unique<double>(jkLength));
373  edm::LogVerbatim("PixelGeom") << "+++++++++++++++ DDPixFwdBlades: "
374  << "JK Length " << jkLength * CLHEP::mm;
375 
376  // Position of the center of a nipple in "cover" blade frame :
377 
378  CLHEP::Hep3Vector nippleTranslation((kC + jC) / 2. - CLHEP::Hep3Vector(0., ancorRadius, 0.));
379  if (endcap > 0) {
380  nippleTranslationX = nippleTranslation.x();
381  nippleTranslationY = nippleTranslation.y();
382  nippleTranslationZ = nippleTranslation.z();
383  }
384  edm::LogVerbatim("PixelGeom") << "Child translation : " << nippleTranslation;
385 
386  // Rotations from nipple frame to "cover" blade frame and back :
387 
388  CLHEP::Hep3Vector vZ(0., 0., 1.);
389  CLHEP::Hep3Vector axis = vZ.cross(jkC);
390  double angleCover = vZ.angle(jkC);
391  edm::LogVerbatim("PixelGeom") << " Angle to Cover: " << angleCover;
392  CLHEP::HepRotation* rpCN = new CLHEP::HepRotation(axis, angleCover);
393  if (endcap > 0.) {
394  nippleRotationZPlus = rpCN;
395  } else {
396  nippleRotationZMinus = rpCN;
397  }
398  //( endcap > 0. ? nippleRotationZPlus : nippleRotationZMinus ) = rpCN;
399 
400  DDrot(
401  DDName(rotNameCoverToNipple, "pixfwdNipple"),
402  make_unique<DDRotationMatrix>(
403  rpCN->xx(), rpCN->xy(), rpCN->xz(), rpCN->yx(), rpCN->yy(), rpCN->yz(), rpCN->zx(), rpCN->zy(), rpCN->zz()));
404  CLHEP::HepRotation rpNC(axis, -angleCover);
405  edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades::Defines " << DDName(rotNameCoverToNipple, "pixfwdNipple")
406  << " with " << rpCN;
407  DDrot(DDName(rotNameNippleToCover, "pixfwdNipple"),
408  make_unique<DDRotationMatrix>(
409  rpNC.xx(), rpNC.xy(), rpNC.xz(), rpNC.yx(), rpNC.yy(), rpNC.yz(), rpNC.zx(), rpNC.zy(), rpNC.zz()));
410  edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades::Defines " << DDName(rotNameNippleToCover, "pixfwdNipple")
411  << " with " << rpNC;
412 
413  // Rotation from nipple frame to "body" blade frame :
414 
415  CLHEP::HepRotation rpNB(rpNC * rCB);
416 
417  DDrot(DDName(rotNameNippleToBody, "pixfwdNipple"),
418  make_unique<DDRotationMatrix>(
419  rpNB.xx(), rpNB.xy(), rpNB.xz(), rpNB.yx(), rpNB.yy(), rpNB.yz(), rpNB.zx(), rpNB.zy(), rpNB.zz()));
420  edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades::Defines " << DDName(rotNameNippleToBody, "pixfwdNipple") << " with "
421  << rpNB;
422  double angleBody = vZ.angle(rpNB * vZ);
423  edm::LogVerbatim("PixelGeom") << " Angle to body : " << angleBody;
424 }
425 
426 DEFINE_EDM_PLUGIN(DDAlgorithmFactory, DDPixFwdBlades, "track:DDPixFwdBlades");
Log< level::Info, true > LogVerbatim
static AlgebraicMatrix initialize()
double nippleTranslationZ
void position(const DDLogicalPart &self, const DDLogicalPart &parent, const std::string &copyno, const DDTranslation &trans, const DDRotation &rot, const DDDivision *div=nullptr)
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
void computeNippleParameters(double endcap)
DDName is used to identify DDD entities uniquely.
Definition: DDName.h:17
void execute(DDCompactView &cpv) override
static std::string & ns()
Compact representation of the geometrical detector hierarchy.
Definition: DDCompactView.h:81
static std::string to_string(const XMLCh *ch)
map< string, int > copyNumbers
Represents a uniquely identifyable rotation matrix.
Definition: DDTransform.h:57
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > DD3Vector
U second(std::pair< T, U > const &p)
const std::string & name() const
Returns the name.
Definition: DDName.cc:41
string childRotationName
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
CLHEP::HepRotation * nippleRotationZMinus
DDRotation DDrot(const DDName &name, std::unique_ptr< DDRotationMatrix > rot)
Definition of a uniquely identifiable rotation matrix named by DDName name.
Definition: DDRotation.cc:67
CLHEP::HepRotation * nippleRotationZPlus
const DDRotationMatrix & rotation() const
Returns the read-only rotation-matrix.
Definition: DDTransform.h:81
float x
#define DEFINE_EDM_PLUGIN(factory, type, name)
vector< double > childTranslationVector
~DDPixFwdBlades() override
a named constant corresponding to the DDL-XML tag <Constant> and <ConstantsVector> ...
Definition: DDConstant.h:18
std::pair< std::string, std::string > DDSplit(const std::string &n)
split into (name,namespace), separator = &#39;:&#39;
Definition: DDSplit.cc:3
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > DDTranslation
Definition: DDTranslation.h:7
void initialize(const DDNumericArguments &nArgs, const DDVectorArguments &vArgs, const DDMapArguments &mArgs, const DDStringArguments &sArgs, const DDStringVectorArguments &vsArgs) override