EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ODDPixelEndcap_geo.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ODDPixelEndcap_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 Ref_t create_element(Detector& oddd, xml_h xml, SensitiveDetector sens) {
20  xml_det_t x_det = xml;
21  string detName = x_det.nameStr();
22 
23  // Make DetElement
24  DetElement endcapDetector(detName, x_det.id());
25 
26  // Add Extension to DetElement for the RecoGeometry
27  Acts::ActsExtension* endcapExtension = new Acts::ActsExtension();
28  endcapExtension->addType("endcap", "detector");
29  // Add the volume boundary material if configured
30  for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) {
31  xml_comp_t x_boundary_material = bmat;
32  xmlToProtoSurfaceMaterial(x_boundary_material, *endcapExtension,
33  "boundary_material");
34  }
35  endcapDetector.addExtension<Acts::ActsExtension>(endcapExtension);
36  // Make Volume
37  dd4hep::xml::Dimension x_det_dim(x_det.dimensions());
38  string endcapShapeName = x_det_dim.nameStr();
39 
40  Tube endcapShape(x_det_dim.rmin(), x_det_dim.rmax(), x_det_dim.dz());
41  Volume endcapVolume(detName, endcapShape, oddd.air());
42  endcapVolume.setVisAttributes(oddd, x_det.visStr());
43 
44  // Place Volume
45  Volume motherVolume = oddd.pickMotherVolume(endcapDetector);
46  Position translation(0., 0., x_det_dim.z());
47  PlacedVolume placedEndcap =
48  motherVolume.placeVolume(endcapVolume, translation);
49 
50  // Create the module components
51  xml_comp_t x_module = x_det.child(_U(module));
52  double ylength = 0.;
53  auto module =
54  ODDModuleHelper::assembleRectangularModule(oddd, sens, x_module, ylength);
55 
56  Assembly diskAssembly("disk");
57 
58  // DetElement tree
59  DetElement diskElementTemplate("DiskElementTemplate", 0);
60 
61  // Loop over the rings to create a template disk
62  size_t ringNum = 0;
63  for (xml_coll_t ring(xml, _U(ring)); ring; ++ring, ++ringNum) {
64  // Get the ring
65  xml_comp_t x_ring = ring;
66 
67  // The ring name
68  string ringName = _toString((int)ringNum, "ring%d");
69  Assembly ringAssembly(ringName);
70  ringAssembly.setVisAttributes(oddd, x_ring.visStr());
71 
72  // DetElement tree
73  DetElement ringElement(ringName, ringNum);
74 
75  double r = x_ring.r();
76  double phi0 = x_ring.phi0();
77  unsigned int nModules = x_ring.nphi();
78  double zgap = x_ring.gap();
79  double phiStep = 2. * M_PI / nModules;
80 
81  // Loop over modules
82  for (unsigned int modNum = 0; modNum < nModules; ++modNum) {
83  // The module name
84  string moduleName = _toString((int)modNum, "module%d");
85  bool odd = bool(modNum % 2);
86  // Position it
87  double phi = phi0 + modNum * phiStep;
88  double z = odd ? -zgap : zgap;
89  Position trans(r * cos(phi), r * sin(phi), z);
90  // Place Module Box Volumes, flip if necessary
91  double flip = x_det_dim.z() < 0. ? M_PI : 0.;
92  if (ringNum != 0) {
93  flip += M_PI;
94  }
95  PlacedVolume placedModule = ringAssembly.placeVolume(
96  module.first,
97  Transform3D(RotationZ(phi + 1.5 * M_PI) * RotationY(flip), trans));
98  placedModule.addPhysVolID("module", modNum);
99  // Clone the detector element
100  auto moduleElement = module.second.clone(moduleName, modNum);
101  moduleElement.setPlacement(placedModule);
102  // Assign it as child to the stave template
103  ringElement.add(moduleElement);
104  }
105 
106  // Place Ring assembly into disk
107  PlacedVolume placedRing = diskAssembly.placeVolume(
108  ringAssembly, Position(0., 0., x_ring.z_offset()));
109  placedRing.addPhysVolID("ring", ringNum);
110  ringElement.setPlacement(placedRing);
111  // Add it to the Disk element template
112  diskElementTemplate.add(ringElement);
113  }
114 
115  xml_comp_t x_support = x_det.child(_Unicode(ring_support));
116  // The support shape
117  Tube supportShape(x_support.rmin(), x_support.rmax(), x_support.dz());
118  Volume supportVolume("DiskSupport", supportShape,
119  oddd.material(x_support.materialStr()));
120  supportVolume.setVisAttributes(oddd, x_support.visStr());
121  diskAssembly.placeVolume(supportVolume);
122 
123  // Cooling rings
124  buildCoolingRings(oddd, diskAssembly, x_det);
125 
126  // Loop over the layers and place the disk
127  size_t layNum = 0;
128  // Remember the layers for the service routing
129  std::vector<double> endcapZ;
130  for (xml_coll_t lay(xml, _U(layer)); lay; ++lay, ++layNum) {
131  // Get the layer
132  xml_comp_t x_layer = lay;
133 
134  // The Layer envelope volume
135  string layerName = detName + std::to_string(layNum);
136  Volume layerVolume(layerName,
137  Tube(x_layer.rmin(), x_layer.rmax(), x_layer.dz()),
138  oddd.air());
139 
140  layerVolume.setVisAttributes(oddd, x_layer.visStr());
141 
142  string diskElName = _toString((int)layNum, "disk%d");
143 
144  // The DetElement tree
145  DetElement layerElement(layerName, layNum);
146  auto diskElement = diskElementTemplate.clone(diskElName, layNum);
147 
148  // Place the disk into the layer
149  PlacedVolume placedDisk = layerVolume.placeVolume(diskAssembly);
150  diskElement.setPlacement(placedDisk);
151  layerElement.add(diskElement);
152 
153  // Place Ring assembly into disk
154  double zeff = x_layer.z_offset() - x_det_dim.z();
155  endcapZ.push_back(zeff);
156 
157  PlacedVolume placedLayer =
158  endcapVolume.placeVolume(layerVolume, Position(0., 0., zeff));
159  placedLayer.addPhysVolID("layer", layNum);
160 
161  // Place the layer with appropriate Acts::Extension
162  // Configure the ACTS extension
163  Acts::ActsExtension* layerExtension = new Acts::ActsExtension();
164  layerExtension->addType("sensitive disk", "layer");
165  layerElement.addExtension<Acts::ActsExtension>(layerExtension);
166  // Add the proto layer material
167  for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
168  xml_comp_t x_layer_material = lmat;
169  xmlToProtoSurfaceMaterial(x_layer_material, *layerExtension,
170  "layer_material");
171  } // Finish up the DetElement tree
172  layerElement.setPlacement(placedLayer);
173  endcapDetector.add(layerElement);
174  }
175 
176  // Close up the detector
177  if (x_det.hasChild(_U(disk))) {
178  // Endplate disk
179  xml_comp_t x_endplate = x_det.child(_U(disk));
180 
181  // The Shape and Volume
182  Tube endplateShape(x_endplate.rmin(), x_endplate.rmax(), x_endplate.dz());
183  Volume endplateVolume("Endplate", endplateShape,
184  oddd.material(x_endplate.materialStr()));
185  endplateVolume.setVisAttributes(oddd, x_endplate.visStr());
186 
187  double zeff = x_endplate.z_offset() - x_det_dim.z();
188  endcapZ.push_back(zeff);
189  PlacedVolume placedEndplate =
190  endcapVolume.placeVolume(endplateVolume, Position(0., 0., zeff));
191 
192  DetElement endplateElement("Endplate", 0);
193 
194  // Place the layer with appropriate Acts::Extension
195  // Configure the ACTS extension
196  Acts::ActsExtension* endplateExtension = new Acts::ActsExtension();
197  endplateExtension->addType("passive disk", "layer");
198  endplateElement.addExtension<Acts::ActsExtension>(endplateExtension);
199  // Add the proto layer material
200  for (xml_coll_t lmat(x_endplate, _Unicode(layer_material)); lmat; ++lmat) {
201  xml_comp_t x_layer_material = lmat;
202  xmlToProtoSurfaceMaterial(x_layer_material, *endplateExtension,
203  "layer_material");
204  }
205  // Finish up the DetElement tree
206  endplateElement.setPlacement(placedEndplate);
207  endcapDetector.add(endplateElement);
208  }
209 
210  if (x_det.hasChild(_Unicode(services))) {
211  // Grab the services
212  xml_comp_t x_services = x_det.child(_Unicode(services));
213  if (x_services.hasChild(_Unicode(cable_routing))) {
214  xml_comp_t x_cable_routing = x_services.child(_Unicode(cable_routing));
215  buildEndcapRouting(oddd, endcapVolume, x_cable_routing, endcapZ);
216  }
217  if (x_services.hasChild(_Unicode(cooling_routing))) {
218  xml_comp_t x_cooling_routing =
219  x_services.child(_Unicode(cooling_routing));
220  buildEndcapRouting(oddd, endcapVolume, x_cooling_routing, endcapZ);
221  }
222  }
223 
224  // Place the additional support cylinders per detector
225  std::vector<double> layerR;
226  buildSupportCylinder(oddd, endcapVolume, x_det, layerR);
227 
228  // "system" is hard coded in the DD4Hep::VolumeManager
229  placedEndcap.addPhysVolID("system", endcapDetector.id());
230  endcapDetector.setPlacement(placedEndcap);
231 
232  // And return it
233  return endcapDetector;
234 }
235 
236 DECLARE_DETELEMENT(ODDPixelEndcap, create_element)