CMS 3D CMS Logo

DDCutTubsFromPoints.cc
Go to the documentation of this file.
1 #include "DD4hep/DetFactoryHelper.h"
4 
6 
7 using namespace cms_units::operators; // _deg and convertRadToDeg
8 
9 static long algorithm(dd4hep::Detector& /* description */, cms::DDParsingContext& ctxt, xml_h e) {
10  cms::DDNamespace ns(ctxt, e, true);
12 
13  dd4hep::Volume mother = ns.volume(args.parentName());
14 
15  struct Section {
16  float phi; // phi position of this edge
17  float z_l; // -Z end (cuttubs l plane)
18  float z_t; // +Z end (cuttubs t plane)
19  // radius is implicitly r_min
20  };
21 
22  std::vector<Section> sections;
23 
24  float r_min = args.value<float>("rMin");
25  float r_max = args.value<float>("rMax");
26  float z_pos = args.value<float>("zPos");
27 
28  std::string solidOutput = args.value<std::string>("SolidName");
29  const std::string material = args.value<std::string>("Material");
30 
31  auto phis = ns.vecFloat(args.str("Phi"));
32  auto z_ls = ns.vecFloat(args.str("z_l"));
33  auto z_ts = ns.vecFloat(args.str("z_t"));
34 
35  assert(phis.size() == z_ls.size());
36  assert(phis.size() == z_ts.size());
37 
38  for (unsigned i = 0; i < phis.size(); i++) {
39  Section s = {phis[i], z_ls[i], z_ts[i]};
40 
41  edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: Sections :" << phis[i] << " , " << z_ls[i] << " , "
42  << z_ts[i];
43  sections.emplace_back(s);
44  }
45 
46  assert(!sections.empty());
47 
48  // a segment is produced between each two consecutive sections that have a
49  // non-zero phi distance. Sections with zero phi distance can be used to
50  // create sharp jumps.
51 
52  solidOutput = ns.prepend(solidOutput);
53  edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints debug: Parent " << args.parentName() << "\tSolid "
54  << solidOutput << " NameSpace " << ns.name() << "\tnumber of sections "
55  << sections.size();
56 
57  // radius for plane calculations
58  // We use r_max here, since P3 later has a Z that is always more inside
59  // than the extreme points. This means the cutting planes have outwards
60  // slopes in r-Z, and the corner at r_max could stick out of the bounding
61  // volume otherwise.
62  float r = r_max;
63 
64  // min and max z for the placement in the end
65  float min_z = 1e9;
66  float max_z = -1e9;
67 
68  // counter of actually produced segments (excluding skipped ones)
69  int segment = 0;
70 
71  // the segments and their corresponding offset (absolute, as in the input)
72  std::vector<dd4hep::Solid> segments;
73  std::vector<float> offsets;
74 
75  Section s1 = sections[0];
76 
77  for (Section s2 : sections) {
78  if (s1.phi != s2.phi) {
79  segment++;
80  // produce segment s1-s2.
81  float phi1 = s1.phi;
82  float phi2 = s2.phi;
83 
84  // track the min/max to properly place&align later
85  if (s2.z_l < min_z)
86  min_z = s2.z_l;
87  if (s2.z_t > max_z)
88  max_z = s2.z_t;
89 
90  float P1_z_l = s1.z_l;
91  float P1_z_t = s1.z_t;
92  float P2_z_l = s2.z_l;
93  float P2_z_t = s2.z_t;
94 
95  float P1_x_t = cos(phi1) * r;
96  float P1_x_l = cos(phi1) * r;
97  float P1_y_t = sin(phi1) * r;
98  float P1_y_l = sin(phi1) * r;
99 
100  float P2_x_t = cos(phi2) * r;
101  float P2_x_l = cos(phi2) * r;
102  float P2_y_t = sin(phi2) * r;
103  float P2_y_l = sin(phi2) * r;
104 
105  // each cutting plane is defined by P1-3. P1-2 are corners of the
106  // segment, P3 is at r=0 with the "average" z to get a nice cut.
107  float P3_z_l = (P1_z_l + P2_z_l) / 2;
108  float P3_z_t = (P1_z_t + P2_z_t) / 2;
109 
110  std::string segname(solidOutput + "_seg_" + std::to_string(segment));
111  edm::LogVerbatim("TrackerGeom").log([&](auto& log) {
112  log << "DDCutTubsFromPoints: P1 l: " << segname << P1_x_l << " , " << P1_y_l << " , " << P1_z_l;
113  log << "DDCutTubsFromPoints: P1 t: " << segname << P1_x_t << " , " << P1_y_t << " , " << P1_z_t;
114  log << "DDCutTubsFromPoints: P2 l: " << segname << P2_x_l << " , " << P2_y_l << " , " << P2_z_l;
115  log << "DDCutTubsFromPoints: P2 t: " << segname << P2_x_t << " , " << P2_y_t << " , " << P2_z_t;
116  });
117 
118  // we only have one dz to position both planes. The anchor is implicitly
119  // between the P3's, we have to use an offset later to make the segments
120  // line up correctly.
121  float dz = 0.5 * (P3_z_t - P3_z_l);
122  float offset = 0.5 * (P3_z_t + P3_z_l);
123 
124  // the plane is defined by P1-P3 and P2-P3; since P3 is at r=0 we
125  // only need the z.
126  float D1_z_l = P1_z_l - P3_z_l;
127  float D2_z_l = P2_z_l - P3_z_l;
128 
129  // the normal is then the cross product...
130  float n_x_l = (P1_y_l * D2_z_l) - (D1_z_l * P2_y_l);
131  float n_y_l = (D1_z_l * P2_x_l) - (P1_x_l * D2_z_l);
132  float n_z_l = (P1_x_l * P2_y_l) - (P1_y_l * P2_x_l);
133 
134  edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: l_Pos (" << n_x_l << "," << n_y_l << "," << n_z_l << ")";
135 
136  // ... normalized.
137  // flip the sign here (but not for t) since root wants it like that.
138  float norm = -sqrt(n_x_l * n_x_l + n_y_l * n_y_l + n_z_l * n_z_l);
139  n_x_l /= norm;
140  n_y_l /= norm;
141  n_z_l /= norm;
142 
143  edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: l_norm " << norm;
144 
145  // same game for the t side.
146  float D1_z_t = P1_z_t - P3_z_t;
147  float D2_z_t = P2_z_t - P3_z_t;
148 
149  float n_x_t = (P1_y_t * D2_z_t) - (D1_z_t * P2_y_t);
150  float n_y_t = (D1_z_t * P2_x_t) - (P1_x_t * D2_z_t);
151  float n_z_t = (P1_x_t * P2_y_t) - (P1_y_t * P2_x_t);
152 
153  edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: t_Pos (" << n_x_t << "," << n_y_t << "," << n_z_t << ")";
154 
155  norm = sqrt(n_x_t * n_x_t + n_y_t * n_y_t + n_z_t * n_z_t);
156 
157  edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: t_norm " << norm;
158 
159  n_x_t /= norm;
160  n_y_t /= norm;
161  n_z_t /= norm;
162 
163  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);
164 
165  edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: CutTube(" << r_min << "," << r_max << "," << dz << ","
166  << phi1 << "," << phi2 << "," << n_x_l << "," << n_y_l << "," << n_z_l << ","
167  << n_x_t << "," << n_y_t << "," << n_z_t << ")";
168 
169  segments.emplace_back(seg);
170  offsets.emplace_back(offset);
171  }
172 
173  s1 = s2;
174  }
175 
176  assert(segments.size() >= 2); // less would be special cases
177 
178  dd4hep::Solid solid = segments[0];
179 
180  // placement happens relative to the first member of the union
181  float shift = offsets[0];
182 
183  for (unsigned i = 1; i < segments.size() - 1; i++) {
184  solid = dd4hep::UnionSolid(solidOutput + "_uni_" + std::to_string(i + 1),
185  solid,
186  segments[i],
187  dd4hep::Position(0., 0., offsets[i] - shift));
188  }
189 
190  solid = dd4hep::UnionSolid(solidOutput,
191  solid,
192  segments[segments.size() - 1],
193  dd4hep::Position(0., 0., offsets[segments.size() - 1] - shift));
194 
195  edm::LogVerbatim("TrackerGeom") << "DDCutTubsFromPoints: " << solid.name() << " Union solid with " << segments.size()
196  << " segments";
197 
198  // remove the common offset from the input, to get sth. aligned at z=0.
199  float offset = -shift + (min_z + 0.5 * (max_z - min_z));
200 
201  auto logical = dd4hep::Volume(solidOutput, solid, ns.material(material));
202 
203  int nCopy = 1;
204  auto pos = dd4hep::Position(0., 0., z_pos - offset);
205  mother.placeVolume(logical, nCopy, dd4hep::Transform3D(dd4hep::Rotation3D(), pos));
206 
207  mother.placeVolume(logical, nCopy + 1, dd4hep::Transform3D(ns.rotation("pixfwdCommon:Z180"), pos));
208 
209  return cms::s_executed;
210 }
211 
212 // first argument is the type from the xml file
213 DECLARE_DDCMS_DETELEMENT(DDCMS_track_DDCutTubsFromPoints, algorithm)
Log< level::Info, true > LogVerbatim
const dd4hep::Rotation3D & rotation(const std::string &name) const
Definition: DDNamespace.cc:182
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
assert(be >=bs)
dd4hep::Material material(const std::string &name) const
Definition: DDNamespace.cc:166
static std::string to_string(const XMLCh *ch)
#define DECLARE_DDCMS_DETELEMENT(name, func)
Definition: DDPlugins.h:25
static constexpr long s_executed
std::vector< float > vecFloat(const std::string &name) const
Definition: DDNamespace.cc:341
T sqrt(T t)
Definition: SSEVec.h:23
std::string_view name() const
Definition: DDNamespace.h:79
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
dd4hep::Volume Volume
static unsigned int const shift
static long algorithm(dd4hep::Detector &, cms::DDParsingContext &ctxt, xml_h e)
dd4hep::Volume volume(const std::string &name, bool exc=true) const
Definition: DDNamespace.cc:276
std::string prepend(const std::string &) const
Definition: DDNamespace.cc:99