Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:15:21

0001 #include "DD4hep/DetFactoryHelper.h"
0002 #include "DetectorDescription/DDCMS/interface/DDPlugins.h"
0003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0004 
0005 #include "DataFormats/Math/interface/CMSUnits.h"
0006 
0007 using namespace cms_units::operators;  // _deg and convertRadToDeg
0008 
0009 static long algorithm(dd4hep::Detector& /* description */, cms::DDParsingContext& ctxt, xml_h e) {
0010   cms::DDNamespace ns(ctxt, e, true);
0011   cms::DDAlgoArguments args(ctxt, e);
0012 
0013   dd4hep::Volume mother = ns.volume(args.parentName());
0014 
0015   struct Section {
0016     float phi;  // phi position of this edge
0017     float z_l;  // -Z end (cuttubs l plane)
0018     float z_t;  // +Z end (cuttubs t plane)
0019     // radius is implicitly r_min
0020   };
0021 
0022   std::vector<Section> sections;
0023 
0024   float r_min = args.value<float>("rMin");
0025   float r_max = args.value<float>("rMax");
0026   float z_pos = args.value<float>("zPos");
0027 
0028   std::string solidOutput = args.value<std::string>("SolidName");
0029   const std::string material = args.value<std::string>("Material");
0030 
0031   auto phis = ns.vecFloat(args.str("Phi"));
0032   auto z_ls = ns.vecFloat(args.str("z_l"));
0033   auto z_ts = ns.vecFloat(args.str("z_t"));
0034 
0035   assert(phis.size() == z_ls.size());
0036   assert(phis.size() == z_ts.size());
0037 
0038   for (unsigned i = 0; i < phis.size(); i++) {
0039     Section s = {phis[i], z_ls[i], z_ts[i]};
0040 
0041     edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: Sections :" << phis[i] << " , " << z_ls[i] << " , "
0042                                     << z_ts[i];
0043     sections.emplace_back(s);
0044   }
0045 
0046   assert(!sections.empty());
0047 
0048   // a segment is produced between each two consecutive sections that have a
0049   // non-zero phi distance. Sections with zero phi distance can be used to
0050   // create sharp jumps.
0051 
0052   solidOutput = ns.prepend(solidOutput);
0053   edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints debug: Parent " << args.parentName() << "\tSolid "
0054                                   << solidOutput << " NameSpace " << ns.name() << "\tnumber of sections "
0055                                   << sections.size();
0056 
0057   // radius for plane calculations
0058   // We use r_max here, since P3 later has a Z that is always more inside
0059   // than the extreme points. This means the cutting planes have outwards
0060   // slopes in r-Z, and the corner at r_max could stick out of the bounding
0061   // volume otherwise.
0062   float r = r_max;
0063 
0064   // min and max z for the placement in the end
0065   float min_z = 1e9;
0066   float max_z = -1e9;
0067 
0068   // counter of actually produced segments (excluding skipped ones)
0069   int segment = 0;
0070 
0071   // the segments and their corresponding offset (absolute, as in the input)
0072   std::vector<dd4hep::Solid> segments;
0073   std::vector<float> offsets;
0074 
0075   Section s1 = sections[0];
0076 
0077   for (Section s2 : sections) {
0078     if (s1.phi != s2.phi) {
0079       segment++;
0080       // produce segment s1-s2.
0081       float phi1 = s1.phi;
0082       float phi2 = s2.phi;
0083 
0084       // track the min/max to properly place&align later
0085       if (s2.z_l < min_z)
0086         min_z = s2.z_l;
0087       if (s2.z_t > max_z)
0088         max_z = s2.z_t;
0089 
0090       float P1_z_l = s1.z_l;
0091       float P1_z_t = s1.z_t;
0092       float P2_z_l = s2.z_l;
0093       float P2_z_t = s2.z_t;
0094 
0095       float P1_x_t = cos(phi1) * r;
0096       float P1_x_l = cos(phi1) * r;
0097       float P1_y_t = sin(phi1) * r;
0098       float P1_y_l = sin(phi1) * r;
0099 
0100       float P2_x_t = cos(phi2) * r;
0101       float P2_x_l = cos(phi2) * r;
0102       float P2_y_t = sin(phi2) * r;
0103       float P2_y_l = sin(phi2) * r;
0104 
0105       // each cutting plane is defined by P1-3. P1-2 are corners of the
0106       // segment, P3 is at r=0 with the "average" z to get a nice cut.
0107       float P3_z_l = (P1_z_l + P2_z_l) / 2;
0108       float P3_z_t = (P1_z_t + P2_z_t) / 2;
0109 
0110       std::string segname(solidOutput + "_seg_" + std::to_string(segment));
0111       edm::LogVerbatim("TrackerGeom").log([&](auto& log) {
0112         log << "DDCutTubsFromPoints: P1 l: " << segname << P1_x_l << " , " << P1_y_l << " , " << P1_z_l;
0113         log << "DDCutTubsFromPoints: P1 t: " << segname << P1_x_t << " , " << P1_y_t << " , " << P1_z_t;
0114         log << "DDCutTubsFromPoints: P2 l: " << segname << P2_x_l << " , " << P2_y_l << " , " << P2_z_l;
0115         log << "DDCutTubsFromPoints: P2 t: " << segname << P2_x_t << " , " << P2_y_t << " , " << P2_z_t;
0116       });
0117 
0118       // we only have one dz to position both planes. The anchor is implicitly
0119       // between the P3's, we have to use an offset later to make the segments
0120       // line up correctly.
0121       float dz = 0.5 * (P3_z_t - P3_z_l);
0122       float offset = 0.5 * (P3_z_t + P3_z_l);
0123 
0124       // the plane is defined by P1-P3 and P2-P3; since P3 is at r=0 we
0125       // only need the z.
0126       float D1_z_l = P1_z_l - P3_z_l;
0127       float D2_z_l = P2_z_l - P3_z_l;
0128 
0129       // the normal is then the cross product...
0130       float n_x_l = (P1_y_l * D2_z_l) - (D1_z_l * P2_y_l);
0131       float n_y_l = (D1_z_l * P2_x_l) - (P1_x_l * D2_z_l);
0132       float n_z_l = (P1_x_l * P2_y_l) - (P1_y_l * P2_x_l);
0133 
0134       edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: l_Pos (" << n_x_l << "," << n_y_l << "," << n_z_l << ")";
0135 
0136       // ... normalized.
0137       // flip the sign here (but not for t) since root wants it like that.
0138       float norm = -sqrt(n_x_l * n_x_l + n_y_l * n_y_l + n_z_l * n_z_l);
0139       n_x_l /= norm;
0140       n_y_l /= norm;
0141       n_z_l /= norm;
0142 
0143       edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: l_norm " << norm;
0144 
0145       // same game for the t side.
0146       float D1_z_t = P1_z_t - P3_z_t;
0147       float D2_z_t = P2_z_t - P3_z_t;
0148 
0149       float n_x_t = (P1_y_t * D2_z_t) - (D1_z_t * P2_y_t);
0150       float n_y_t = (D1_z_t * P2_x_t) - (P1_x_t * D2_z_t);
0151       float n_z_t = (P1_x_t * P2_y_t) - (P1_y_t * P2_x_t);
0152 
0153       edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: t_Pos (" << n_x_t << "," << n_y_t << "," << n_z_t << ")";
0154 
0155       norm = sqrt(n_x_t * n_x_t + n_y_t * n_y_t + n_z_t * n_z_t);
0156 
0157       edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: t_norm " << norm;
0158 
0159       n_x_t /= norm;
0160       n_y_t /= norm;
0161       n_z_t /= norm;
0162 
0163       auto seg = dd4hep::CutTube(segname, r_min, r_max, dz, phi1, phi2, n_x_l, n_y_l, n_z_l, n_x_t, n_y_t, n_z_t);
0164 
0165       edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: CutTube(" << r_min << "," << r_max << "," << dz << ","
0166                                       << phi1 << "," << phi2 << "," << n_x_l << "," << n_y_l << "," << n_z_l << ","
0167                                       << n_x_t << "," << n_y_t << "," << n_z_t << ")";
0168 
0169       segments.emplace_back(seg);
0170       offsets.emplace_back(offset);
0171     }
0172 
0173     s1 = s2;
0174   }
0175 
0176   assert(segments.size() >= 2);  // less would be special cases
0177 
0178   dd4hep::Solid solid = segments[0];
0179 
0180   // placement happens relative to the first member of the union
0181   float shift = offsets[0];
0182 
0183   for (unsigned i = 1; i < segments.size() - 1; i++) {
0184     solid = dd4hep::UnionSolid(solidOutput + "_uni_" + std::to_string(i + 1),
0185                                solid,
0186                                segments[i],
0187                                dd4hep::Position(0., 0., offsets[i] - shift));
0188   }
0189 
0190   solid = dd4hep::UnionSolid(solidOutput,
0191                              solid,
0192                              segments[segments.size() - 1],
0193                              dd4hep::Position(0., 0., offsets[segments.size() - 1] - shift));
0194 
0195   edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: " << solid.name() << " Union solid with " << segments.size()
0196                                   << " segments";
0197 
0198   // remove the common offset from the input, to get sth. aligned at z=0.
0199   float offset = -shift + (min_z + 0.5 * (max_z - min_z));
0200 
0201   auto logical = dd4hep::Volume(solidOutput, solid, ns.material(material));
0202 
0203   int nCopy = 1;
0204   auto pos = dd4hep::Position(0., 0., z_pos - offset);
0205   mother.placeVolume(logical, nCopy, dd4hep::Transform3D(dd4hep::Rotation3D(), pos));
0206 
0207   mother.placeVolume(logical, nCopy + 1, dd4hep::Transform3D(ns.rotation("pixfwdCommon:Z180"), pos));
0208 
0209   return cms::s_executed;
0210 }
0211 
0212 // first argument is the type from the xml file
0213 DECLARE_DDCMS_DETELEMENT(DDCMS_track_DDCutTubsFromPoints, algorithm)