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