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