ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ODDStripEndcap_geo.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ODDStripEndcap_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 
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  Assembly diskAssembly("Disk");
45 
46  // DetElement tree
47  DetElement diskElementTemplate("DiskElementTemplate", 0);
48 
49  // build the ring templates
50  size_t ringNum = 0;
51  for (xml_coll_t ring(x_det, _U(ring)); ring; ++ring, ++ringNum) {
52  xml_comp_t x_ring = ring;
53 
54  string ringName = "Ring" + std::to_string(ringNum);
55  Assembly ringAssembly(ringName);
56 
57  // DetElement tree
58  DetElement ringElement(ringName, ringNum);
59 
60  if (x_ring.hasChild(_U(module))) {
61  xml_comp_t x_module = x_ring.child(_U(module));
62  auto module =
63  ODDModuleHelper::assembleTrapezoidalModule(oddd, sens, x_module);
64 
65  // place the modules
66  unsigned int nPhi = x_ring.nphi();
67  double phiStep = 2 * M_PI / nPhi;
68  double phi0 = x_ring.phi0();
69  double r = x_ring.r();
70  double zgap = x_ring.gap();
71 
72  for (unsigned int modNum = 0; modNum < nPhi; ++modNum) {
73  // The module name
74  string moduleName = _toString((int)modNum, "module%d");
75 
76  bool odd = bool(modNum % 2);
77 
78  // Position parameters
79  double phi = phi0 + modNum * phiStep;
80  double x = r * cos(phi);
81  double y = r * sin(phi);
82  double z = odd ? -zgap : zgap;
83 
84  // Place Module Box Volumes, flip if necessary
85  Position trans(x, y, z);
86  double flip = odd ? M_PI : 0.;
87 
88  double angX = 0.5 * M_PI + flip;
89  double angY = odd ? 0.5 * M_PI - phi : 0.5 * M_PI + phi;
90 
91  PlacedVolume placedModule = ringAssembly.placeVolume(
92  module.first,
94  RotationX(angX) * RotationY(angY),
95  trans)); // RotationZ(phi + 1.5 * M_PI) * RotationY(flip)
96  placedModule.addPhysVolID("module", modNum);
97  // Clone the detector element
98  auto moduleElement = module.second.clone(moduleName, modNum);
99  moduleElement.setPlacement(placedModule);
100  // Assign it as child to the stave template
101  ringElement.add(moduleElement);
102  }
103 
104  // Now add the ring detector Element to the disk
105  diskElementTemplate.add(ringElement);
106 
107  size_t supportNum = 0;
108  for (xml_coll_t sup(x_ring, _U(support)); sup; ++sup, ++supportNum) {
109  xml_comp_t x_support = sup;
110  // Create the volume of the support structure
111  string supportName = _toString((int)supportNum, "RingSupport%d");
112  Volume supportVolume(
113  supportName,
114  Tube(x_support.rmin(), x_support.rmax(), x_support.dz()),
115  oddd.material(x_support.materialStr()));
116  supportVolume.setVisAttributes(oddd, x_support.visStr());
117  // Place the support structure
118  ringAssembly.placeVolume(supportVolume,
119  Position(0., 0., x_support.z_offset()));
120  }
121 
122  // Cooling rings
123  buildCoolingRings(oddd, ringAssembly, x_ring);
124 
125  PlacedVolume placedRing = diskAssembly.placeVolume(
126  ringAssembly, Position(0., 0., x_ring.z_offset()));
127 
128  placedRing.addPhysVolID("ring", ringNum);
129  ringElement.setPlacement(placedRing);
130  }
131  }
132 
133  // Loop over the layers and place the disk, remember the z positions
134  std::vector<double> endcapZ;
135  size_t layNum = 0;
136  for (xml_coll_t lay(xml, _U(layer)); lay; ++lay, ++layNum) {
137  xml_comp_t x_layer = lay;
138  // The Layer envelope volume
139  string layerName = detName + std::to_string(layNum);
140  Volume layerVolume(layerName,
141  Tube(x_layer.rmin(), x_layer.rmax(), x_layer.dz()),
142  oddd.air());
143 
144  layerVolume.setVisAttributes(oddd, x_layer.visStr());
145 
146  string diskElName = _toString((int)layNum, "disk%d");
147 
148  // The DetElement tree
149  DetElement layerElement(layerName, layNum);
150  auto diskElement = diskElementTemplate.clone(diskElName, layNum);
151 
152  // Place the disk into the layer
153  PlacedVolume placedDisk = layerVolume.placeVolume(diskAssembly);
154  diskElement.setPlacement(placedDisk);
155  layerElement.add(diskElement);
156 
157  // Place Ring assembly into disk
158  double zeff = x_layer.z_offset() - x_det_dim.z();
159  PlacedVolume placedLayer =
160  endcapVolume.placeVolume(layerVolume, Position(0., 0., zeff));
161  placedLayer.addPhysVolID("layer", layNum);
162  endcapZ.push_back(zeff);
163 
164  // Place the layer with appropriate Acts::Extension
165  // Configure the ACTS extension
166  Acts::ActsExtension* layerExtension = new Acts::ActsExtension();
167  layerExtension->addType("sensitive disk", "layer");
168  layerElement.addExtension<Acts::ActsExtension>(layerExtension);
169  // Add the proto layer material
170  for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
171  xml_comp_t x_layer_material = lmat;
172  xmlToProtoSurfaceMaterial(x_layer_material, *layerExtension,
173  "layer_material");
174  }
175  // Finish up the DetElement tree
176  layerElement.setPlacement(placedLayer);
177  endcapDetector.add(layerElement);
178  }
179 
180  if (x_det.hasChild(_Unicode(services))) {
181  // Grab the services - cables
182  xml_comp_t x_services = x_det.child(_Unicode(services));
183  for (xml_coll_t crout(x_services, _Unicode(cable_routing)); crout;
184  ++crout) {
185  xml_comp_t x_cable_routing = crout;
186  buildEndcapRouting(oddd, endcapVolume, x_cable_routing, endcapZ);
187  }
188  // Grab for services - cooling
189  for (xml_coll_t crout(x_services, _Unicode(cooling_routing)); crout;
190  ++crout) {
191  xml_comp_t x_cooling_routing = crout;
192  buildEndcapRouting(oddd, endcapVolume, x_cooling_routing, endcapZ);
193  }
194  }
195 
196  // Place Volume
197  Volume motherVolume = oddd.pickMotherVolume(endcapDetector);
198  Position translation(0., 0., x_det_dim.z());
199  PlacedVolume placedEndcap =
200  motherVolume.placeVolume(endcapVolume, translation);
201  // "system" is hard coded in the DD4Hep::VolumeManager
202  placedEndcap.addPhysVolID("system", endcapDetector.id());
203  endcapDetector.setPlacement(placedEndcap);
204 
205  // And return it
206  return endcapDetector;
207 }
208 
209 DECLARE_DETELEMENT(ODDStripEndcap, create_element)