EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ODDServiceHelper.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ODDServiceHelper.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
11 #include "DD4hep/DetFactoryHelper.h"
12 
13 using namespace std;
14 using namespace dd4hep;
15 
24 template <typename volume_t>
25 void buildBarrelRouting(Detector& oddd, volume_t& barrelVolume,
26  const xml_comp_t& x_routing,
27  const std::vector<double>& layerR) {
28  // Grab the cables & route them outwards
29  unsigned int nphi = x_routing.nphi();
30 
31  double phiStep = 2 * M_PI / nphi;
32  double phi0 = x_routing.phi0();
33  double rmin = x_routing.rmin();
34  double rmax = x_routing.rmax();
35  double n = x_routing.number();
36 
37  for (int side = -1; side < 2; side += 2) {
38  // Loop over the layer routings
39  for (unsigned int ib = 1; ib < layerR.size(); ++ib) {
40  for (unsigned int iphi = 0; iphi < nphi; ++iphi) {
41  // Calculate the phi
42  double phi = phi0 + iphi * phiStep;
43 
44  // The layer position
45  double gap = x_routing.gap();
46  double clength = layerR[ib] - layerR[ib - 1] - 2. * gap;
47  double rpos = 0.5 * (layerR[ib] + layerR[ib - 1]);
48  double xpos = rpos * cos(phi);
49  double ypos = rpos * sin(phi);
50  double zpos = side * x_routing.z_offset();
51 
52  Assembly cableboxAssembly("CableBox");
53  if (x_routing.hasChild(_U(box))) {
54  // The box plate for the cables
55  xml_comp_t x_box = x_routing.child(_U(box));
56  Box box(x_box.dz(), n * ib * rmax, 0.5 * clength);
57  Volume boxVolume("CableBand", box,
58  oddd.material(x_routing.materialStr()));
59  boxVolume.setVisAttributes(oddd, x_box.visStr());
60 
61  cableboxAssembly.placeVolume(
62  boxVolume, Position(side * (rmax + x_box.dz()), 0., 0.));
63  }
64 
65  Tube cable(rmin, rmax, 0.5 * clength);
66  Volume cableVolume("Cable", cable,
67  oddd.material(x_routing.materialStr()));
68  cableVolume.setVisAttributes(oddd, x_routing.visStr());
69 
70  for (unsigned int icable = 0; icable < n * ib; ++icable) {
71  // Place the pipe in the stave
72  cableboxAssembly.placeVolume(
73  cableVolume, Position(0., (-n * ib + 1 + 2 * icable) * rmax, 0.));
74  }
75  // Place the pipe in the stave
76  barrelVolume.placeVolume(
77  cableboxAssembly,
78  Transform3D(RotationZ(phi) * RotationY(0.5 * M_PI),
79  Position(xpos, ypos, zpos)));
80  }
81  }
82  }
83 }
84 
93 template <typename volume_t>
94 void buildEndcapRouting(Detector& oddd, volume_t& endcapVolume,
95  const xml_comp_t& x_routing,
96  const std::vector<double>& endcapZ) {
97  // Grab the cables & route them outwards
98  unsigned int nphi = x_routing.nphi();
99 
100  double phiStep = 2 * M_PI / nphi;
101  double phi0 = x_routing.phi0();
102  double rmin = x_routing.rmin();
103  double rmax = x_routing.rmax();
104  double r = x_routing.r();
105  double n = x_routing.number();
106 
107  // Loop over the layer routings
108  for (unsigned int iec = 1; iec < endcapZ.size(); ++iec) {
109  for (unsigned int iphi = 0; iphi < nphi; ++iphi) {
110  // Calculate the phi
111  double phi = phi0 + iphi * phiStep;
112 
113  // The layer position
114  double gap = x_routing.gap();
115  double clength = std::abs(endcapZ[iec] - endcapZ[iec - 1]) - 2. * gap;
116  double xpos = r * cos(phi);
117  double ypos = r * sin(phi);
118  double zpos = 0.5 * (endcapZ[iec] + endcapZ[iec - 1]);
119 
120  Assembly cableboxAssembly("CableBox");
121  if (x_routing.hasChild(_U(box))) {
122  // The box plate for the cables
123  xml_comp_t x_box = x_routing.child(_U(box));
124  Box box(x_box.dz(), n * iec * rmax, 0.5 * clength);
125  Volume boxVolume("CableBand", box,
126  oddd.material(x_routing.materialStr()));
127  boxVolume.setVisAttributes(oddd, x_box.visStr());
128 
129  cableboxAssembly.placeVolume(boxVolume,
130  Position(rmax + x_box.dz(), 0., 0.));
131  }
132 
133  Tube cable(rmin, rmax, 0.5 * clength);
134  Volume cableVolume("Cable", cable,
135  oddd.material(x_routing.materialStr()));
136  cableVolume.setVisAttributes(oddd, x_routing.visStr());
137 
138  for (unsigned int icable = 0; icable < n * iec; ++icable) {
139  // Place the pipe in the stave
140  cableboxAssembly.placeVolume(
141  cableVolume, Position(0., (-n * iec + 1 + 2 * icable) * rmax, 0.));
142  }
143  // Place the pipe in the stave
144  endcapVolume.placeVolume(
145  cableboxAssembly,
146  Transform3D(RotationZ(+phi), Position(xpos, ypos, zpos)));
147  }
148  }
149 }
150 
159 template <typename volume_t>
160 void buildSupportCylinder(Detector& oddd, volume_t& motherVolume,
161  const xml_comp_t& x_mother_comp,
162  std::vector<double>& layerR) {
163  size_t supportNum = 0;
164  for (xml_coll_t sup(x_mother_comp, _U(support)); sup; ++sup, ++supportNum) {
165  xml_comp_t x_support = sup;
166  // Create the volume of the support structure
167  string supportName = _toString((int)supportNum, "SupportCylinder%d");
168 
169  // Remember the layer radius if it is needed for operation
170  if (x_support.hasChild(_Unicode(connector))) {
171  layerR.push_back(0.5 * (x_support.rmin() + x_support.rmax()));
172  }
173  // If nz is not set to 0, build 2 symmetric ones
174  for (int side = -1; side < x_support.nsides(); side += 2) {
175  // Create the support volume
176  Volume supportVolume(
177  supportName, Tube(x_support.rmin(), x_support.rmax(), x_support.dz()),
178  oddd.material(x_support.materialStr()));
179  supportVolume.setVisAttributes(oddd, x_support.visStr());
180  // Place the support structure
181  motherVolume.placeVolume(supportVolume,
182  Position(0., 0., side * x_support.z_offset()));
183  }
184  }
185 }
186 
195 template <typename volume_t>
196 void buildCoolingRings(Detector& oddd, volume_t& motherVolume,
197  const xml_comp_t& x_mother_comp) {
198  size_t cringNum = 0;
199  for (xml_coll_t cring(x_mother_comp, _Unicode(cooling_ring)); cring;
200  ++cring, ++cringNum) {
201  xml_comp_t x_cooling_ring = cring;
202 
203  double r = x_cooling_ring.r();
204  double nPhi = x_cooling_ring.nphi();
205  double phiStep = 2. * M_PI / nPhi;
206  double zpos = x_cooling_ring.z_offset();
207  double dz = 2 * (r * M_PI / nPhi - x_cooling_ring.gap());
208 
209  // Create the segments around the ring
210  for (unsigned int iphi = 0; iphi < nPhi; ++iphi) {
211  Volume coolingSegement(
212  "CoolingRingSegment",
213  Tube(x_cooling_ring.rmin(), x_cooling_ring.rmax(), dz),
214  oddd.material(x_cooling_ring.materialStr()));
215  coolingSegement.setVisAttributes(oddd, x_cooling_ring.visStr());
216 
217  // position & orientation
218  double phi = iphi * phiStep;
219  Position segementPos(r * cos(phi), r * sin(phi), zpos);
220  // Place the support structure
221  motherVolume.placeVolume(
222  coolingSegement,
223  Transform3D(RotationY(0.5 * M_PI) * RotationX(0.5 * M_PI - phi),
224  segementPos));
225  }
226  }
227 }