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