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