Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-04-26 22:29:31

0001 /* 
0002    == CMS Forward Pixels Geometry ==
0003    Algorithm for placing one-per-blade components.
0004 */
0005 
0006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0007 #include "DetectorDescription/Core/interface/DDRotationMatrix.h"
0008 #include "DetectorDescription/Core/interface/DDLogicalPart.h"
0009 #include "DetectorDescription/Core/interface/DDSolid.h"
0010 #include "DetectorDescription/Core/interface/DDMaterial.h"
0011 #include "DetectorDescription/Core/interface/DDCurrentNamespace.h"
0012 #include "DetectorDescription/Core/interface/DDSplit.h"
0013 #include "DetectorDescription/Core/interface/DDConstant.h"
0014 #include "DetectorDescription/Core/interface/DDTypes.h"
0015 #include "DetectorDescription/Core/interface/DDAlgorithm.h"
0016 #include "DetectorDescription/Core/interface/DDAlgorithmFactory.h"
0017 #include "DetectorDescription/Core/interface/DDTransform.h"
0018 #include "CLHEP/Vector/ThreeVector.h"
0019 #include "CLHEP/Vector/Rotation.h"
0020 #include "CLHEP/Vector/RotationInterfaces.h"
0021 #include "CLHEP/Units/GlobalPhysicalConstants.h"
0022 #include "CLHEP/Units/GlobalSystemOfUnits.h"
0023 
0024 #include <cmath>
0025 #include <algorithm>
0026 #include <map>
0027 #include <string>
0028 #include <vector>
0029 
0030 /* 
0031 
0032 == CMS Forward Pixels Geometry ==
0033 
0034  @version 3.02.01 May 30, 2006
0035  @created Dmitry Onoprienko
0036 
0037 == ALGORITHM DESCRIPTION: ==
0038 
0039   Algorithm for placing one-per-blade components
0040   Also computes parameters necessary for defining the "nipple" geometry.
0041 
0042 == Parameters : ==
0043 
0044   "Endcap" - +1 if placing the child volume into +Z disk, -1 if placing into -Z disk.
0045   "Child" - name of a child volume being places (should be in the form "file:volume")
0046             In no child name is given, the algorithm simply calculates Nipple parameters.
0047   "ChildRotation" - rotation of the child volume with respect to the "blade frame". [OPTIONAL]
0048   "ChildTranslation" - vector defining translation of the child volume with respect to the 
0049                        "blade frame". [OPTIONAL]
0050   "FlagString" - string of 24 characters, used to indicate blades into which the child volume 
0051                  should be placed. [OPTIONAL]
0052   "FlagSelector" - 1 character string, key to interpreting "FlagString".
0053                    Positions in "BladeFlag" that have this character will get the child volume.
0054                    
0055   If "Child" parameter is omitted, the algorithm computes rotation needed for describing 
0056   coolant "nipples" but does not do any placements.
0057   
0058   If "Child" is "PixelForwardNippleZPlus" or "PixelForwardNippleZMinus" and no rotation or translation
0059   is supplied, correct rotations and translations are automatically computed.
0060   
0061   Blade frame: origin on the axis of the blade at a distance "ancorRadius" from the beam line
0062   (it therefore coincides with the ancor point of a blade). 
0063   Y along blade axis pointing away from beam line, Z perpendicular to blade plane and pointing away from IP.
0064   (That assumes the axes of ZPlus disk are aligned with CMS global reference frame, and ZMinus disk
0065   is rotated around Y by 180 degrees.)
0066 
0067 == Example of use : ==
0068 
0069 <Algorithm name="track:DDPixFwdBlades">
0070   <rParent name="pixfwdDisk:PixelForwardDiskZMinus"/>
0071   <Numeric name="Endcap"        value="-1." />
0072   <String  name="Child"         value="pixfwdPanel:PixelForwardPanel4Left"/>
0073   <Vector  name="ChildTranslation" type="numeric" nEntries="3"> 0., -[pixfwdPanel:AncorY], [zPanel] </Vector>
0074   <String  name="ChildRotation" value="pixfwdCommon:Y180"/>
0075   <String  name="FlagString"    value="LRRRRLRRRRRRLRRRRLRRRRRR" />  <!-- Panel Layout ZMinus 4  -->
0076   <String  name="FlagSelector"  value="L" />
0077 </Algorithm>
0078 
0079 */
0080 
0081 using namespace std;
0082 
0083 class DDPixFwdBlades : public DDAlgorithm {
0084 public:
0085   DDPixFwdBlades();
0086   ~DDPixFwdBlades() override;
0087 
0088   void initialize(const DDNumericArguments& nArgs,
0089                   const DDVectorArguments& vArgs,
0090                   const DDMapArguments& mArgs,
0091                   const DDStringArguments& sArgs,
0092                   const DDStringVectorArguments& vsArgs) override;
0093 
0094   void execute(DDCompactView& cpv) override;
0095 
0096 private:
0097   int nBlades;         // Number of blades
0098   double bladeAngle;   // Angle of blade rotation around axis perpendicular to beam
0099   double zPlane;       // Common shift in Z for all blades (with respect to disk center plane)
0100   double bladeZShift;  // Shift in Z between the axes of two adjacent blades
0101 
0102   double ancorRadius;  // Distance from beam line to ancor point defining center of "blade frame"
0103 
0104   // Coordinates of Nipple ancor points J and K in "blade frame" :
0105 
0106   double jX;
0107   double jY;
0108   double jZ;
0109   double kX;
0110   double kY;
0111   double kZ;
0112 
0113   double endcap;  // +1 for Z Plus endcap disks, -1 for Z Minus endcap disks
0114 
0115   string flagString;    // String of flags
0116   string flagSelector;  // Character that means "yes" in flagString
0117 
0118   string childName;  // Child volume name
0119 
0120   vector<double> childTranslationVector;  // Child translation with respect to "blade frame"
0121   string childRotationName;               // Child rotation with respect to "blade frame"
0122   string idNameSpace;                     //Namespace of this and ALL sub-parts
0123 
0124   map<string, int> copyNumbers;
0125 
0126   CLHEP::HepRotation* nippleRotationZPlus;
0127   CLHEP::HepRotation* nippleRotationZMinus;
0128   double nippleTranslationX, nippleTranslationY, nippleTranslationZ;
0129 
0130   int issueCopyNumber();
0131   void computeNippleParameters(double endcap);
0132 };
0133 
0134 DDPixFwdBlades::DDPixFwdBlades() {}
0135 DDPixFwdBlades::~DDPixFwdBlades() {}
0136 
0137 void DDPixFwdBlades::initialize(const DDNumericArguments& nArgs,
0138                                 const DDVectorArguments& vArgs,
0139                                 const DDMapArguments&,
0140                                 const DDStringArguments& sArgs,
0141                                 const DDStringVectorArguments&) {
0142   if (nArgs.find("Endcap") != nArgs.end()) {
0143     endcap = nArgs["Endcap"];
0144   } else {
0145     endcap = 1.;
0146   }
0147 
0148   if (sArgs.find("FlagString") != sArgs.end()) {
0149     flagString = sArgs["FlagString"];
0150     flagSelector = sArgs["FlagSelector"];
0151   } else {
0152     flagString = "YYYYYYYYYYYYYYYYYYYYYYYY";
0153     flagSelector = "Y";
0154   }
0155 
0156   if (sArgs.find("Child") != sArgs.end()) {
0157     childName = sArgs["Child"];
0158   } else {
0159     childName = "";
0160   }
0161 
0162   if (vArgs.find("ChildTranslation") != vArgs.end()) {
0163     childTranslationVector = vArgs["ChildTranslation"];
0164   } else {
0165     childTranslationVector = vector<double>(3, 0.);
0166   }
0167 
0168   if (sArgs.find("ChildRotation") != sArgs.end()) {
0169     childRotationName = sArgs["ChildRotation"];
0170   } else {
0171     childRotationName = "";
0172   }
0173 
0174   idNameSpace = DDCurrentNamespace::ns();
0175 
0176   // -- Input geometry parameters :  -----------------------------------------------------
0177 
0178   nBlades = 24;                   // Number of blades
0179   bladeAngle = 20. * CLHEP::deg;  // Angle of blade rotation around its axis
0180   zPlane = 0.;                    // Common shift in Z for all blades (with respect to disk center plane)
0181   bladeZShift = 6. * CLHEP::mm;   // Shift in Z between the axes of two adjacent blades
0182 
0183   ancorRadius = 54.631 * CLHEP::mm;  // Distance from beam line to ancor point defining center of "blade frame"
0184 
0185   // Coordinates of Nipple ancor points J and K in "blade frame" :
0186 
0187   jX = -16.25 * CLHEP::mm;
0188   jY = 96.50 * CLHEP::mm;
0189   jZ = 1.25 * CLHEP::mm;
0190   kX = 16.25 * CLHEP::mm;
0191   kY = 96.50 * CLHEP::mm;
0192   kZ = -1.25 * CLHEP::mm;
0193 
0194   // -- Static initialization :  -----------------------------------------------------------
0195 
0196   nippleRotationZPlus = nullptr;
0197   nippleRotationZMinus = nullptr;
0198   nippleTranslationX = 0.;
0199   nippleTranslationY = 0.;
0200   nippleTranslationZ = 0.;
0201 
0202   copyNumbers.clear();
0203 
0204   edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades: Initialize with endcap " << endcap << " FlagString " << flagString
0205                                 << " FlagSelector " << flagSelector << " Child " << childName << " ChildTranslation "
0206                                 << childTranslationVector[0] << ":" << childTranslationVector[1] << ":"
0207                                 << childTranslationVector[2] << " ChildRotation " << childRotationName << " NameSpace "
0208                                 << idNameSpace << "\n  nBlades " << nBlades << " bladeAngle " << bladeAngle
0209                                 << " zPlane " << zPlane << " bladeZShift " << bladeZShift << " ancorRadius "
0210                                 << ancorRadius << " jX|jY|jZ " << jX << ":" << jY << ":" << jZ << " kX|kY|kZ " << kX
0211                                 << ":" << kY << ":" << kZ;
0212 }
0213 
0214 void DDPixFwdBlades::execute(DDCompactView& cpv) {
0215   // -- Compute Nipple parameters if not already computed :
0216 
0217   if (!nippleRotationZPlus) {
0218     computeNippleParameters(1.);   // Z Plus endcap
0219     computeNippleParameters(-1.);  // Z Minus endcap
0220   }
0221   if (childName.empty())
0222     return;
0223 
0224   // -- Signed versions of blade angle and z-shift :
0225 
0226   double effBladeAngle = -endcap * bladeAngle;
0227   double effBladeZShift = endcap * bladeZShift;
0228 
0229   // -- Names of mother and child volumes :
0230 
0231   DDName mother = parent().name();
0232   DDName child(DDSplit(childName).first, DDSplit(childName).second);
0233 
0234   // -- Get translation and rotation from "blade frame" to "child frame", if any :
0235 
0236   CLHEP::HepRotation childRotMatrix = CLHEP::HepRotation();
0237   if (!childRotationName.empty()) {
0238     DDRotation childRotation = DDRotation(DDName(DDSplit(childRotationName).first, DDSplit(childRotationName).second));
0239     // due to conversion to ROOT::Math::Rotation3D -- Michael Case
0240     DD3Vector x, y, z;
0241     childRotation.rotation().GetComponents(x, y, z);  // these are the orthonormal columns.
0242     CLHEP::HepRep3x3 tr(x.X(), y.X(), z.X(), x.Y(), y.Y(), z.Y(), x.Z(), y.Z(), z.Z());
0243     childRotMatrix = CLHEP::HepRotation(tr);
0244   } else if (childName == "pixfwdNipple:PixelForwardNippleZPlus") {
0245     childRotMatrix = *nippleRotationZPlus;
0246   } else if (childName == "pixfwdNipple:PixelForwardNippleZMinus") {
0247     childRotMatrix = *nippleRotationZMinus;
0248   }
0249 
0250   CLHEP::Hep3Vector childTranslation;
0251   if (childName == "pixfwdNipple:PixelForwardNippleZPlus") {
0252     childTranslation = CLHEP::Hep3Vector(nippleTranslationX, nippleTranslationY, nippleTranslationZ);
0253   } else if (childName == "pixfwdNipple:PixelForwardNippleZMinus") {
0254     childTranslation = CLHEP::Hep3Vector(-nippleTranslationX, nippleTranslationY, nippleTranslationZ);
0255   } else {
0256     childTranslation =
0257         CLHEP::Hep3Vector(childTranslationVector[0], childTranslationVector[1], childTranslationVector[2]);
0258   }
0259 
0260   // Create a matrix for rotation around blade axis (to "blade frame") :
0261 
0262   CLHEP::HepRotation bladeRotMatrix(CLHEP::Hep3Vector(0., 1., 0.), effBladeAngle);
0263 
0264   // Cycle over Phi positions, placing copies of the child volume :
0265 
0266   double deltaPhi = (360. / nBlades) * CLHEP::deg;
0267   int nQuarter = nBlades / 4;
0268   double zShiftMax = effBladeZShift * ((nQuarter - 1) / 2.);
0269 
0270   for (int iBlade = 0; iBlade < nBlades; iBlade++) {
0271     // check if this blade position should be skipped :
0272 
0273     if (flagString[iBlade] != flagSelector[0])
0274       continue;
0275     int copy = issueCopyNumber();
0276 
0277     // calculate Phi and Z shift for this blade :
0278 
0279     double phi = (iBlade + 0.5) * deltaPhi - 90. * CLHEP::deg;
0280     int iQuarter = iBlade % nQuarter;
0281     double zShift = -zShiftMax + iQuarter * effBladeZShift;
0282 
0283     // compute rotation matrix from mother to blade frame :
0284 
0285     CLHEP::HepRotation rotMatrix(CLHEP::Hep3Vector(0., 0., 1.), phi);
0286     rotMatrix *= bladeRotMatrix;
0287 
0288     // convert translation vector from blade frame to mother frame, and add Z shift :
0289 
0290     CLHEP::Hep3Vector translation = rotMatrix(childTranslation + CLHEP::Hep3Vector(0., ancorRadius, 0.));
0291     translation += CLHEP::Hep3Vector(0., 0., zShift + zPlane);
0292 
0293     // create DDRotation for placing the child if not already existent :
0294 
0295     DDRotation rotation;
0296     string rotstr = mother.name() + DDSplit(childName).first + to_string(copy);
0297     rotation = DDRotation(DDName(rotstr, idNameSpace));
0298     edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades: Rotation " << rotstr << " : " << rotation;
0299 
0300     if (!rotation) {
0301       rotMatrix *= childRotMatrix;
0302       rotation = DDrot(DDName(rotstr, idNameSpace),
0303                        make_unique<DDRotationMatrix>(rotMatrix.xx(),
0304                                                      rotMatrix.xy(),
0305                                                      rotMatrix.xz(),
0306                                                      rotMatrix.yx(),
0307                                                      rotMatrix.yy(),
0308                                                      rotMatrix.yz(),
0309                                                      rotMatrix.zx(),
0310                                                      rotMatrix.zy(),
0311                                                      rotMatrix.zz()));
0312     }
0313     // position the child :
0314 
0315     DDTranslation ddtran(translation.x(), translation.y(), translation.z());
0316     cpv.position(child, mother, copy, ddtran, rotation);
0317     edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades::Position " << child << " copy " << copy << " in " << mother
0318                                   << " with translation " << ddtran << " and rotation " << rotation;
0319   }
0320 
0321   // End of cycle over Phi positions
0322 }
0323 
0324 int DDPixFwdBlades::issueCopyNumber() {
0325   if (copyNumbers.count(childName) == 0)
0326     copyNumbers[childName] = 0;
0327   return ++copyNumbers[childName];
0328 }
0329 
0330 // -- Calculating Nipple parameters :  ---------------------------------------------------
0331 
0332 void DDPixFwdBlades::computeNippleParameters(double endcap) {
0333   double effBladeAngle = endcap * bladeAngle;
0334 
0335   CLHEP::Hep3Vector jC;  // Point J in the "cover" blade frame
0336   CLHEP::Hep3Vector kB;  // Point K in the "body" blade frame
0337   string rotNameNippleToCover;
0338   string rotNameCoverToNipple;
0339   string rotNameNippleToBody;
0340 
0341   if (endcap > 0.) {
0342     jC = CLHEP::Hep3Vector(jX, jY + ancorRadius, jZ);
0343     kB = CLHEP::Hep3Vector(kX, kY + ancorRadius, kZ);
0344     rotNameNippleToCover = "NippleToCoverZPlus";
0345     rotNameCoverToNipple = "CoverToNippleZPlus";
0346     rotNameNippleToBody = "NippleToBodyZPlus";
0347   } else {
0348     jC = CLHEP::Hep3Vector(-jX, jY + ancorRadius, jZ);
0349     kB = CLHEP::Hep3Vector(-kX, kY + ancorRadius, kZ);
0350     rotNameNippleToCover = "NippleToCoverZMinus";
0351     rotNameCoverToNipple = "CoverToNippleZMinus";
0352     rotNameNippleToBody = "NippleToBodyZMinus";
0353   }
0354 
0355   // Z-shift from "cover" to "body" blade frame:
0356 
0357   CLHEP::Hep3Vector tCB(bladeZShift * sin(effBladeAngle), 0., bladeZShift * cos(effBladeAngle));
0358 
0359   // Rotation from "cover" blade frame into "body" blade frame :
0360 
0361   double deltaPhi = endcap * (360. / nBlades) * CLHEP::deg;
0362   CLHEP::HepRotation rCB(CLHEP::Hep3Vector(1. * sin(effBladeAngle), 0., 1. * cos(effBladeAngle)), deltaPhi);
0363 
0364   // Transform vector k into "cover" blade frame :
0365 
0366   CLHEP::Hep3Vector kC = rCB * (kB + tCB);
0367 
0368   // Vector JK in the "cover" blade frame:
0369 
0370   CLHEP::Hep3Vector jkC = kC - jC;
0371   double jkLength = jkC.mag();
0372   DDConstant JK(DDName("JK", "pixfwdNipple"), make_unique<double>(jkLength));
0373   edm::LogVerbatim("PixelGeom") << "+++++++++++++++ DDPixFwdBlades: "
0374                                 << "JK Length " << jkLength * CLHEP::mm;
0375 
0376   // Position of the center of a nipple in "cover" blade frame :
0377 
0378   CLHEP::Hep3Vector nippleTranslation((kC + jC) / 2. - CLHEP::Hep3Vector(0., ancorRadius, 0.));
0379   if (endcap > 0) {
0380     nippleTranslationX = nippleTranslation.x();
0381     nippleTranslationY = nippleTranslation.y();
0382     nippleTranslationZ = nippleTranslation.z();
0383   }
0384   edm::LogVerbatim("PixelGeom") << "Child translation : " << nippleTranslation;
0385 
0386   // Rotations from nipple frame to "cover" blade frame and back :
0387 
0388   CLHEP::Hep3Vector vZ(0., 0., 1.);
0389   CLHEP::Hep3Vector axis = vZ.cross(jkC);
0390   double angleCover = vZ.angle(jkC);
0391   edm::LogVerbatim("PixelGeom") << " Angle to Cover: " << angleCover;
0392   CLHEP::HepRotation* rpCN = new CLHEP::HepRotation(axis, angleCover);
0393   if (endcap > 0.) {
0394     nippleRotationZPlus = rpCN;
0395   } else {
0396     nippleRotationZMinus = rpCN;
0397   }
0398   //( endcap > 0. ? nippleRotationZPlus : nippleRotationZMinus ) = rpCN;
0399 
0400   DDrot(
0401       DDName(rotNameCoverToNipple, "pixfwdNipple"),
0402       make_unique<DDRotationMatrix>(
0403           rpCN->xx(), rpCN->xy(), rpCN->xz(), rpCN->yx(), rpCN->yy(), rpCN->yz(), rpCN->zx(), rpCN->zy(), rpCN->zz()));
0404   CLHEP::HepRotation rpNC(axis, -angleCover);
0405   edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades::Defines " << DDName(rotNameCoverToNipple, "pixfwdNipple")
0406                                 << " with " << rpCN;
0407   DDrot(DDName(rotNameNippleToCover, "pixfwdNipple"),
0408         make_unique<DDRotationMatrix>(
0409             rpNC.xx(), rpNC.xy(), rpNC.xz(), rpNC.yx(), rpNC.yy(), rpNC.yz(), rpNC.zx(), rpNC.zy(), rpNC.zz()));
0410   edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades::Defines " << DDName(rotNameNippleToCover, "pixfwdNipple")
0411                                 << " with " << rpNC;
0412 
0413   // Rotation from nipple frame to "body" blade frame :
0414 
0415   CLHEP::HepRotation rpNB(rpNC * rCB);
0416 
0417   DDrot(DDName(rotNameNippleToBody, "pixfwdNipple"),
0418         make_unique<DDRotationMatrix>(
0419             rpNB.xx(), rpNB.xy(), rpNB.xz(), rpNB.yx(), rpNB.yy(), rpNB.yz(), rpNB.zx(), rpNB.zy(), rpNB.zz()));
0420   edm::LogVerbatim("PixelGeom") << "DDPixFwdBlades::Defines " << DDName(rotNameNippleToBody, "pixfwdNipple") << " with "
0421                                 << rpNB;
0422   double angleBody = vZ.angle(rpNB * vZ);
0423   edm::LogVerbatim("PixelGeom") << " Angle to body : " << angleBody;
0424 }
0425 
0426 DEFINE_EDM_PLUGIN(DDAlgorithmFactory, DDPixFwdBlades, "track:DDPixFwdBlades");