ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ODDStripBarrel_geo.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ODDStripBarrel_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 Ref_t create_element(Detector& oddd, xml_h xml, SensitiveDetector sens) {
19  xml_det_t x_det = xml;
20  string detName = x_det.nameStr();
21 
22  // Make DetElement
23  DetElement barrelDetector(detName, x_det.id());
24 
25  // Add Extension to DetElement for the RecoGeometry
26  Acts::ActsExtension* barrelExtension = new Acts::ActsExtension();
27  barrelExtension->addType("barrel", "detector");
28  // Add the volume boundary material if configured
29  for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) {
30  xml_comp_t x_boundary_material = bmat;
31  xmlToProtoSurfaceMaterial(x_boundary_material, *barrelExtension,
32  "boundary_material");
33  }
34  barrelDetector.addExtension<Acts::ActsExtension>(barrelExtension);
35 
36  // Make Volume
37  dd4hep::xml::Dimension x_det_dim(x_det.dimensions());
38  string barrelShapeName = x_det_dim.nameStr();
39 
40  Tube barrelShape(x_det_dim.rmin(), x_det_dim.rmax(), x_det_dim.dz());
41  Volume barrelVolume(detName, barrelShape, oddd.air());
42  barrelVolume.setVisAttributes(oddd, x_det.visStr());
43 
44  // Create the stave volume and DetElement tree
45  xml_comp_t x_stave = x_det.child(_U(stave));
46  Assembly staveAssembly("stave");
47  // Visualization
48  staveAssembly.setVisAttributes(oddd, x_stave.visStr());
49  // DetElement tree
50  DetElement staveElementTemplate("StaveElementTemplate", 0);
51 
52  // Build a template module for the Barrel
53  xml_comp_t x_module = x_det.child(_U(module));
54  double length = 0.;
55  auto module =
56  ODDModuleHelper::assembleRectangularModule(oddd, sens, x_module, length);
57 
58  // Place the modules into the stave
59  double gap = x_stave.gap();
60  unsigned int nModules = x_stave.nmodules();
61  double ystep = length + gap;
62  double ymin = (nModules * 0.5 - 0.5) * length;
63  double staveHlength = ymin + 0.5 * length;
64 
65  // Loop over the modules and place them in the stave
66  for (unsigned int moduleNum = 0; moduleNum < nModules; ++moduleNum) {
67  double positionY = -ymin + moduleNum * ystep;
68  // Place the cable bundle, one per stave
69  if (x_stave.hasChild(_U(eltube))) {
70  // Retrieve cable parameters
71  xml_comp_t x_cable = x_stave.child(_U(eltube));
72 
73  double rMin = x_cable.rmin();
74  double rMax = x_cable.rmax();
75 
76  // For an odd number of modules this will create an asymmetric powering
77  // (as it should)
78  double rStep = (rMax - rMin) / (0.5 * nModules);
79  double rCable = rMin + abs(moduleNum - 0.5 * nModules) * rStep;
80 
81  Tube cable(0., rCable, 0.495 * ystep);
82  // Create the scable volume
83  Volume cableVolume("Cable", cable, oddd.material(x_cable.materialStr()));
84  cableVolume.setVisAttributes(oddd, x_cable.visStr());
85 
86  // Place the pipe in the stave
87  staveAssembly.placeVolume(
88  cableVolume, Transform3D(RotationX(0.5 * M_PI),
89  Position(x_cable.x_offset(), positionY,
90  x_cable.z_offset())));
91  }
92 
93  // Place them along local y
94  PlacedVolume placedModule =
95  staveAssembly.placeVolume(module.first, Position(0., positionY, 0.));
96  placedModule.addPhysVolID("module", moduleNum);
97 
98  string moduleName = _toString((int)moduleNum, "module%d");
99  // Clone the detector element
100  auto moduleElement = module.second.clone(moduleName, moduleNum);
101  moduleElement.setPlacement(placedModule);
102  // Assign it as child to the stave template
103  staveElementTemplate.add(moduleElement);
104  }
105 
106  // Remember the layer radii
107  std::vector<double> layerR;
108 
109  // Loop over the layers to build staves
110  size_t layerNum = 0;
111  for (xml_coll_t lay(xml, _U(layer)); lay; ++lay, ++layerNum) {
112  xml_comp_t x_layer = lay;
113 
114  string layerName = detName + std::to_string(layerNum);
115  // The Module envelope volume
116  Volume layerVolume(
117  layerName,
118  Tube(x_layer.rmin(), x_layer.rmax(), staveHlength + x_layer.outer_z()),
119  oddd.air());
120  // Visualization
121  layerVolume.setVisAttributes(oddd, x_layer.visStr());
122 
123  // The DetElement tree, keep it flat
124  DetElement layerElement(barrelDetector, layerName, layerNum);
125 
126  // Place the staves in the layer
127  unsigned int nStaves = x_layer.nphi();
128  double phiStep = 2. * M_PI / nStaves;
129  double phiTilt = x_layer.phi_tilt();
130  double phi0 = x_layer.phi0();
131  double r = x_layer.r();
132  layerR.push_back(r);
133 
134  // Loop over the staves and place them
135  for (unsigned int staveNum = 0; staveNum < nStaves; ++staveNum) {
136  string staveName = _toString((int)staveNum, "stave%d");
137  // position of the stave
138  double phi = phi0 + staveNum * phiStep;
139  double x = r * cos(phi);
140  double y = r * sin(phi);
141  // Now place the stave
142  PlacedVolume placedStave = layerVolume.placeVolume(
143  staveAssembly,
144  Transform3D(RotationY(0.5 * M_PI) * RotationZ(0.5 * M_PI) *
145  RotationY(phi + phiTilt),
146  Position(x, y, 0.)));
147  placedStave.addPhysVolID("stave", staveNum);
148 
149  // Clone the stave element from the template
150  DetElement staveElement = staveElementTemplate.clone(staveName, staveNum);
151  staveElement.setPlacement(placedStave);
152  // Add to the layer element
153  layerElement.add(staveElement);
154  }
155 
156  // Place the support cylinder
157  std::vector<double> dummyR;
158  buildSupportCylinder(oddd, barrelVolume, x_layer, dummyR);
159 
160  // Place the layer with appropriate Acts::Extension
161  // Configure the ACTS extension
162  Acts::ActsExtension* layerExtension = new Acts::ActsExtension();
163  layerExtension->addType("sensitive cylinder", "layer");
164  layerElement.addExtension<Acts::ActsExtension>(layerExtension);
165  // Add the proto layer material
166  for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
167  xml_comp_t x_layer_material = lmat;
168  xmlToProtoSurfaceMaterial(x_layer_material, *layerExtension,
169  "layer_material");
170  }
171  PlacedVolume placedLayer = barrelVolume.placeVolume(layerVolume);
172  placedLayer.addPhysVolID("layer", layerNum);
173 
174  // Assign layer DetElement to layer volume
175  layerElement.setPlacement(placedLayer);
176 
177  } // loop over layers
178 
179  // Place the support rails
180  buildSupportCylinder(oddd, barrelVolume, x_det, layerR);
181 
182  // Route the services out on both sides
183  if (x_det.hasChild(_Unicode(services))) {
184  // Grab the services
185  xml_comp_t x_services = x_det.child(_Unicode(services));
186  if (x_services.hasChild(_Unicode(cable_routing))) {
187  xml_comp_t x_cable_routing = x_services.child(_Unicode(cable_routing));
188  buildBarrelRouting(oddd, barrelVolume, x_cable_routing, layerR);
189  }
190  if (x_services.hasChild(_Unicode(cooling_routing))) {
191  xml_comp_t x_cooling_routing =
192  x_services.child(_Unicode(cooling_routing));
193  buildBarrelRouting(oddd, barrelVolume, x_cooling_routing, layerR);
194  }
195  }
196 
197  // Place Volume
198  Volume motherVolume = oddd.pickMotherVolume(barrelDetector);
199  Position translation(0., 0., x_det_dim.z());
200  PlacedVolume placedBarrel =
201  motherVolume.placeVolume(barrelVolume, translation);
202  // "system" is hard coded in the DD4Hep::VolumeManager
203  placedBarrel.addPhysVolID("system", barrelDetector.id());
204  barrelDetector.setPlacement(placedBarrel);
205 
206  // And return it
207  return barrelDetector;
208 }
209 
210 DECLARE_DETELEMENT(ODDStripBarrel, create_element)