EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylindricalTrackingGeometry.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylindricalTrackingGeometry.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 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 
9 #pragma once
10 
11 // Workaround for building on clang+libstdc++
13 
36 #include "Acts/Utilities/Units.hpp"
37 
38 #include <functional>
39 #include <vector>
40 
41 namespace Acts {
42 namespace Test {
43 
45  std::reference_wrapper<const GeometryContext> geoContext;
46 
49  std::reference_wrapper<const GeometryContext> gctx)
50  : geoContext(gctx) {}
51 
52  using DetectorStore = std::vector<std::unique_ptr<const DetectorElementStub>>;
53 
56 
71  std::vector<const Surface*> surfacesRing(
72  DetectorStore& detStore, double moduleHalfXminY, double moudleHalfXmaxY,
73  double moduleHalfY, double moduleThickness, double moduleTilt,
74  double ringRadius, double ringZ, double zStagger, int nPhi) {
75  std::vector<const Surface*> layerSurfaces;
76 
77  // Module material from input
78  MaterialSlab moduleMaterial(makeSilicon(), moduleThickness);
79 
80  // Create a new surface material
81  std::shared_ptr<const ISurfaceMaterial> moduleMaterialPtr =
82  std::shared_ptr<const ISurfaceMaterial>(
83  new Acts::HomogeneousSurfaceMaterial(moduleMaterial));
84 
85  // The rectangle/trapezoid bounds for all modules
86  std::shared_ptr<PlanarBounds> mBounds = nullptr;
87  if (moduleHalfXminY == moudleHalfXmaxY) {
88  mBounds = std::make_shared<RectangleBounds>(moduleHalfXminY, moduleHalfY);
89  } else {
90  mBounds = std::make_shared<TrapezoidBounds>(moduleHalfXminY,
91  moudleHalfXmaxY, moduleHalfY);
92  }
93 
94  double phiStep = 2 * M_PI / nPhi;
95 
96  for (int im = 0; im < nPhi; ++im) {
97  // Get the moduleTransform
98  double phi = -M_PI + im * phiStep;
99  auto mModuleTransform = Transform3D(
100  Translation3D(ringRadius * std::cos(phi), ringRadius * std::sin(phi),
101  ringZ + (im % 2) * zStagger) *
102  AngleAxis3D(phi - 0.5 * M_PI, Vector3D::UnitZ()) *
103  AngleAxis3D(moduleTilt, Vector3D::UnitY()));
104 
105  // Create the detector element
106  auto detElement = std::make_unique<const DetectorElementStub>(
107  mModuleTransform, mBounds, moduleThickness, moduleMaterialPtr);
108 
109  layerSurfaces.push_back(&detElement->surface());
110  detStore.push_back(std::move(detElement));
111  }
112 
113  return layerSurfaces;
114  }
115 
129  std::vector<const Surface*> surfacesCylinder(
130  DetectorStore& detStore, double moduleHalfX, double moduleHalfY,
131  double moduleThickness, double moduleTiltPhi, double layerRadius,
132  double radialStagger, double longitudinalOverlap,
133  const std::pair<int, int>& binningSchema) {
134  std::vector<const Surface*> layerSurfaces;
135 
136  // Module material from input
137  MaterialSlab moduleMaterial(makeSilicon(), moduleThickness);
138 
139  // Create a new surface material
140  std::shared_ptr<const ISurfaceMaterial> moduleMaterialPtr =
141  std::shared_ptr<const ISurfaceMaterial>(
142  new Acts::HomogeneousSurfaceMaterial(moduleMaterial));
143 
144  // The rectangle bounds for all modules
145  auto mBounds = std::make_shared<RectangleBounds>(moduleHalfX, moduleHalfY);
146 
147  // Create the module centers
148  auto moduleCenters =
149  modulePositionsCylinder(layerRadius, radialStagger, moduleHalfY,
150  longitudinalOverlap, binningSchema);
151 
152  for (auto& mCenter : moduleCenters) {
153  // The association transform
154  double modulePhi = VectorHelpers::phi(mCenter);
155  // Local z axis is the normal vector
156  Vector3D moduleLocalZ(cos(modulePhi + moduleTiltPhi),
157  sin(modulePhi + moduleTiltPhi), 0.);
158  // Local y axis is the global z axis
159  Vector3D moduleLocalY(0., 0., 1);
160  // Local x axis the normal to local y,z
161  Vector3D moduleLocalX(-sin(modulePhi + moduleTiltPhi),
162  cos(modulePhi + moduleTiltPhi), 0.);
163  // Create the RotationMatrix
164  RotationMatrix3D moduleRotation;
165  moduleRotation.col(0) = moduleLocalX;
166  moduleRotation.col(1) = moduleLocalY;
167  moduleRotation.col(2) = moduleLocalZ;
168  // Get the moduleTransform
169  auto mModuleTransform =
170  Transform3D(Translation3D(mCenter) * moduleRotation);
171  // Create the detector element
172  auto detElement = std::make_unique<const DetectorElementStub>(
173  mModuleTransform, mBounds, moduleThickness, moduleMaterialPtr);
174 
175  layerSurfaces.push_back(&detElement->surface());
176  detStore.push_back(std::move(detElement));
177  }
178  return layerSurfaces;
179  }
180 
183  std::vector<Vector3D> modulePositionsCylinder(
184  double radius, double zStagger, double moduleHalfLength, double lOverlap,
185  const std::pair<int, int>& binningSchema) {
186  int nPhiBins = binningSchema.first;
187  int nZbins = binningSchema.second;
188  // prepare the return value
189  std::vector<Vector3D> mPositions;
190  mPositions.reserve(nPhiBins * nZbins);
191  // prep work
192  double phiStep = 2 * M_PI / (nPhiBins);
193  double minPhi = -M_PI + 0.5 * phiStep;
194  double zStart = -0.5 * (nZbins - 1) * (2 * moduleHalfLength - lOverlap);
195  double zStep = 2 * std::abs(zStart) / (nZbins - 1);
196  // loop over the bins
197  for (size_t zBin = 0; zBin < size_t(nZbins); ++zBin) {
198  // prepare z and r
199  double moduleZ = zStart + zBin * zStep;
200  double moduleR =
201  (zBin % 2) != 0u ? radius - 0.5 * zStagger : radius + 0.5 * zStagger;
202  for (size_t phiBin = 0; phiBin < size_t(nPhiBins); ++phiBin) {
203  // calculate the current phi value
204  double modulePhi = minPhi + phiBin * phiStep;
205  mPositions.push_back(Vector3D(moduleR * cos(modulePhi),
206  moduleR * sin(modulePhi), moduleZ));
207  }
208  }
209  return mPositions;
210  }
211 
212  // @brief Call operator for the creation method of the tracking geometry
213  std::shared_ptr<const TrackingGeometry> operator()() {
214  using namespace Acts::UnitLiterals;
215 
216  Logging::Level surfaceLLevel = Logging::INFO;
217  Logging::Level layerLLevel = Logging::INFO;
218  Logging::Level volumeLLevel = Logging::INFO;
219 
220  // configure surface array creator
221  auto surfaceArrayCreator = std::make_shared<const SurfaceArrayCreator>(
222  getDefaultLogger("SurfaceArrayCreator", surfaceLLevel));
223  // configure the layer creator that uses the surface array creator
224  LayerCreator::Config lcConfig;
225  lcConfig.surfaceArrayCreator = surfaceArrayCreator;
226  auto layerCreator = std::make_shared<const LayerCreator>(
227  lcConfig, getDefaultLogger("LayerCreator", layerLLevel));
228  // configure the layer array creator
229  LayerArrayCreator::Config lacConfig;
230  auto layerArrayCreator = std::make_shared<const LayerArrayCreator>(
231  lacConfig, getDefaultLogger("LayerArrayCreator", layerLLevel));
232 
233  // tracking volume array creator
235  auto tVolumeArrayCreator =
236  std::make_shared<const TrackingVolumeArrayCreator>(
237  tvacConfig,
238  getDefaultLogger("TrackingVolumeArrayCreator", volumeLLevel));
239  // configure the cylinder volume helper
241  cvhConfig.layerArrayCreator = layerArrayCreator;
242  cvhConfig.trackingVolumeArrayCreator = tVolumeArrayCreator;
243  auto cylinderVolumeHelper = std::make_shared<const CylinderVolumeHelper>(
244  cvhConfig, getDefaultLogger("CylinderVolumeHelper", volumeLLevel));
245 
246  // ----------------- build a beam pipe -----------------------------------
247  MaterialSlab beamPipeMaterial(makeBeryllium(), 0.8_mm);
248  PassiveLayerBuilder::Config bplConfig;
249  bplConfig.layerIdentification = "BeamPipe";
250  bplConfig.centralLayerRadii = std::vector<double>(1, 19.);
251  bplConfig.centralLayerHalflengthZ = std::vector<double>(1, 1000.);
252  bplConfig.centralLayerThickness = std::vector<double>(1, 0.8);
253  bplConfig.centralLayerMaterial = {
254  std::make_shared<const HomogeneousSurfaceMaterial>(beamPipeMaterial)};
255  auto beamPipeBuilder = std::make_shared<const PassiveLayerBuilder>(
256  bplConfig, getDefaultLogger("BeamPipeLayerBuilder", layerLLevel));
257  // create the volume for the beam pipe
259  bpvConfig.trackingVolumeHelper = cylinderVolumeHelper;
260  bpvConfig.volumeName = "BeamPipe";
261  bpvConfig.layerBuilder = beamPipeBuilder;
262  bpvConfig.layerEnvelopeR = {1_mm, 1_mm};
263  bpvConfig.buildToRadiusZero = true;
264  bpvConfig.volumeSignature = 0;
265  auto beamPipeVolumeBuilder = std::make_shared<const CylinderVolumeBuilder>(
266  bpvConfig, getDefaultLogger("BeamPipeVolumeBuilder", volumeLLevel));
267 
268  // create the bounds and the volume
269  auto beamPipeBounds =
270  std::make_shared<const CylinderVolumeBounds>(0., 25., 1100.);
271  auto beamPipeVolume = beamPipeVolumeBuilder->trackingVolume(
272  geoContext, nullptr, beamPipeBounds);
273 
274  //-------------------------------------------------------------------------------------
275  // some prep work for the material
276  // Layer material properties - thickness, X0, L0, A, Z, Rho
277  MaterialSlab lProperties(makeSilicon(), 1.5_mm);
278 
279  std::shared_ptr<const ISurfaceMaterial> layerMaterialPtr =
280  std::shared_ptr<const ISurfaceMaterial>(
281  new Acts::HomogeneousSurfaceMaterial(lProperties));
282 
283  std::vector<double> pLayerRadii = {32., 72., 116., 172.};
284  std::vector<std::pair<int, int>> pLayerBinning = {
285  {16, 14}, {32, 14}, {52, 14}, {78, 14}};
286  std::vector<double> pModuleTiltPhi = {0.145, 0.145, 0.145, 0.145};
287  std::vector<double> pModuleHalfX = {8.4, 8.4, 8.4, 8.4};
288  std::vector<double> pModuleHalfY = {36., 36., 36., 36.};
289  std::vector<double> pModuleThickness = {0.15, 0.15, 0.15, 0.15};
290 
291  std::vector<LayerPtr> pLayers;
292 
293  for (size_t ilp = 0; ilp < pLayerRadii.size(); ++ilp) {
294  std::vector<const Surface*> layerSurfaces =
295  surfacesCylinder(detectorStore, pModuleHalfX[ilp], pModuleHalfY[ilp],
296  pModuleThickness[ilp], pModuleTiltPhi[ilp],
297  pLayerRadii[ilp], 2_mm, 5_mm, pLayerBinning[ilp]);
298 
299  // Make a shared version out of it
300  std::vector<std::shared_ptr<const Surface>> layerSurfacePtrs;
301  layerSurfacePtrs.reserve(layerSurfaces.size());
302  for (auto& sf : layerSurfaces) {
303  layerSurfacePtrs.push_back(sf->getSharedPtr());
304  }
305 
306  // create the layer and store it
307  ProtoLayer protoLayer(geoContext, layerSurfaces);
308  protoLayer.envelope[binR] = {0.5, 0.5};
309  auto pLayer = layerCreator->cylinderLayer(
310  geoContext, std::move(layerSurfacePtrs), pLayerBinning[ilp].first,
311  pLayerBinning[ilp].second, protoLayer);
312  auto approachSurfaces = pLayer->approachDescriptor()->containedSurfaces();
313  auto mutableOuterSurface =
314  const_cast<Acts::Surface*>(approachSurfaces.at(1));
315  mutableOuterSurface->assignSurfaceMaterial(layerMaterialPtr);
317  pLayers.push_back(pLayer);
318 
319  } // loop over layers
320 
321  // layer array
322  auto pLayerArray = layerArrayCreator->layerArray(geoContext, pLayers, 25.,
323  300., arbitrary, binR);
324  auto pVolumeBounds =
325  std::make_shared<const CylinderVolumeBounds>(25., 300., 1100.);
326  // create the Tracking volume
327  auto pVolume = TrackingVolume::create(
328  Transform3D::Identity(), pVolumeBounds, nullptr, std::move(pLayerArray),
329  nullptr, {}, "Pixel::Barrel");
330 
331  // The combined volume
332  auto detectorVolume = cylinderVolumeHelper->createContainerTrackingVolume(
333  geoContext, {beamPipeVolume, pVolume});
334 
335  // create and return the geometry
336  return std::make_shared<const TrackingGeometry>(detectorVolume);
337  }
338 };
339 
340 } // namespace Test
341 } // namespace Acts