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