EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ODDPixelBarrel_geo.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ODDPixelBarrel_geo.cpp
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 
11 
12 #include "DD4hep/DetFactoryHelper.h"
13 #include "ODDModuleHelper.hpp"
14 #include "ODDServiceHelper.hpp"
15 
16 using namespace std;
17 using namespace dd4hep;
18 
19 static void completeStaveStructure(Detector& oddd, xml_comp_t& x_stave,
20  Assembly& staveAssembly, double staveHlength,
21  double ylength) {
22  unsigned int nModules = x_stave.nmodules();
23 
24  // Place carbon foam structure
25  if (x_stave.hasChild(_U(subtraction)) and x_stave.hasChild(_U(tube))) {
26  xml_comp_t x_sub = x_stave.child(_U(subtraction));
27  xml_comp_t x_trd = x_sub.child(_U(trd));
28  xml_comp_t x_tubs = x_sub.child(_U(tubs));
29  xml_comp_t x_pipe = x_stave.child(_U(tube));
30 
31  // Create the two shapes first
32  Trapezoid foamShape(x_trd.x1(), x_trd.x2(), staveHlength + x_trd.dz(),
33  staveHlength + x_trd.dz(), x_trd.thickness());
34 
35  Tube foamCutout(x_tubs.rmin(), x_tubs.rmax(), staveHlength + x_tubs.dz());
36 
37  // Create the subtraction
38  Volume foamVolume("CarbonFoam",
39  SubtractionSolid(foamShape, foamCutout,
40  Transform3D(RotationX(0.5 * M_PI))),
41  oddd.material(x_sub.materialStr()));
42  foamVolume.setVisAttributes(oddd, x_sub.visStr());
43  // Place the volume in the stave
44  staveAssembly.placeVolume(
45  foamVolume,
46  Position(x_sub.x_offset(), x_sub.y_offset(), x_sub.z_offset()));
47 
48  Tube coolingPipe(x_pipe.rmin(), x_pipe.rmax(), staveHlength + x_pipe.dz());
49  // Create the subtraction
50  Volume pipeVolume("CoolingPipe", coolingPipe,
51  oddd.material(x_pipe.materialStr()));
52  pipeVolume.setVisAttributes(oddd, x_pipe.visStr());
53 
54  // Place the pipe in the stave
55  staveAssembly.placeVolume(
56  pipeVolume, Transform3D(RotationX(0.5 * M_PI),
57  Position(x_pipe.x_offset(), x_pipe.y_offset(),
58  x_pipe.z_offset())));
59 
60  xml_comp_t x_cable = x_stave.child(_U(eltube));
61  // Place the support cables for the modules
62  for (unsigned int modCable = 0; modCable < 0.5 * nModules; ++modCable) {
63  double cableLength = staveHlength - modCable * ylength;
64 
65  for (int side = -1; side < 2; side += 2) {
66  Tube cable(x_cable.rmin(), x_cable.rmax(), 0.5 * cableLength);
67  // Create the cable volume
68  Volume cableVolume("Cable", cable,
69  oddd.material(x_cable.materialStr()));
70  cableVolume.setVisAttributes(oddd, x_cable.visStr());
71 
72  // Place the pipe in the stave
73  staveAssembly.placeVolume(
74  cableVolume,
76  RotationX(0.5 * M_PI),
77  Position(
78  x_cable.x_offset() + 2.05 * modCable * x_cable.rmax(),
79  side * (staveHlength - 0.5 * cableLength + x_cable.dz()),
80  x_cable.z_offset())));
81  }
82  }
83  }
84 }
85 
86 static Ref_t create_element(Detector& oddd, xml_h xml, SensitiveDetector sens) {
87  xml_det_t x_det = xml;
88  string detName = x_det.nameStr();
89 
90  // Make DetElement
91  DetElement barrelDetector(detName, x_det.id());
92 
93  // Add Extension to DetElement for the RecoGeometry
94  Acts::ActsExtension* barrelExtension = new Acts::ActsExtension();
95  barrelExtension->addType("barrel", "detector");
96  // Add the volume boundary material if configured
97  for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) {
98  xml_comp_t x_boundary_material = bmat;
99  xmlToProtoSurfaceMaterial(x_boundary_material, *barrelExtension,
100  "boundary_material");
101  }
102  barrelDetector.addExtension<Acts::ActsExtension>(barrelExtension);
103 
104  // Make Volume
105  dd4hep::xml::Dimension x_det_dim(x_det.dimensions());
106  string barrelShapeName = x_det_dim.nameStr();
107 
108  // The Shape and Volume
109  Tube barrelShape(x_det_dim.rmin(), x_det_dim.rmax(), x_det_dim.dz());
110  Volume barrelVolume(detName, barrelShape, oddd.air());
111  barrelVolume.setVisAttributes(oddd, x_det.visStr());
112 
113  // Create the stave volume and DetElement tree
114  xml_comp_t x_stave = x_det.child(_U(stave));
115  Assembly staveAssembly("stave");
116  // Visualization
117  staveAssembly.setVisAttributes(oddd, x_stave.visStr());
118  // DetElement tree
119  DetElement staveElementTemplate("StaveElementTemplate", 0);
120 
121  // Create the module components
122  xml_comp_t x_module = x_det.child(_U(module));
123  double ylength = 0.;
124  auto module =
125  ODDModuleHelper::assembleRectangularModule(oddd, sens, x_module, ylength);
126 
127  // Place the modules into the stave
128  double gap = x_stave.gap();
129  unsigned int nModules = x_stave.nmodules();
130  double ystep = ylength + gap;
131  double ymin = (nModules * 0.5 - 0.5) * ylength;
132  double staveHlength = ymin + 0.5 * ylength;
133 
134  // Loop over the modules and place them in the stave
135  for (unsigned int moduleNum = 0; moduleNum < nModules; ++moduleNum) {
136  // Place them along local y
137  PlacedVolume placedModule = staveAssembly.placeVolume(
138  module.first, Position(0., -ymin + moduleNum * ystep, 0.));
139  placedModule.addPhysVolID("module", moduleNum);
140 
141  string moduleName = _toString((int)moduleNum, "module%d");
142  // Clone the detector element
143  auto moduleElement = module.second.clone(moduleName, moduleNum);
144  moduleElement.setPlacement(placedModule);
145  // Assign it as child to the stave template
146  staveElementTemplate.add(moduleElement);
147  }
148 
149  // Complete the staveStructure
150  completeStaveStructure(oddd, x_stave, staveAssembly, staveHlength, ylength);
151 
152  std::vector<double> layerR;
153 
154  // Loop over the layers to build staves
155  size_t layerNum = 0;
156  for (xml_coll_t lay(xml, _U(layer)); lay; ++lay, ++layerNum) {
157  xml_comp_t x_layer = lay;
158 
159  // The Layer envelope volume
160  string layerName = detName + std::to_string(layerNum);
161  Volume layerVolume(
162  layerName,
163  Tube(x_layer.rmin(), x_layer.rmax(), staveHlength + x_layer.outer_z()),
164  oddd.air());
165  // Visualization
166  layerVolume.setVisAttributes(oddd, x_layer.visStr());
167 
168  // The DetElement tree, keep it flat
169  DetElement layerElement(barrelDetector, layerName, layerNum);
170 
171  // Place the staves in the layer
172  unsigned int nStaves = x_layer.nphi();
173  double phiStep = 2. * M_PI / nStaves;
174  double phiTilt = x_layer.phi_tilt();
175  double phi0 = x_layer.phi0();
176  double r = x_layer.r();
177  layerR.push_back(r);
178 
179  // Loop over the staves and place them
180  for (unsigned int staveNum = 0; staveNum < nStaves; ++staveNum) {
181  string staveName = _toString((int)staveNum, "stave%d");
182  // position of the stave
183  double phi = phi0 + staveNum * phiStep;
184  double x = r * cos(phi);
185  double y = r * sin(phi);
186  // Now place the stave
187  PlacedVolume placedStave = layerVolume.placeVolume(
188  staveAssembly,
189  Transform3D(RotationY(0.5 * M_PI) * RotationZ(0.5 * M_PI) *
190  RotationY(phi + phiTilt),
191  Position(x, y, 0.)));
192  placedStave.addPhysVolID("stave", staveNum);
193 
194  // Clone the stave element from the template
195  DetElement staveElement = staveElementTemplate.clone(staveName, staveNum);
196  staveElement.setPlacement(placedStave);
197  // Add to the layer element
198  layerElement.add(staveElement);
199  }
200 
201  // Place the support cylinder per layer
202  buildSupportCylinder(oddd, layerVolume, x_layer, layerR);
203 
204  // Cleanup the templates
205  // dd4hep::detail::destroyHandle(staveElementTemplate);
206  // dd4hep::detail::destroyHandle(module.second);
207 
208  // Place the layer with appropriate Acts::Extension
209  // Configure the ACTS extension
210  Acts::ActsExtension* layerExtension = new Acts::ActsExtension();
211  // Add the proto layer material
212  for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
213  xml_comp_t x_layer_material = lmat;
214  xmlToProtoSurfaceMaterial(x_layer_material, *layerExtension,
215  "layer_material");
216  }
217  layerExtension->addType("sensitive cylinder", "layer");
218  layerElement.addExtension<Acts::ActsExtension>(layerExtension);
219 
220  PlacedVolume placedLayer = barrelVolume.placeVolume(layerVolume);
221  placedLayer.addPhysVolID("layer", layerNum);
222 
223  // Assign layer DetElement to layer volume
224  layerElement.setPlacement(placedLayer);
225  }
226 
227  // Place the additional support cylinders per detector
228  buildSupportCylinder(oddd, barrelVolume, x_det, layerR);
229 
230  if (x_det.hasChild(_Unicode(services))) {
231  // Grab the services
232  xml_comp_t x_services = x_det.child(_Unicode(services));
233  if (x_services.hasChild(_Unicode(cable_routing))) {
234  xml_comp_t x_cable_routing = x_services.child(_Unicode(cable_routing));
235  buildBarrelRouting(oddd, barrelVolume, x_cable_routing, layerR);
236  }
237  if (x_services.hasChild(_Unicode(cooling_routing))) {
238  xml_comp_t x_cooling_routing =
239  x_services.child(_Unicode(cooling_routing));
240  buildBarrelRouting(oddd, barrelVolume, x_cooling_routing, layerR);
241  }
242  }
243 
244  // Place Volume
245  Volume motherVolume = oddd.pickMotherVolume(barrelDetector);
246  Position translation(0., 0., x_det_dim.z());
247  PlacedVolume placedBarrel =
248  motherVolume.placeVolume(barrelVolume, translation);
249  // "system" is hard coded in the DD4Hep::VolumeManager
250  placedBarrel.addPhysVolID("system", barrelDetector.id());
251  barrelDetector.setPlacement(placedBarrel);
252 
253  // And return the detector element
254  return barrelDetector;
255 }
256 
257 DECLARE_DETELEMENT(ODDPixelBarrel, create_element)