ATLAS Offline Software
CaloTrackingGeometryBuilderImpl.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Calo
7 // Trk
15 //
18 #include "TrkGeometry/DiscLayer.h"
24 //
25 #include "TrkSurfaces/DiscBounds.h"
30 //
31 #include <memory>
32 //
34 #include "GaudiKernel/SystemOfUnits.h"
35 
36 // constructor
38  const std::string& t, const std::string& n, const IInterface* p)
39  : AthAlgTool(t, n, p) {
40 }
41 
42 // destructor
44 
45 // Athena standard methods
46 // initialize
48 
49  // Retrieve the tracking volume array creator
50  // -------------------------------------------------
51  if (m_trackingVolumeArrayCreator.retrieve().isFailure()) {
52  ATH_MSG_FATAL("Failed to retrieve tool " << m_trackingVolumeArrayCreator);
53  return StatusCode::FAILURE;
54  } else
55  ATH_MSG_INFO("Retrieved tool " << m_trackingVolumeArrayCreator);
56 
57  // Retrieve the tracking volume helper
58  // -------------------------------------------------
59  if (m_trackingVolumeHelper.retrieve().isFailure()) {
60  ATH_MSG_FATAL("Failed to retrieve tool " << m_trackingVolumeHelper);
61  return StatusCode::FAILURE;
62  } else
63  ATH_MSG_INFO("Retrieved tool " << m_trackingVolumeHelper);
64 
65  // Retrieve the second volume creator
66  if (m_buildMBTS && m_trackingVolumeCreator.retrieve().isFailure()) {
67  ATH_MSG_FATAL("Failed to retrieve tool " << m_trackingVolumeCreator);
68  return StatusCode::FAILURE;
69  } else
70  ATH_MSG_INFO("Retrieved tool " << m_trackingVolumeCreator);
71 
72  // Retrieve the volume builders
73 
74  // Retrieve the tracking volume array creator
75  // -------------------------------------------------
76  if (m_lArVolumeBuilder.retrieve().isFailure()) {
77  ATH_MSG_FATAL("Failed to retrieve tool " << m_lArVolumeBuilder);
78  return StatusCode::FAILURE;
79  } else
80  ATH_MSG_INFO("Retrieved tool " << m_lArVolumeBuilder);
81 
82  // Retrieve the tracking volume helper
83  // -------------------------------------------------
84  if (m_tileVolumeBuilder.retrieve().isFailure()) {
85  ATH_MSG_FATAL("Failed to retrieve tool " << m_tileVolumeBuilder);
86  return StatusCode::FAILURE;
87  } else
88  ATH_MSG_INFO("Retrieved tool " << m_tileVolumeBuilder);
89 
90  ATH_MSG_INFO("initialize() succesful");
91 
92  return StatusCode::SUCCESS;
93 }
94 
95 std::unique_ptr<Trk::TrackingGeometry>
97  Trk::TrackingVolume* innerVol, const CaloDetDescrManager* caloDDM) const {
98 
99  ATH_MSG_VERBOSE("Starting to build CaloTrackingGeometry ...");
100 
101  Trk::TrackingVolume* calorimeter = nullptr;
102 
103  // the key dimensions
104  RZPairVector keyDim;
105 
106  // the enclosed input volume (ID)
107  double enclosedInnerSectorHalflength = 0.;
108  double enclosedInnerSectorRadius = 0.;
109 
110  // dummy objects
111  Trk::LayerArray* dummyLayers = nullptr;
112  Trk::TrackingVolumeArray* dummyVolumes = nullptr;
113 
114  if (innerVol) {
115  ATH_MSG_VERBOSE("Got Inner Detector Volume: " << innerVol->volumeName());
116  innerVol->screenDump(msg(MSG::VERBOSE));
117 
118  // retrieve dimensions
119  const Trk::CylinderVolumeBounds* innerDetectorBounds =
120  dynamic_cast<const Trk::CylinderVolumeBounds*>(
121  &(innerVol->volumeBounds()));
122  if (!innerDetectorBounds)
123  std::abort();
124 
125  enclosedInnerSectorHalflength = innerDetectorBounds->halflengthZ();
126  enclosedInnerSectorRadius = innerDetectorBounds->outerRadius();
127 
128  keyDim.emplace_back(enclosedInnerSectorRadius, enclosedInnerSectorHalflength);
129  }
130  // get the dimensions from the envelope service
131  const RZPairVector& envelopeDefsIn =
132  m_enclosingEnvelopeSvc->getCaloRZBoundary();
133 
134  // find the max,max pair
135  unsigned int ii = 0;
136  for (unsigned int i = 0; i < envelopeDefsIn.size(); i++) {
137  if (envelopeDefsIn[i].second > envelopeDefsIn[ii].second)
138  ii = i;
139  else if (envelopeDefsIn[i].second == envelopeDefsIn[ii].second &&
140  envelopeDefsIn[i].first > envelopeDefsIn[ii].first)
141  ii = i;
142  }
143 
144  // find the sense of rotation
145  int irot = 1;
146  unsigned int inext = ii + 1;
147  if (inext == envelopeDefsIn.size())
148  inext = 0;
149  if (envelopeDefsIn[inext].second != envelopeDefsIn[ii].second) {
150  irot = -1;
151  inext = ii > 0 ? ii - 1 : envelopeDefsIn.size() - 1;
152  }
153 
154  // fill starting with upper low edge, end with upper high edge
155  RZPairVector envelopeDefs;
156  if (irot > 0) {
157  for (unsigned int i = inext; i < envelopeDefsIn.size(); i++)
158  envelopeDefs.push_back(envelopeDefsIn[i]);
159  if (inext > 0)
160  for (unsigned int i = 0; i <= inext - 1; i++)
161  envelopeDefs.push_back(envelopeDefsIn[i]);
162  } else {
163  int i = inext;
164  while (i >= 0) {
165  envelopeDefs.push_back(envelopeDefsIn[i]);
166  i = i - 1;
167  };
168  inext = envelopeDefsIn.size() - 1;
169  while (inext >= ii) {
170  envelopeDefs.push_back(envelopeDefsIn[inext]);
171  inext = inext - 1;
172  };
173  }
174 
175  double envEnclosingVolumeHalfZ = m_caloDefaultHalflengthZ;
176 
177  ATH_MSG_VERBOSE("Calo envelope definition retrieved:");
178  RZPairVector msCutouts;
179  for (unsigned int i = 0; i < envelopeDefs.size(); i++) {
180  ATH_MSG_VERBOSE("Rz pair:" << i << ":" << envelopeDefs[i].first << ","
181  << envelopeDefs[i].second);
182  if (std::abs(envelopeDefs[i].second) < envEnclosingVolumeHalfZ)
183  envEnclosingVolumeHalfZ = std::abs(envelopeDefs[i].second);
184  // ID dimensions : pick 1100 < R < 1200
185  if (envelopeDefs[i].first > 1100. && envelopeDefs[i].first < 1200. &&
186  envelopeDefs[i].second > 0.) {
187  // check that radial size of ID envelope fits
188  if (enclosedInnerSectorRadius != envelopeDefs[i].first)
189  ATH_MSG_INFO(
190  "Enclosed ID volume radius does not match ID envelope, adjusting "
191  "Calo.");
192  envEnclosingVolumeHalfZ = envelopeDefs[i].second;
193  if (!innerVol) {
194  enclosedInnerSectorRadius = envelopeDefs[i].first;
195  enclosedInnerSectorHalflength = envelopeDefs[i].second;
196  }
197  }
198  // collect outer cutouts, process those with |z| < 6785.mm ( this cut should
199  // be synchronized with MS default size,
200  // MS builder would crash for a longer input volume )
201  if (envelopeDefs[i].second > 0. && envelopeDefs[i].second < 6785. &&
202  (envelopeDefs[i].first > 1200. ||
203  envelopeDefs[i].second > envEnclosingVolumeHalfZ)) {
204  if (msCutouts.empty())
205  msCutouts.push_back(envelopeDefs[i]);
206  else {
207  RZPairVector::iterator envIter = msCutouts.begin();
208  while (envIter != msCutouts.end() &&
209  (*envIter).second < envelopeDefs[i].second)
210  ++envIter;
211  while (envIter != msCutouts.end() &&
212  (*envIter).second == envelopeDefs[i].second &&
213  (*envIter).first > envelopeDefs[i].first)
214  ++envIter;
215  msCutouts.insert(envIter, envelopeDefs[i]);
216  }
217  }
218  // end outer (MS) cutouts
219  }
220  if (msgLvl(MSG::VERBOSE)) {
221  for (unsigned int i = 0; i < msCutouts.size(); i++)
222  ATH_MSG_VERBOSE("MS cutouts to be processed by Calo:"
223  << i << ":" << msCutouts[i].first << ","
224  << msCutouts[i].second);
225  }
226 
227  // first member of msCutouts redefines the default central cylinder dimension
228  double caloDefaultRadius = m_caloDefaultRadius;
229  double caloDefaultHalflengthZ = m_caloDefaultHalflengthZ;
230 
231  if (!msCutouts.empty()) {
232  caloDefaultRadius = msCutouts[0].first;
233  caloDefaultHalflengthZ = msCutouts[0].second;
235  " Calo central cylinder dimensions adjusted using EnvelopeSvc:"
236  << m_caloDefaultRadius << "," << m_caloDefaultHalflengthZ);
237  }
238 
239  // create dummy ID if not built already
240 
241  if (!innerVol) {
243  enclosedInnerSectorRadius, enclosedInnerSectorHalflength);
244 
245  Amg::Transform3D* idTr = new Amg::Transform3D(Trk::s_idTransform);
246 
247  innerVol =
248  new Trk::TrackingVolume(idTr, idBounds, m_caloMaterial, dummyLayers,
249  dummyVolumes, "Calo::GapVolumes::DummyID");
250 
251  keyDim.emplace_back(enclosedInnerSectorRadius, enclosedInnerSectorHalflength);
252  }
253 
254  // BEAM PIPE
255  const RZPairVector& bpDefs = m_enclosingEnvelopeSvc->getBeamPipeRZBoundary();
256 
257  ATH_MSG_VERBOSE("BeamPipe envelope definition retrieved:");
258  RZPairVector bpCutouts;
259  for (unsigned int i = 0; i < bpDefs.size(); i++) {
260  ATH_MSG_VERBOSE("Rz pair:" << i << ":" << bpDefs[i].first << ","
261  << bpDefs[i].second);
262  // beam pipe within calo : pick 10. < R < 200; envEnclosingVolumeHalfZ =<
263  // z <= msCutouts.back().second;
264  if (bpDefs[i].first > 10. && bpDefs[i].first < 200. &&
265  bpDefs[i].second >= envEnclosingVolumeHalfZ &&
266  bpDefs[i].second <= msCutouts.back().second) {
267  bpCutouts.push_back(bpDefs[i]);
268  }
269  if (i > 0 && i < 4)
270  keyDim.push_back(bpDefs[i]);
271  }
272 
273  // no beam pipe within ID
274  // if (bpCutouts[0].second == envEnclosingVolumeHalfZ && bpCutouts[0].first >
275  // 0 ) bpCutouts[0].first=0.;
276  // last not needed
277  if (bpCutouts.size() > 1 &&
278  bpCutouts.back().second == bpCutouts[bpCutouts.size() - 2].second)
279  bpCutouts.erase(bpCutouts.end() - 1);
280  // end beam pipe envelope within Calo
281  for (unsigned int i = 0; i < bpCutouts.size(); i++)
282  ATH_MSG_VERBOSE("Beam pipe dimensions to be used by Calo:"
283  << i << ":" << bpCutouts[i].first << ","
284  << bpCutouts[i].second);
285 
286  keyDim.emplace_back(caloDefaultRadius, caloDefaultHalflengthZ);
287 
290 
291  // PART 1 : Liquid Argon Volumes
292  // ===========================================================================================
293  // get the Tracking Volumes from the LAr Builder
294  //
295  const std::vector<Trk::TrackingVolume*>* lArVolumes =
296  m_lArVolumeBuilder->trackingVolumes(*caloDDM);
297 
298  ATH_MSG_INFO(lArVolumes->size()
299  << " volumes retrieved from " << m_lArVolumeBuilder.name());
300 
301  // LAr Barrel part
302  Trk::TrackingVolume* solenoid = (*lArVolumes)[0];
303  Trk::TrackingVolume* solenoidlArPresamplerGap = (*lArVolumes)[1];
304  Trk::TrackingVolume* lArBarrelPresampler = (*lArVolumes)[2];
305  Trk::TrackingVolume* lArBarrel = (*lArVolumes)[3];
306 
307  // LAr Positive Endcap part
308  Trk::TrackingVolume* lArPositiveMBTS = (*lArVolumes)[4];
309  Trk::TrackingVolume* lArPositiveEndcap = (*lArVolumes)[5];
310  Trk::TrackingVolume* lArPositiveHec = (*lArVolumes)[6];
311  Trk::TrackingVolume* lArPositiveFcal = (*lArVolumes)[7];
312  Trk::TrackingVolume* lArPositiveHecFcalCover = (*lArVolumes)[8];
313  // LAr Negative Endcap part
314  Trk::TrackingVolume* lArNegativeMBTS = (*lArVolumes)[9];
315  Trk::TrackingVolume* lArNegativeEndcap = (*lArVolumes)[10];
316  Trk::TrackingVolume* lArNegativeHec = (*lArVolumes)[11];
317  Trk::TrackingVolume* lArNegativeFcal = (*lArVolumes)[12];
318  Trk::TrackingVolume* lArNegativeHecFcalCover = (*lArVolumes)[13];
319  Trk::TrackingVolume* lArPosECPresampler = (*lArVolumes)[14];
320  Trk::TrackingVolume* lArNegECPresampler = (*lArVolumes)[15];
321 
322  // PART 2 : Tile Volumes
323  // ===========================================================================================
324  // get the Tracking Volumes from the Tile Builder
325  std::vector<Trk::TrackingVolume*>* tileVolumes =
326  m_tileVolumeBuilder->trackingVolumes(*caloDDM);
327 
328  ATH_MSG_INFO(tileVolumes->size()
329  << " volumes retrieved from " << m_tileVolumeBuilder.name());
330  if (msgLvl(MSG::INFO)) {
331  ATH_MSG_INFO(
332  "--------------- detailed output "
333  "---------------------------------------------------------- ");
334  std::vector<Trk::TrackingVolume*>::const_iterator tileVolIter =
335  tileVolumes->begin();
336  std::vector<Trk::TrackingVolume*>::const_iterator tileVolIterEnd =
337  tileVolumes->end();
338  for (; tileVolIter != tileVolIterEnd;
339  (*tileVolIter)->screenDump(msg(MSG::VERBOSE)), ++tileVolIter)
340  ;
341  }
342 
343  // Tile Barrel part
344  Trk::TrackingVolume* tileCombined = (*tileVolumes)[0];
345  // Tile Positive Extended Part
346  Trk::TrackingVolume* tilePositiveExtendedBarrel = (*tileVolumes)[1];
347 
348  const Trk::CylinderVolumeBounds* ebBounds =
349  dynamic_cast<const Trk::CylinderVolumeBounds*>(
350  &(tilePositiveExtendedBarrel->volumeBounds()));
351 
352  double rTileMin = ebBounds ? ebBounds->innerRadius() : 2288.;
353  double zTileMin = ebBounds ? tilePositiveExtendedBarrel->center().z() -
354  ebBounds->halflengthZ()
355  : 3559.5;
356 
357  keyDim.emplace_back(rTileMin, zTileMin);
358  for (unsigned int i = 0; i < keyDim.size(); i++) {
359  ATH_MSG_VERBOSE("key dimensions:" << i << ":" << keyDim[i].first << ","
360  << keyDim[i].second);
361  }
362 
363  // The Bounds needed for the Gap Volume creation
364  const Trk::CylinderVolumeBounds* solenoidBounds =
365  dynamic_cast<const Trk::CylinderVolumeBounds*>(
366  &(solenoid->volumeBounds()));
367  if (!solenoidBounds)
368  std::abort();
369  const Trk::CylinderVolumeBounds* lArBarrelBounds =
370  dynamic_cast<const Trk::CylinderVolumeBounds*>(
371  &(lArBarrel->volumeBounds()));
372  if (!lArBarrelBounds)
373  std::abort();
374  const Trk::CylinderVolumeBounds* lArPositiveEndcapBounds =
375  dynamic_cast<const Trk::CylinderVolumeBounds*>(
376  &(lArPositiveEndcap->volumeBounds()));
377  if (!lArPositiveEndcapBounds)
378  std::abort();
379  const Trk::CylinderVolumeBounds* lArNegativeEndcapBounds =
380  dynamic_cast<const Trk::CylinderVolumeBounds*>(
381  &(lArNegativeEndcap->volumeBounds()));
382  if (!lArNegativeEndcapBounds)
383  std::abort();
384  const Trk::CylinderVolumeBounds* lArPositiveHecBounds =
385  dynamic_cast<const Trk::CylinderVolumeBounds*>(
386  &(lArPositiveHec->volumeBounds()));
387  if (!lArPositiveHecBounds)
388  std::abort();
389  const Trk::CylinderVolumeBounds* lArPositiveFcalBounds =
390  dynamic_cast<const Trk::CylinderVolumeBounds*>(
391  &(lArPositiveFcal->volumeBounds()));
392  if (!lArPositiveFcalBounds)
393  std::abort();
394  const Trk::CylinderVolumeBounds* lArNegativeFcalBounds =
395  dynamic_cast<const Trk::CylinderVolumeBounds*>(
396  &(lArNegativeFcal->volumeBounds()));
397  if (!lArNegativeFcalBounds)
398  std::abort();
399 
400  const Trk::CylinderVolumeBounds* tileCombinedBounds =
401  dynamic_cast<const Trk::CylinderVolumeBounds*>(
402  &(tileCombined->volumeBounds()));
403  if (!tileCombinedBounds)
404  std::abort();
405 
406  // Create the gap volumes
407  // ======================================================================
408  Trk::TrackingVolume* lArTileCentralSectorGap = nullptr;
409 
410  Trk::TrackingVolume* lArPositiveSectorInnerGap = nullptr;
411  Trk::TrackingVolume* lArPositiveSectorOuterGap = nullptr;
412  Trk::TrackingVolume* lArPositiveSectorOuterGap0 = nullptr;
413  Trk::TrackingVolume* lArCentralPositiveGap = nullptr;
414 
415  Trk::TrackingVolume* lArNegativeSectorInnerGap = nullptr;
416  Trk::TrackingVolume* lArNegativeSectorOuterGap = nullptr;
417  Trk::TrackingVolume* lArNegativeSectorOuterGap0 = nullptr;
418  Trk::TrackingVolume* lArCentralNegativeGap = nullptr;
419 
420  Trk::TrackingVolume* trtSolenoidGap = nullptr;
421 
422  double caloPositiveOuterBoundary = tileCombinedBounds->halflengthZ();
423 
424  double lArPositiveOuterBoundary = lArPositiveFcal->center().z();
425  lArPositiveOuterBoundary += lArPositiveFcalBounds->halflengthZ();
426 
427  // No. 1
428  // building dense volume here
429  Trk::Material tilePositiveSectorInnerGapMaterial =
430  Trk::Material(58., 565., 30.7, 14.6, 0.0025);
431 
432  // calo sensitive volume outer radius/z extent defined (for example) here
433  float caloVolsOuterRadius = tileCombinedBounds->outerRadius();
434  float caloVolsExtendZ = caloPositiveOuterBoundary;
435 
437  // LAr InnerGap sector + beam pipe
438 
439  Trk::Material lArSectorInnerGapMaterial =
440  Trk::Material(361., 1370., 14.5, 7., 0.0009); // ???
441 
442  // create beam pipe volumes for InnerGap/MBTS and return their outer radius
443  float rInnerGapBP = 0.;
444  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> innerGapBP =
445  createBeamPipeVolumes(
446  bpCutouts, keyDim[0].second,
447  // lArPositiveEndcap->center().z()-lArPositiveEndcapBounds->halflengthZ(),
448  keyDim.back().second, "InnerGap", rInnerGapBP);
449 
450  double z = 0.5 * (keyDim.back().second + keyDim[0].second);
451 
452  auto mbtsNegLayers = std::make_unique<std::vector<Trk::Layer*>>();
453  auto mbtsPosLayers = std::make_unique<std::vector<Trk::Layer*>>();
454 
455  if (lArPositiveMBTS && lArNegativeMBTS) {
456  // Disc
457  const Trk::CylinderVolumeBounds* mbtsBounds =
458  dynamic_cast<const Trk::CylinderVolumeBounds*>(
459  &(lArPositiveMBTS->volumeBounds()));
460  if (mbtsBounds && m_buildMBTS) {
461  float rmin = mbtsBounds->innerRadius();
462  float rmax = mbtsBounds->outerRadius();
463  // float d = mbtsBounds->halflengthZ();
464  Trk::DiscBounds* dibo = new Trk::DiscBounds(rmin, rmax);
465  // MBTS positions
466  Amg::Transform3D mbtsNegZpos =
467  Amg::Transform3D(Amg::Translation3D(lArNegativeMBTS->center()));
468  Amg::Transform3D mbtsPosZpos =
469  Amg::Transform3D(Amg::Translation3D(lArPositiveMBTS->center()));
470  // create the two Layers ( TODO: add trd surface subarray )
471  Trk::DiscLayer* mbtsNegLayer = new Trk::DiscLayer(
472  mbtsNegZpos, dibo,
473  // mbtsNegLayerSurfArray,
475  Trk::MaterialProperties(m_caloMaterial, 1.), 1.),
476  1.);
477  Trk::DiscLayer* mbtsPosLayer = new Trk::DiscLayer(
478  mbtsPosZpos, dibo->clone(),
479  // mbtsPosLayerSurfArray,
481  Trk::MaterialProperties(m_caloMaterial, 1.), 1.),
482  1. * Gaudi::Units::mm);
483 
484  mbtsNegLayers->push_back(mbtsNegLayer);
485  mbtsPosLayers->push_back(mbtsPosLayer);
486  }
487  }
488 
489  // building inner gap
491  rInnerGapBP,
492  // lArPositiveEndcapBounds->outerRadius(),
493  keyDim[0].first, 0.5 * (keyDim.back().second - keyDim[0].second));
494 
495  Amg::Transform3D* lArG1P =
497  lArPositiveSectorInnerGap = new Trk::TrackingVolume(
498  lArG1P, lArG1Bounds, lArSectorInnerGapMaterial, mbtsPosLayers.release(),
499  "Calo::GapVolumes::LAr::PositiveSectorInnerGap");
500 
501  Amg::Transform3D* lArG1N =
503  lArNegativeSectorInnerGap = new Trk::TrackingVolume(
504  lArG1N, lArG1Bounds->clone(), lArSectorInnerGapMaterial,
505  mbtsNegLayers.release(), "Calo::GapVolumes::LAr::NegativeSectorInnerGap");
506 
507  // glue InnerGap with beam pipe volumes
508  Trk::TrackingVolume* positiveInnerGap = nullptr;
509  if (innerGapBP.first) {
510  std::vector<Trk::TrackingVolume*> volsInnerGap;
511  volsInnerGap.push_back(innerGapBP.first);
512  volsInnerGap.push_back(lArPositiveSectorInnerGap);
513  positiveInnerGap = m_trackingVolumeCreator->createContainerTrackingVolume(
514  volsInnerGap, m_caloMaterial, "Calo::Container::PositiveInnerGap");
515  } else
516  positiveInnerGap = lArPositiveSectorInnerGap;
517 
518  Trk::TrackingVolume* negativeInnerGap = nullptr;
519  if (innerGapBP.second) {
520  std::vector<Trk::TrackingVolume*> volsInnerGap;
521  volsInnerGap.push_back(innerGapBP.second);
522  volsInnerGap.push_back(lArNegativeSectorInnerGap);
523  negativeInnerGap = m_trackingVolumeCreator->createContainerTrackingVolume(
524  volsInnerGap, m_caloMaterial, "Calo::Container::NegativeInnerGap");
525  } else
526  negativeInnerGap = lArNegativeSectorInnerGap;
527 
528  // glue MBTS volumes with ID
529  std::vector<Trk::TrackingVolume*> inBufferVolumes;
530  inBufferVolumes.push_back(negativeInnerGap);
531  inBufferVolumes.push_back(innerVol);
532  inBufferVolumes.push_back(positiveInnerGap);
533 
534  Trk::TrackingVolume* inDetEnclosed =
535  m_trackingVolumeCreator->createContainerTrackingVolume(
536  inBufferVolumes, m_caloMaterial,
537  "Calo::Container::EnclosedInnerDetector");
538 
539  ATH_MSG_DEBUG(" Inner detector enclosed (MBTS volumes)");
540 
542  // LAr endcap sector including the beam pipe
543  // create beam pipe volumes for Endcap and return their outer radius
544  float rEndcapBP = 0.;
545  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> endcapBP =
546  createBeamPipeVolumes(bpCutouts, keyDim.back().second,
547  lArPositiveEndcap->center().z() +
548  lArPositiveEndcapBounds->halflengthZ(),
549  "Endcap", rEndcapBP);
550 
551  // build lAr vessel around EC Presampler
552  const Trk::CylinderVolumeBounds* ecpBounds =
553  dynamic_cast<const Trk::CylinderVolumeBounds*>(
554  &(lArPosECPresampler->volumeBounds()));
555  if (!ecpBounds)
556  std::abort();
557 
558  float ecpHz = ecpBounds->halflengthZ();
559  float ecpRmin = ecpBounds->innerRadius();
560  float ecpRmax = ecpBounds->outerRadius();
561 
562  Amg::Transform3D* ecpPos =
563  new Amg::Transform3D(lArPosECPresampler->transform());
564  Amg::Transform3D* ecpNeg =
565  new Amg::Transform3D(lArNegECPresampler->transform());
566 
567  Trk::CylinderVolumeBounds* ecpUpBounds =
568  new Trk::CylinderVolumeBounds(ecpRmax, keyDim.back().first, ecpHz);
569  Trk::CylinderVolumeBounds* ecpDownBounds =
570  new Trk::CylinderVolumeBounds(rEndcapBP, ecpRmin, ecpHz);
571 
572  Trk::TrackingVolume* ecPresamplerCoverPos = new Trk::TrackingVolume(
573  ecpPos, ecpUpBounds, m_Al, dummyLayers, dummyVolumes,
574  "Calo::GapVolumes::LAr::PositiveECPresamplerCover");
575  Trk::TrackingVolume* ecPresamplerCoverNeg = new Trk::TrackingVolume(
576  ecpNeg, ecpUpBounds->clone(), m_Al, dummyLayers, dummyVolumes,
577  "Calo::GapVolumes::LAr::NegativeECPresamplerCover");
578  Trk::TrackingVolume* ecPresamplerInnerPos = new Trk::TrackingVolume(
579  new Amg::Transform3D(*ecpPos), ecpDownBounds, m_Al, dummyLayers,
580  dummyVolumes, "Calo::GapVolumes::LAr::PositiveECPresamplerInner");
581  Trk::TrackingVolume* ecPresamplerInnerNeg = new Trk::TrackingVolume(
582  new Amg::Transform3D(*ecpNeg), ecpDownBounds->clone(), m_Al, dummyLayers,
583  dummyVolumes, "Calo::GapVolumes::LAr::NegativeECPresamplerInner");
584 
585  // glue EC presampler radially
586  std::vector<Trk::TrackingVolume*> volsECP;
587  volsECP.push_back(ecPresamplerInnerPos);
588  volsECP.push_back(lArPosECPresampler);
589  volsECP.push_back(ecPresamplerCoverPos);
590  Trk::TrackingVolume* positiveECP =
591  m_trackingVolumeCreator->createContainerTrackingVolume(
592  volsECP, m_caloMaterial, "Calo::Container::PositiveECPresamplerR");
593  std::vector<Trk::TrackingVolume*> volsECN;
594  volsECN.push_back(ecPresamplerInnerNeg);
595  volsECN.push_back(lArNegECPresampler);
596  volsECN.push_back(ecPresamplerCoverNeg);
597  Trk::TrackingVolume* negativeECP =
598  m_trackingVolumeCreator->createContainerTrackingVolume(
599  volsECN, m_caloMaterial, "Calo::Container::NegativeECPresamplerR");
600 
601  // add surrounding buffers
602  z = lArPosECPresampler->center().z() - ecpHz;
603  float z1 = lArPosECPresampler->center().z() + ecpHz;
604  float z2 =
605  lArPositiveEndcap->center().z() - lArPositiveEndcapBounds->halflengthZ();
607  Amg::Vector3D(0., 0., 0.5 * (z + keyDim.back().second))));
609  Amg::Vector3D(0., 0., -0.5 * (z + keyDim.back().second))));
611  rEndcapBP, keyDim.back().first, 0.5 * (z - keyDim.back().second));
612  Amg::Transform3D* ecOPos = new Amg::Transform3D(
613  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (z1 + z2))));
614  Amg::Transform3D* ecONeg = new Amg::Transform3D(
615  Amg::Translation3D(Amg::Vector3D(0., 0., -0.5 * (z1 + z2))));
617  rEndcapBP, keyDim.back().first, 0.5 * (z2 - z1));
618 
619  Trk::TrackingVolume* ecPresamplerInPos = new Trk::TrackingVolume(
620  ecIPos, ecpIBounds, m_Ar, dummyLayers, dummyVolumes,
621  "Calo::GapVolumes::LAr::PositiveECPresamplerIn");
622  Trk::TrackingVolume* ecPresamplerInNeg = new Trk::TrackingVolume(
623  ecINeg, ecpIBounds->clone(), m_Ar, dummyLayers, dummyVolumes,
624  "Calo::GapVolumes::LAr::NegativeECPresamplerIn");
625  Trk::TrackingVolume* ecPresamplerOutPos = new Trk::TrackingVolume(
626  ecOPos, ecpOBounds, m_Ar, dummyLayers, dummyVolumes,
627  "Calo::GapVolumes::LAr::PositiveECPresamplerOut");
628  Trk::TrackingVolume* ecPresamplerOutNeg = new Trk::TrackingVolume(
629  ecONeg, ecpOBounds->clone(), m_Ar, dummyLayers, dummyVolumes,
630  "Calo::GapVolumes::LAr::NegativeECPresamplerOut");
631 
632  // glue EC presampler in z
633  std::vector<Trk::TrackingVolume*> volECP;
634  volECP.push_back(ecPresamplerInPos);
635  volECP.push_back(positiveECP);
636  volECP.push_back(ecPresamplerOutPos);
637  Trk::TrackingVolume* positiveEP =
638  m_trackingVolumeCreator->createContainerTrackingVolume(
639  volECP, m_caloMaterial, "Calo::Container::PositiveECPresampler");
640  std::vector<Trk::TrackingVolume*> volECN;
641  volECN.push_back(ecPresamplerOutNeg);
642  volECN.push_back(negativeECP);
643  volECN.push_back(ecPresamplerInNeg);
644  Trk::TrackingVolume* negativeEP =
645  m_trackingVolumeCreator->createContainerTrackingVolume(
646  volECN, m_caloMaterial, "Calo::Container::NegativeECPresampler");
647 
648  // build lAr vessel around EMEC
649  ecpHz = lArPositiveEndcapBounds->halflengthZ();
650  ecpRmin = lArPositiveEndcapBounds->innerRadius();
651  ecpRmax = lArPositiveEndcapBounds->outerRadius();
652 
653  Amg::Transform3D* ecPos =
654  new Amg::Transform3D(lArPositiveEndcap->transform());
655  Amg::Transform3D* ecNeg =
656  new Amg::Transform3D(lArNegativeEndcap->transform());
657 
658  Trk::CylinderVolumeBounds* ecUpBounds =
659  new Trk::CylinderVolumeBounds(ecpRmax, keyDim.back().first, ecpHz);
660  Trk::CylinderVolumeBounds* ecDownBounds =
661  new Trk::CylinderVolumeBounds(rEndcapBP, ecpRmin, ecpHz);
662 
663  Trk::TrackingVolume* ecCoverPos = new Trk::TrackingVolume(
664  ecPos, ecUpBounds, m_Ar, dummyLayers, dummyVolumes,
665  "Calo::GapVolumes::LAr::PositiveEndcapCover");
666  Trk::TrackingVolume* ecCoverNeg = new Trk::TrackingVolume(
667  ecNeg, ecUpBounds->clone(), m_Ar, dummyLayers, dummyVolumes,
668  "Calo::GapVolumes::LAr::NegativeEndcapCover");
669  Trk::TrackingVolume* ecInnerPos = new Trk::TrackingVolume(
670  new Amg::Transform3D(*ecPos), ecDownBounds, m_Al, dummyLayers,
671  dummyVolumes, "Calo::GapVolumes::LAr::PositiveEndcapInner");
672  Trk::TrackingVolume* ecInnerNeg = new Trk::TrackingVolume(
673  new Amg::Transform3D(*ecNeg), ecDownBounds->clone(), m_Al, dummyLayers,
674  dummyVolumes, "Calo::GapVolumes::LAr::NegativeEndcapInner");
675 
676  // glue EMEC radially
677  std::vector<Trk::TrackingVolume*> volsEC;
678  volsEC.push_back(ecInnerPos);
679  volsEC.push_back(lArPositiveEndcap);
680  volsEC.push_back(ecCoverPos);
681  Trk::TrackingVolume* positiveEC =
682  m_trackingVolumeCreator->createContainerTrackingVolume(
683  volsEC, m_caloMaterial, "Calo::Container::PositiveEndcapR");
684  std::vector<Trk::TrackingVolume*> volsEN;
685  volsEN.push_back(ecInnerNeg);
686  volsEN.push_back(lArNegativeEndcap);
687  volsEN.push_back(ecCoverNeg);
688  Trk::TrackingVolume* negativeEC =
689  m_trackingVolumeCreator->createContainerTrackingVolume(
690  volsEN, m_caloMaterial, "Calo::Container::NegativeEndcapR");
691 
692  // glue presampler with EMEC
693  std::vector<Trk::TrackingVolume*> volEEP;
694  volEEP.push_back(positiveEP);
695  volEEP.push_back(positiveEC);
696  Trk::TrackingVolume* positiveEEP =
697  m_trackingVolumeCreator->createContainerTrackingVolume(
698  volEEP, m_caloMaterial, "Calo::Container::PositiveEMEC");
699  std::vector<Trk::TrackingVolume*> volEEN;
700  volEEN.push_back(negativeEC);
701  volEEN.push_back(negativeEP);
702  Trk::TrackingVolume* negativeEEP =
703  m_trackingVolumeCreator->createContainerTrackingVolume(
704  volEEN, m_caloMaterial, "Calo::Container::NegativeEMEC");
705 
706  // glue EMEC sector with beam pipe volumes
707 
708  std::vector<Trk::TrackingVolume*> volsEndcapPos;
709  if (endcapBP.first)
710  volsEndcapPos.push_back(endcapBP.first);
711  volsEndcapPos.push_back(positiveEEP);
712 
713  std::unique_ptr<Trk::TrackingVolume> positiveEndcap(
714  m_trackingVolumeCreator->createContainerTrackingVolume(
715  volsEndcapPos, m_caloMaterial, "Calo::Container::PositiveEndcap"));
716 
717  std::vector<Trk::TrackingVolume*> volsEndcapNeg;
718  if (endcapBP.second)
719  volsEndcapNeg.push_back(endcapBP.second);
720  volsEndcapNeg.push_back(negativeEEP);
721 
722  std::unique_ptr<Trk::TrackingVolume> negativeEndcap(
723  m_trackingVolumeCreator->createContainerTrackingVolume(
724  volsEndcapNeg, m_caloMaterial, "Calo::Container::NegativeEndcap"));
725 
727  // Hec sector + beam pipe + lAr cover
728  // create beam pipe volumes for Hec and return their outer radius
729  float rHecBP = 0.;
730  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> hecBP =
731  createBeamPipeVolumes(
732  bpCutouts,
733  lArPositiveHec->center().z() - lArPositiveHecBounds->halflengthZ(),
734  lArPositiveHec->center().z() + lArPositiveHecBounds->halflengthZ(),
735  "Hec", rHecBP);
736  // HecInnerGap (new gap volume )
737  Trk::Material lArHecInnerGapMaterial =
738  Trk::Material(390., 1223., 18., 9., 0.0014);
739 
740  // create the Bounds
741  Trk::CylinderVolumeBounds* lArHecInnerGapBounds =
742  new Trk::CylinderVolumeBounds(rHecBP, lArPositiveHecBounds->innerRadius(),
743  lArPositiveHecBounds->halflengthZ());
744 
745  Amg::Transform3D* lArHecPos = new Amg::Transform3D(
746  Amg::Translation3D(Amg::Vector3D(0., 0., lArPositiveHec->center().z())));
747  Amg::Transform3D* lArHecNeg = new Amg::Transform3D(
748  Amg::Translation3D(Amg::Vector3D(0., 0., lArNegativeHec->center().z())));
749 
750  Trk::TrackingVolume* lArPositiveHecInnerGap = new Trk::TrackingVolume(
751  lArHecPos, lArHecInnerGapBounds, m_Al, dummyLayers, dummyVolumes,
752  "Calo::GapVolumes::LAr::PositiveHecInnerGap");
753 
754  Trk::TrackingVolume* lArNegativeHecInnerGap = new Trk::TrackingVolume(
755  lArHecNeg, lArHecInnerGapBounds->clone(), m_Al, dummyLayers, dummyVolumes,
756  "Calo::GapVolumes::LAr::NegativeHecInnerGap");
757  // create the Bounds
758  Trk::CylinderVolumeBounds* lArHecOuterGapBounds =
759  new Trk::CylinderVolumeBounds(lArPositiveHecBounds->outerRadius(),
760  keyDim.back().first,
761  lArPositiveHecBounds->halflengthZ());
762 
763  Trk::TrackingVolume* lArPositiveHecOuterGap = new Trk::TrackingVolume(
764  new Amg::Transform3D(*lArHecPos), lArHecOuterGapBounds, m_Ar, dummyLayers,
765  dummyVolumes, "Calo::GapVolumes::LAr::PositiveHecOuterGap");
766 
767  Trk::TrackingVolume* lArNegativeHecOuterGap = new Trk::TrackingVolume(
768  new Amg::Transform3D(*lArHecNeg), lArHecOuterGapBounds->clone(), m_Ar,
769  dummyLayers, dummyVolumes, "Calo::GapVolumes::LAr::NegativeHecOuterGap");
770 
771  // glue Hec sector with beam pipe volumes
772 
773  std::vector<Trk::TrackingVolume*> volsHecPos;
774  if (hecBP.first)
775  volsHecPos.push_back(hecBP.first);
776  volsHecPos.push_back(lArPositiveHecInnerGap);
777  volsHecPos.push_back(lArPositiveHec);
778  volsHecPos.push_back(lArPositiveHecOuterGap);
779 
780  std::unique_ptr<Trk::TrackingVolume> positiveHec(
781  m_trackingVolumeCreator->createContainerTrackingVolume(
782  volsHecPos, m_caloMaterial, "Calo::Container::PositiveHec"));
783 
784  std::vector<Trk::TrackingVolume*> volsHecNeg;
785  if (hecBP.second)
786  volsHecNeg.push_back(hecBP.second);
787  volsHecNeg.push_back(lArNegativeHecInnerGap);
788  volsHecNeg.push_back(lArNegativeHec);
789  volsHecNeg.push_back(lArNegativeHecOuterGap);
790 
791  std::unique_ptr<Trk::TrackingVolume> negativeHec(
792  m_trackingVolumeCreator->createContainerTrackingVolume(
793  volsHecNeg, m_caloMaterial, "Calo::Container::NegativeHec"));
794 
796  // Fcal sector + beam pipe + lAr cover
797 
798  // create beam pipe volumes for Fcal and return their outer radius
799  float rFcalBP = 0.;
800  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> fcalBP =
801  createBeamPipeVolumes(
802  bpCutouts,
803  lArPositiveFcal->center().z() - lArPositiveFcalBounds->halflengthZ(),
804  lArPositiveFcal->center().z() + lArPositiveFcalBounds->halflengthZ(),
805  "Fcal", rFcalBP);
806  // FcalInnerGap (new gap volume )
807  // Trk::Material lArFcalInnerGapMaterial = Trk::Material(390.,
808  // 1223., 40.,18., 0.0014);
809 
810  if (rFcalBP > lArPositiveFcalBounds->innerRadius()) {
811  ATH_MSG_ERROR("PROBLEM : beam pipe collide with Fcal:"
812  << rFcalBP << ">" << lArPositiveFcalBounds->innerRadius()
813  << ", abort");
814  return nullptr;
815  }
816 
817  // create the Bounds
818  Trk::CylinderVolumeBounds* lArFcalInnerGapBounds =
819  new Trk::CylinderVolumeBounds(rFcalBP,
820  lArPositiveFcalBounds->innerRadius(),
821  lArPositiveFcalBounds->halflengthZ());
822 
823  Amg::Transform3D* lArFcalPos = new Amg::Transform3D(
824  Amg::Translation3D(Amg::Vector3D(0., 0., lArPositiveFcal->center().z())));
825  Amg::Transform3D* lArFcalNeg = new Amg::Transform3D(
826  Amg::Translation3D(Amg::Vector3D(0., 0., lArNegativeFcal->center().z())));
827 
828  Trk::TrackingVolume* lArPositiveFcalInnerGap = new Trk::TrackingVolume(
829  lArFcalPos, lArFcalInnerGapBounds, m_Al, dummyLayers, dummyVolumes,
830  "Calo::GapVolumes::LAr::PositiveFcalInnerGap");
831 
832  Trk::TrackingVolume* lArNegativeFcalInnerGap = new Trk::TrackingVolume(
833  lArFcalNeg, lArFcalInnerGapBounds->clone(), m_Al, dummyLayers,
834  dummyVolumes, "Calo::GapVolumes::LAr::NegativeFcalInnerGap");
835 
836  // create the Bounds
837  Trk::CylinderVolumeBounds* lArFcalOuterGapBounds =
838  new Trk::CylinderVolumeBounds(lArPositiveHecBounds->outerRadius(),
839  keyDim.back().first,
840  lArPositiveFcalBounds->halflengthZ());
841 
842  Trk::TrackingVolume* lArPositiveFcalOuterGap = new Trk::TrackingVolume(
843  new Amg::Transform3D(*lArFcalPos), lArFcalOuterGapBounds, m_Ar,
844  dummyLayers, dummyVolumes, "Calo::GapVolumes::LAr::PositiveFcalOuterGap");
845 
846  Trk::TrackingVolume* lArNegativeFcalOuterGap = new Trk::TrackingVolume(
847  new Amg::Transform3D(*lArFcalNeg), lArFcalOuterGapBounds->clone(), m_Ar,
848  dummyLayers, dummyVolumes, "Calo::GapVolumes::LAr::NegativeFcalOuterGap");
849 
850  // glue Fcal sector with beam pipe volumes
851 
852  std::vector<Trk::TrackingVolume*> volsFcalPos;
853  if (fcalBP.first)
854  volsFcalPos.push_back(fcalBP.first);
855  volsFcalPos.push_back(lArPositiveFcalInnerGap);
856  volsFcalPos.push_back(lArPositiveFcal);
857  volsFcalPos.push_back(lArPositiveHecFcalCover);
858  volsFcalPos.push_back(lArPositiveFcalOuterGap);
859 
860  std::unique_ptr<Trk::TrackingVolume> positiveFcal(
861  m_trackingVolumeCreator->createContainerTrackingVolume(
862  volsFcalPos, m_caloMaterial, "Calo::Container::PositiveFcal"));
863 
864  std::vector<Trk::TrackingVolume*> volsFcalNeg;
865  if (fcalBP.second)
866  volsFcalNeg.push_back(fcalBP.second);
867  volsFcalNeg.push_back(lArNegativeFcalInnerGap);
868  volsFcalNeg.push_back(lArNegativeFcal);
869  volsFcalNeg.push_back(lArNegativeHecFcalCover);
870  volsFcalNeg.push_back(lArNegativeFcalOuterGap);
871 
872  std::unique_ptr<Trk::TrackingVolume> negativeFcal(
873  m_trackingVolumeCreator->createContainerTrackingVolume(
874  volsFcalNeg, m_caloMaterial, "Calo::Container::NegativeFcal"));
875 
877  // Outer endcap sector + beam pipe
878 
879  // create beam pipe volumes for Outer sector and return their outer radius
880  float rOutBP = 0.;
881  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> outBP =
882  createBeamPipeVolumes(bpCutouts, lArPositiveOuterBoundary,
883  caloPositiveOuterBoundary, "Outer", rOutBP);
884 
885  Trk::Material lArSectorOuterGapMat =
886  Trk::Material(20.5, 723., 64., 28., 0.0084);
887 
888  Trk::CylinderVolumeBounds* lArSectorOuterG0Bounds =
890  rOutBP, 430.,
891  // lArPositiveEndcapBounds->outerRadius(),
892  0.5 * (caloPositiveOuterBoundary - lArPositiveOuterBoundary));
893 
894  Trk::CylinderVolumeBounds* lArSectorOuterG1Bounds =
896  430., keyDim.back().first,
897  // lArPositiveEndcapBounds->outerRadius(),
898  0.5 * (caloPositiveOuterBoundary - lArPositiveOuterBoundary));
899 
900  z = 0.5 * (caloPositiveOuterBoundary + lArPositiveOuterBoundary);
901 
902  Amg::Transform3D* lArSecOutG1P =
904  Amg::Transform3D* lArSecOutG0P =
906 
907  lArPositiveSectorOuterGap0 = new Trk::TrackingVolume(
908  lArSecOutG0P, lArSectorOuterG0Bounds, lArSectorOuterGapMat, dummyLayers,
909  dummyVolumes, "Calo::GapVolumes::LAr::PositiveSectorOuterGap0");
910 
911  lArPositiveSectorOuterGap = new Trk::TrackingVolume(
912  lArSecOutG1P, lArSectorOuterG1Bounds, m_Ar, dummyLayers, dummyVolumes,
913  "Calo::GapVolumes::LAr::PositiveSectorOuterGap");
914 
915  Amg::Transform3D* lArSecOutG1N =
917  Amg::Transform3D* lArSecOutG0N =
919 
920  lArNegativeSectorOuterGap0 =
921  new Trk::TrackingVolume(lArSecOutG0N, lArSectorOuterG0Bounds->clone(),
922  lArSectorOuterGapMat, dummyLayers, dummyVolumes,
923  "Calo::GapVolumes::LAr::NegativeSectorOuterGap0");
924 
925  lArNegativeSectorOuterGap = new Trk::TrackingVolume(
926  lArSecOutG1N, lArSectorOuterG1Bounds->clone(), m_Ar, dummyLayers,
927  dummyVolumes, "Calo::GapVolumes::LAr::NegativeSectorOuterGap");
928 
929  // glue OuterGap with beam pipe volumes
930  std::vector<Trk::TrackingVolume*> volsOuterGapP;
931  if (outBP.first)
932  volsOuterGapP.push_back(outBP.first);
933  volsOuterGapP.push_back(lArPositiveSectorOuterGap0);
934  volsOuterGapP.push_back(lArPositiveSectorOuterGap);
935  std::unique_ptr<Trk::TrackingVolume> positiveOuterGap(
936  m_trackingVolumeCreator->createContainerTrackingVolume(
937  volsOuterGapP, m_caloMaterial, "Calo::Container::PositiveOuterGap"));
938 
939  std::vector<Trk::TrackingVolume*> volsOuterGapN;
940  if (outBP.second)
941  volsOuterGapN.push_back(outBP.second);
942  volsOuterGapN.push_back(lArNegativeSectorOuterGap0);
943  volsOuterGapN.push_back(lArNegativeSectorOuterGap);
944  std::unique_ptr<Trk::TrackingVolume> negativeOuterGap(
945  m_trackingVolumeCreator->createContainerTrackingVolume(
946  volsOuterGapN, m_caloMaterial, "Calo::Container::NegativeOuterGap"));
947 
948  ATH_MSG_DEBUG("Endcap volumes ready");
949 
950  // ++ (ii) lArNegativeSector
951  Trk::TrackingVolume* lArNegativeSector = nullptr;
952  // +++ has 4 sub volumes in Z
953  std::vector<Trk::TrackingVolume*> lArNegativeSectorVolumes;
954  // +++ (A) -> Outer sector
955  lArNegativeSectorVolumes.push_back(negativeOuterGap.release());
956  // +++ (B) -> Fcal sector
957  lArNegativeSectorVolumes.push_back(negativeFcal.release());
958  // +++ (C) -> Hec sector
959  lArNegativeSectorVolumes.push_back(negativeHec.release());
960  // +++ (D) -> Endcap sector
961  lArNegativeSectorVolumes.push_back(negativeEndcap.release());
962  // +++ all exists : create super volume (ii)
963  lArNegativeSector = m_trackingVolumeCreator->createContainerTrackingVolume(
964  lArNegativeSectorVolumes, m_caloMaterial,
965  "Calo::LAr::Container::NegativeSector");
966 
967  // ++ (ii) lArPositiveSector
968  Trk::TrackingVolume* lArPositiveSector = nullptr;
969  // +++ has 4 sub volumes in Z
970  std::vector<Trk::TrackingVolume*> lArPositiveSectorVolumes;
971  // +++ (A) -> Endcap sector
972  lArPositiveSectorVolumes.push_back(positiveEndcap.release());
973  // +++ (B) -> Hec sector
974  lArPositiveSectorVolumes.push_back(positiveHec.release());
975  // +++ (C) -> Fcal sector
976  lArPositiveSectorVolumes.push_back(positiveFcal.release());
977  // +++ (D) -> OuterGap
978  lArPositiveSectorVolumes.push_back(positiveOuterGap.release());
979  // +++ all exists : create super volume (ii)
980  lArPositiveSector = m_trackingVolumeCreator->createContainerTrackingVolume(
981  lArPositiveSectorVolumes, m_caloMaterial,
982  "Calo::LAr::Container::PositiveSector");
983 
985  // central LAr barrel
986  //
987  // solenoid gap
989  keyDim[0].first, solenoidBounds->innerRadius(),
990  solenoidBounds->halflengthZ());
991 
992  // solenoid gap is not completely empty
993  Trk::Material solGapMat(535., 2871., 18.6, 9.1, 0.00038);
994 
995  trtSolenoidGap =
996  new Trk::TrackingVolume(nullptr, trtSolGapBounds, solGapMat, dummyLayers,
997  dummyVolumes, "Calo::GapVolumes::SolenoidGap");
998 
999  Trk::CylinderVolumeBounds* lArTileCentralG1Bounds =
1000  new Trk::CylinderVolumeBounds(lArBarrelBounds->outerRadius(),
1001  tileCombinedBounds->innerRadius(),
1002  lArBarrelBounds->halflengthZ());
1003 
1004  lArTileCentralSectorGap = new Trk::TrackingVolume(
1005  nullptr, lArTileCentralG1Bounds, m_Ar, dummyLayers, dummyVolumes,
1006  "Calo::GapVolumes::LArTileCentralSectorGap");
1007 
1008  Trk::TrackingVolume* lArCentralBarrelSector = nullptr;
1009  // ++ has 6 sub volumes in R
1010  std::vector<Trk::TrackingVolume*> lArCentralBarrelSectorVolumes;
1011  // ++++ (a) -> solenoid gap
1012  lArCentralBarrelSectorVolumes.push_back(trtSolenoidGap);
1013  // ++++ (b) -> solenoid (exists already)
1014  lArCentralBarrelSectorVolumes.push_back(solenoid);
1015  // ++++ (c) -> solenoidlArPresamplerGap (exists already)
1016  lArCentralBarrelSectorVolumes.push_back(solenoidlArPresamplerGap);
1017  // ++++ (d) -> lArBarrelPresampler (exists already)
1018  lArCentralBarrelSectorVolumes.push_back(lArBarrelPresampler);
1019  // ++++ (e) -> lArBarrel (exists already)
1020  lArCentralBarrelSectorVolumes.push_back(lArBarrel);
1021  // ++++ (f) -> lArTile gap
1022  lArCentralBarrelSectorVolumes.push_back(lArTileCentralSectorGap);
1023  // ++++ all sub volumes exist: build the super volume
1024  lArCentralBarrelSector =
1025  m_trackingVolumeCreator->createContainerTrackingVolume(
1026  lArCentralBarrelSectorVolumes, m_caloMaterial,
1027  "Calo::Containers::LAr::CentralBarrelSector", false, true);
1029  // side buffers
1030  // the Tile Crack volume (TileGap3, enum 17) inserted here
1031  // binned material for Crack : steering in binEta
1032  // TODO turn into 2D binned array
1033  std::vector<Trk::IdentifiedMaterial> matCrack;
1034  // layer material can be adjusted here
1035  int baseID = Trk::GeometrySignature(Trk::Calo) * 1000 + 17;
1036  matCrack.emplace_back(&m_Scint, baseID);
1037  matCrack.emplace_back(&m_caloMaterial, -1);
1038  matCrack.emplace_back(&m_Al, -1);
1039  //
1040  double etadist;
1041  // if TileGap3 goes above 1.6 in eta - it's RUN3 geometry
1042  int nbins =
1043  (caloDDM->is_in(1.65, 0.0, CaloCell_ID::TileGap3, etadist)) ? 6 : 3;
1044  Trk::BinUtility* bun =
1045  new Trk::BinUtility(nbins, -1.8, -1.2, Trk::open, Trk::binEta);
1046  Trk::BinUtility* bup =
1047  new Trk::BinUtility(nbins, 1.2, 1.8, Trk::open, Trk::binEta);
1048  // array of indices
1049  std::vector<std::vector<size_t>> indexP;
1050  std::vector<std::vector<size_t>> indexN;
1051  // binned material for LAr : layer depth per eta bin
1052  std::vector<Trk::BinUtility*> layDN(bun->bins());
1053  std::vector<Trk::BinUtility*> layUP(bup->bins());
1054  double crackZ1 = 3532.;
1055  double crackZ2 = 3540.;
1056  // construct bin utilities
1057  std::vector<float> steps;
1058  for (unsigned int i = 0; i < bup->bins(); i++) {
1059  steps.clear();
1060  std::vector<size_t> indx;
1061  indx.clear();
1062  steps.push_back(crackZ1);
1063  indx.push_back(i < bup->bins() - 1 ? 0 : 1);
1064  steps.push_back(crackZ2);
1065  indx.push_back(2);
1066  steps.push_back(keyDim.back().second);
1068  layUP[i] = zBU;
1069  indexP.push_back(indx);
1070  }
1071 
1072  const Trk::BinnedMaterial* crackBinPos =
1073  new Trk::BinnedMaterial(&m_crackMaterial, bup, layUP, indexP, matCrack);
1074 
1075  Amg::Transform3D* align = nullptr;
1076 
1078  keyDim[0].first, tileCombinedBounds->innerRadius(),
1079  0.5 * (keyDim.back().second - crackZ1));
1080  z = 0.5 * (keyDim.back().second + crackZ1);
1081  Amg::Transform3D* crackPosTransform =
1083 
1085  crackPosTransform, align, crackBoundsPos, crackBinPos, 17,
1086  "Calo::Detectors::Tile::CrackPos");
1087 
1088  for (unsigned int i = 0; i < bun->bins(); i++) {
1089  steps.clear();
1090  std::vector<size_t> indx;
1091  indx.clear();
1092  steps.push_back(-keyDim.back().second);
1093  indx.push_back(2);
1094  steps.push_back(-crackZ2);
1095  indx.push_back(i > 0 ? 0 : 1);
1096  steps.push_back(-crackZ1);
1098  layDN[i] = zBU;
1099  indexN.push_back(indx);
1100  }
1101 
1102  Trk::BinnedMaterial* crackBinNeg =
1103  new Trk::BinnedMaterial(&m_crackMaterial, bun, layDN, indexN, matCrack);
1104 
1105  align = nullptr;
1106 
1107  Amg::Transform3D* crackNegTransform =
1109 
1111  crackNegTransform, align, crackBoundsPos->clone(), crackBinNeg, 17,
1112  "Calo::Detectors::Tile::CrackNeg");
1114 
1115  Trk::CylinderVolumeBounds* lArCentralG1Bounds = new Trk::CylinderVolumeBounds(
1116  keyDim[0].first, tileCombinedBounds->innerRadius(),
1117  0.5 * (crackZ1 - lArBarrelBounds->halflengthZ()));
1118 
1119  z = 0.5 * (crackZ1 + lArBarrelBounds->halflengthZ());
1120  Amg::Transform3D* lArCentralG1P =
1122 
1123  lArCentralPositiveGap = new Trk::TrackingVolume(
1124  lArCentralG1P, lArCentralG1Bounds, m_Ar, dummyLayers, dummyVolumes,
1125  "Calo::GapVolumes::LArCentralPositiveGap");
1126 
1127  Amg::Transform3D* lArCentralG1N =
1129 
1130  lArCentralNegativeGap = new Trk::TrackingVolume(
1131  lArCentralG1N, lArCentralG1Bounds->clone(), m_Ar, dummyLayers,
1132  dummyVolumes, "Calo::GapVolumes::LArCentralNegativeGap");
1133 
1134  // glue laterally
1135  Trk::TrackingVolume* lArCentralSector = nullptr;
1136  // ++ has 5 sub volumes in z
1137  std::vector<Trk::TrackingVolume*> lArCentralSectorVolumes;
1138  // ++++ (a) -> negative crack
1139  lArCentralSectorVolumes.push_back(crackNeg);
1140  // ++++ (b) -> negative gap
1141  lArCentralSectorVolumes.push_back(lArCentralNegativeGap);
1142  // ++++ (c) -> central barrel
1143  lArCentralSectorVolumes.push_back(lArCentralBarrelSector);
1144  // ++++ (d) -> positive gap
1145  lArCentralSectorVolumes.push_back(lArCentralPositiveGap);
1146  // ++++ (e) -> positive crack
1147  lArCentralSectorVolumes.push_back(crackPos);
1148  // ++++ all sub volumes exist: build the super volume
1149  lArCentralSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1150  lArCentralSectorVolumes, m_caloMaterial,
1151  "Calo::Containers::LAr::CentralSector");
1152 
1153  // glue with ID sector
1154  Trk::TrackingVolume* caloCentralSector = nullptr;
1155  // ++ has 2 sub volumes in R
1156  std::vector<Trk::TrackingVolume*> caloCentralSectorVolumes;
1157  // ++++ (a) -> ID sector
1158  caloCentralSectorVolumes.push_back(inDetEnclosed);
1159  // ++++ (b) -> LAr sector
1160  caloCentralSectorVolumes.push_back(lArCentralSector);
1161  // ++++ all sub volumes exist: build the super volume
1162  caloCentralSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1163  caloCentralSectorVolumes, m_caloMaterial,
1164  "Calo::Containers::CaloCentralSector");
1165 
1167 
1168  // glue laterally with endcaps
1169  Trk::TrackingVolume* lArCombined = nullptr;
1170  // ++ has 3 sub volumes in z
1171  std::vector<Trk::TrackingVolume*> lArCombinedVolumes;
1172  // ++++ (a) -> negative endcap
1173  lArCombinedVolumes.push_back(lArNegativeSector);
1174  // ++++ (b) -> barrel
1175  lArCombinedVolumes.push_back(caloCentralSector);
1176  // ++++ (a) -> positive endcap
1177  lArCombinedVolumes.push_back(lArPositiveSector);
1178  // ++++ all sub volumes exist: build the super volume
1179  lArCombined = m_trackingVolumeCreator->createContainerTrackingVolume(
1180  lArCombinedVolumes, m_caloMaterial, "Calo::Containers::LAr::Combined");
1181 
1182  // glue with LAr sector
1183  Trk::TrackingVolume* caloCombined = nullptr;
1184  // ++ has 2 sub volumes in R
1185  std::vector<Trk::TrackingVolume*> caloVolumes;
1186  // ++++ (a) -> LAr sector
1187  caloVolumes.push_back(lArCombined);
1188  // ++++ (b) -> Tile sector
1189  caloVolumes.push_back(tileCombined);
1190  // ++++ all sub volumes exist: build the super volume
1191  caloCombined = m_trackingVolumeCreator->createContainerTrackingVolume(
1192  caloVolumes, m_caloMaterial, "Calo::Containers::CombinedCalo");
1193 
1195 
1196  // build the radial buffer volume to synchronize the radial envelope
1197  // dimensions
1198  Trk::TrackingVolume* centralBuffer = nullptr;
1199  Trk::TrackingVolume* ecPosBuffer = nullptr;
1200  Trk::TrackingVolume* ecNegBuffer = nullptr;
1201 
1202  if (caloVolsOuterRadius > caloDefaultRadius) {
1204  "Calo volumes exceeds envelope radius: adjusting envelope "
1205  "(de-synchronizing...)");
1206  caloDefaultRadius = caloVolsOuterRadius;
1207  }
1208 
1209  if (caloVolsOuterRadius < caloDefaultRadius) {
1211  "Build radial buffer to synchronize the boundaries in between R "
1212  << caloVolsOuterRadius << " and " << caloDefaultRadius);
1213 
1214  Trk::CylinderVolumeBounds* centralSynBounds = new Trk::CylinderVolumeBounds(
1215  caloVolsOuterRadius, caloDefaultRadius, caloVolsExtendZ);
1216  centralBuffer = new Trk::TrackingVolume(
1217  nullptr, centralSynBounds, m_caloMaterial, dummyLayers, dummyVolumes,
1218  "Calo::GapVolumes::EnvelopeBuffer");
1219  }
1220 
1221  if (caloVolsExtendZ < caloDefaultHalflengthZ) {
1223  "Build longitudinal buffers to synchronize the boundaries in between Z "
1224  << caloVolsExtendZ << " and " << caloDefaultHalflengthZ);
1225 
1227  0., caloDefaultRadius,
1228  0.5 * (caloDefaultHalflengthZ - caloVolsExtendZ));
1229  // endcap buffers not empty
1230  Trk::Material ecBuffMat(53. / 0.38, 355. / 0.38, 20., 10.,
1231  0.0053 * pow(0.38, 3));
1232 
1233  float zPos = 0.5 * (caloDefaultHalflengthZ + caloVolsExtendZ);
1234  ecPosBuffer = new Trk::TrackingVolume(
1236  endcapSynBounds, m_Ar, dummyLayers, dummyVolumes,
1237  "Calo::GapVolumes::PosECBuffer");
1238 
1239  ecNegBuffer = new Trk::TrackingVolume(
1240  new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0., 0., -zPos))),
1241  endcapSynBounds->clone(), m_Ar, dummyLayers, dummyVolumes,
1242  "Calo::GapVolumes::NegECBuffer");
1243  }
1244 
1246  "All gap volumes for the Calorimeter created. Starting to build Volume "
1247  "Hiearchy.");
1248 
1250 
1251  ATH_MSG_VERBOSE("Resolve MS cutouts:");
1252 
1253  // resolve number of additional cutout volumes
1254  int nCutVol = 0;
1255  std::vector<float> zCutStep;
1256  std::vector<float> rCutStep;
1257  if (msCutouts.size() > 1) {
1258  zCutStep.push_back(msCutouts[0].second);
1259  rCutStep.push_back(msCutouts[0].first);
1260  for (unsigned int i = 1; i < msCutouts.size(); i++) {
1261  if (msCutouts[i].second == zCutStep.back())
1262  rCutStep.push_back(msCutouts[i].first);
1263  else
1264  zCutStep.push_back(msCutouts[i].second);
1265  }
1266  nCutVol = zCutStep.size() - 1;
1267  }
1268  if (nCutVol > 0)
1269  ATH_MSG_VERBOSE(nCutVol << " MS cutout volume(s) required ");
1270 
1271  std::vector<Trk::TrackingVolume*> forwardCutoutVols;
1272  std::vector<Trk::TrackingVolume*> backwardCutoutVols;
1273 
1274  // cutout region not empty
1275  std::vector<Trk::Material> cutOutMat;
1276  cutOutMat.emplace_back(19.9, 213., 50., 23.,
1277  0.0065); // 3.5 Fe + 1 Ar : verify
1278  cutOutMat.push_back(m_caloMaterial);
1279  // cutOutMat.push_back(Trk::Material(18.74, 200.9, 52.36, 24.09, 0.0069));
1280 
1281  if (nCutVol > 0) {
1282  // loop over zCutStep, rCutStep[0] gives the fixed outer radius, rCutStep[i]
1283  // the cutout radius for ith volume
1284  float rout = rCutStep[0];
1285  float zlow = zCutStep[0];
1286  for (unsigned int i = 1; i < zCutStep.size(); i++) {
1287  float zup = zCutStep[i];
1288  float rcut = rCutStep[i];
1289  std::stringstream ss;
1290  ss << i;
1291  // get beam pipe volumes
1292  float rCutOutBP = 0.;
1293  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> cutOutBP =
1294  createBeamPipeVolumes(bpCutouts, zlow, zup, "CutOuts" + ss.str(),
1295  rCutOutBP);
1296 
1297  // build inner part ( -> Calo )
1298  unsigned int mindex = i > 1 ? 1 : i;
1299 
1300  Trk::CylinderVolumeBounds* cutInBounds =
1301  new Trk::CylinderVolumeBounds(rCutOutBP, rcut, 0.5 * (zup - zlow));
1302  Trk::TrackingVolume* caloInPos = new Trk::TrackingVolume(
1303  new Amg::Transform3D(
1304  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (zup + zlow)))),
1305  cutInBounds, cutOutMat[mindex], dummyLayers, dummyVolumes,
1306  "Calo::GapVolumes::CaloPositiveCutIn" + ss.str());
1307  Trk::TrackingVolume* caloInNeg = new Trk::TrackingVolume(
1308  new Amg::Transform3D(
1309  Amg::Translation3D(Amg::Vector3D(0., 0., -0.5 * (zup + zlow)))),
1310  cutInBounds->clone(), cutOutMat[mindex], dummyLayers, dummyVolumes,
1311  "Calo::GapVolumes::CaloNegativeCutIn" + ss.str());
1312  // build cutout ( -> MS ) : geometry signature needs to be resolved later
1313  // : follow naming convention
1314  Trk::CylinderVolumeBounds* cutOutBounds =
1315  new Trk::CylinderVolumeBounds(rcut, rout, 0.5 * (zup - zlow));
1316  Trk::TrackingVolume* caloOutPos = new Trk::TrackingVolume(
1317  new Amg::Transform3D(
1318  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (zup + zlow)))),
1319  cutOutBounds, m_caloMaterial, dummyLayers, dummyVolumes,
1320  "Muon::GapVolumes::CaloPositiveCutOut" + ss.str());
1321  Trk::TrackingVolume* caloOutNeg = new Trk::TrackingVolume(
1322  new Amg::Transform3D(
1323  Amg::Translation3D(Amg::Vector3D(0., 0., -0.5 * (zup + zlow)))),
1324  cutOutBounds->clone(), m_caloMaterial, dummyLayers, dummyVolumes,
1325  "Muon::GapVolumes::CaloNegativeCutOut" + ss.str());
1326 
1327  // sign
1328  caloOutPos->sign(Trk::MS);
1329  caloOutNeg->sign(Trk::MS);
1330 
1331  // glue radially and save for final gluing
1332  std::vector<Trk::TrackingVolume*> cvPos;
1333  cvPos.push_back(cutOutBP.first);
1334  cvPos.push_back(caloInPos);
1335  cvPos.push_back(caloOutPos);
1336  Trk::TrackingVolume* cutOutPos =
1337  m_trackingVolumeCreator->createContainerTrackingVolume(
1338  cvPos, m_caloMaterial,
1339  "Calo::GapVolumes::CaloPositiveCutoutVolume" + ss.str());
1340  forwardCutoutVols.push_back(cutOutPos);
1341  //
1342  std::vector<Trk::TrackingVolume*> cvNeg;
1343  cvNeg.push_back(cutOutBP.second);
1344  cvNeg.push_back(caloInNeg);
1345  cvNeg.push_back(caloOutNeg);
1346  Trk::TrackingVolume* cutOutNeg =
1347  m_trackingVolumeCreator->createContainerTrackingVolume(
1348  cvNeg, m_caloMaterial,
1349  "Calo::GapVolumes::CaloNegativeCutoutVolume" + ss.str());
1350  backwardCutoutVols.insert(backwardCutoutVols.begin(), cutOutNeg);
1351 
1352  zlow = zup;
1353  }
1354  }
1355 
1357 
1358  if (!centralBuffer) { //(XX)
1359  // all volumes exist : create the super volume at top level
1360  calorimeter = caloCombined;
1361 
1362  } else { //(X)
1363 
1364  std::vector<Trk::TrackingVolume*> envRVols;
1365  envRVols.push_back(caloCombined);
1366  envRVols.push_back(centralBuffer);
1367 
1368  // add cutouts - final step
1369  if (!forwardCutoutVols.empty() || ecNegBuffer) {
1370 
1371  Trk::TrackingVolume* caloRVolume =
1372  m_trackingVolumeCreator->createContainerTrackingVolume(
1373  envRVols, m_caloMaterial, "Calo::Containers::CombinedRCalo");
1374  std::vector<Trk::TrackingVolume*> envZVols;
1375  envZVols.reserve(backwardCutoutVols.size());
1376  for (auto& backwardCutoutVol : backwardCutoutVols)
1377  envZVols.push_back(backwardCutoutVol);
1378  if (ecNegBuffer)
1379  envZVols.push_back(ecNegBuffer);
1380  envZVols.push_back(caloRVolume);
1381  if (ecPosBuffer)
1382  envZVols.push_back(ecPosBuffer);
1383  for (auto& forwardCutoutVol : forwardCutoutVols)
1384  envZVols.push_back(forwardCutoutVol);
1385 
1386  calorimeter = m_trackingVolumeCreator->createContainerTrackingVolume(
1387  envZVols, m_caloMaterial, m_exitVolume);
1388 
1389  } else { // if no cutouts or endcap buffers, this is the top calo volume
1390 
1391  calorimeter = m_trackingVolumeCreator->createContainerTrackingVolume(
1392  envRVols, m_caloMaterial, m_exitVolume);
1393  }
1394  }
1395 
1397  "TrackingVolume 'Calorimeter' built successfully. Wrap it in "
1398  "TrackingGeometry.");
1399 
1400  delete lArVolumes;
1401  lArVolumes = nullptr;
1402  delete tileVolumes;
1403  tileVolumes = nullptr;
1404 
1405  auto caloTrackingGeometry =
1406  std::make_unique<Trk::TrackingGeometry>(calorimeter);
1407 
1408  if (msgLvl(MSG::VERBOSE) && caloTrackingGeometry){
1409  caloTrackingGeometry->printVolumeHierarchy(msg(MSG::VERBOSE));
1410  }
1411 
1412  if (m_indexStaticLayers && caloTrackingGeometry){
1413  caloTrackingGeometry->indexStaticLayers(signature());
1414  }
1415 
1416  return caloTrackingGeometry;
1417 }
1418 
1420  Trk::LayerIndexSampleMap& licsMap,
1421  std::vector<CaloCell_ID::CaloSample> ccid, const Trk::TrackingVolume& vol,
1422  int side) const {
1423 
1424  ATH_MSG_VERBOSE("[+] Registering layers of TrackingVolume '"
1425  << vol.volumeName() << "' in LayerIndex/CaloCell_ID map");
1426 
1427  // get the confined Layers from the TrackingVolume
1428  const Trk::LayerArray* confinedLayers = vol.confinedLayers();
1429  if (!confinedLayers)
1430  return;
1431 
1433  confinedLayers->arrayObjects();
1435  layerObjects.begin();
1437  layerObjects.end();
1438 
1439  // now pick out the material layers (and skip the navigation ones)
1440  std::vector<const Trk::Layer*> materialLayers;
1441  for (; layerObjIter != layerObjEnd; ++layerObjIter)
1442  if ((*layerObjIter)->layerMaterialProperties())
1443  materialLayers.push_back((*layerObjIter));
1444 
1445  unsigned int matLaySize = materialLayers.size();
1446  unsigned int ccidSize = ccid.size();
1447 
1448  ATH_MSG_VERBOSE("[+] Found " << matLaySize << " material layers ( "
1449  << ccidSize << " CaloSample ids )");
1450  if (matLaySize != ccidSize)
1451  return;
1452 
1453  // everything's fine for side > 0
1454  if (side > 0) {
1455  // match 1-to-1
1456  std::vector<const Trk::Layer*>::iterator layerIt = materialLayers.begin();
1457  std::vector<const Trk::Layer*>::iterator layerItEnd = materialLayers.end();
1458  std::vector<CaloCell_ID::CaloSample>::iterator ccidIt = ccid.begin();
1459  std::vector<CaloCell_ID::CaloSample>::iterator ccidItEnd = ccid.end();
1460 
1461  for (; layerIt != layerItEnd && ccidIt != ccidItEnd; ++layerIt, ++ccidIt)
1462  licsMap.insert(std::make_pair((*layerIt)->layerIndex(), int(*ccidIt)));
1463 
1464  } else {
1465  // the order needs to be reversed, because TG has z-ordering positive
1466  // defined
1467 
1468  std::vector<CaloCell_ID::CaloSample>::iterator ccidIt = ccid.begin();
1469  std::vector<CaloCell_ID::CaloSample>::iterator ccidItEnd = ccid.end();
1470 
1471  for (; ccidIt != ccidItEnd; ++ccidIt, --matLaySize)
1472  licsMap.insert(std::make_pair(
1473  (materialLayers[matLaySize - 1])->layerIndex(), int(*ccidIt)));
1474  }
1475 }
1476 
1477 std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*>
1479  const RZPairVector& bpCutouts, float zmin, float zmax,
1480  const std::string& name, float& outerRadius) const {
1481  outerRadius = 0.;
1482 
1483  // dummy objects
1484  Trk::LayerArray* dummyLayers = nullptr;
1485  Trk::TrackingVolumeArray* dummyVolumes = nullptr;
1486 
1487  // beam pipe thickness along the z distance
1488  if (bpCutouts.empty()) {
1489  return std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*>(0, 0);
1490  }
1491 
1492  RZPairVector dim;
1493  dim.emplace_back(bpCutouts[0].first, zmin);
1494  float rOut = bpCutouts[0].first;
1495  for (const auto& bpCutout : bpCutouts) {
1496  if (bpCutout.second <= dim[0].second)
1497  dim[0].first = bpCutout.first;
1498  else if (bpCutout.second <= zmax)
1499  dim.push_back(bpCutout);
1500  if (bpCutout.second <= zmax)
1501  rOut = bpCutout.first;
1502  }
1503 
1504  if (dim.back().second < zmax)
1505  dim.emplace_back(rOut, zmax);
1506 
1507  if (dim.size() == 2) { // simple case
1508 
1509  outerRadius = dim[0].first;
1510 
1511  Trk::CylinderVolumeBounds* bpBounds =
1512  new Trk::CylinderVolumeBounds(0., outerRadius, 0.5 * (zmax - zmin));
1513 
1514  Amg::Transform3D* bpPos = new Amg::Transform3D(
1515  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (zmin + zmax))));
1516 
1517  Trk::TrackingVolume* bpVolPos =
1518  new Trk::TrackingVolume(bpPos, bpBounds, m_caloMaterial, dummyLayers,
1519  dummyVolumes, "BeamPipe::Positive" + name);
1520 
1521  Amg::Transform3D* bpNeg = new Amg::Transform3D(
1522  Amg::Translation3D(Amg::Vector3D(0., 0., -0.5 * (zmin + zmax))));
1523 
1524  Trk::TrackingVolume* bpVolNeg = new Trk::TrackingVolume(
1525  bpNeg, bpBounds->clone(), m_caloMaterial, dummyLayers, dummyVolumes,
1526  "BeamPipe::Negative" + name);
1527 
1528  // geometry signature
1529  bpVolPos->sign(Trk::BeamPipe);
1530  bpVolNeg->sign(Trk::BeamPipe);
1531 
1532  return std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*>(bpVolPos,
1533  bpVolNeg);
1534  }
1535 
1536  // cutout included
1537 
1538  outerRadius = dim[0].first;
1539 
1540  // find rMax
1541  for (unsigned int i = 1; i < dim.size(); i++)
1542  if (dim[i].first > outerRadius)
1543  outerRadius = dim[i].first;
1544 
1545  // loop over z sections, prepare volumes for gluing
1546  std::vector<Trk::TrackingVolume*> posVols;
1547 
1548  for (unsigned int i = 0; i < dim.size() - 1; i++) {
1549 
1550  if (dim[i].second == dim[i + 1].second)
1551  continue;
1552 
1553  // beam pipe volume
1555  0., dim[i].first, 0.5 * (dim[i + 1].second - dim[i].second));
1556 
1558  Amg::Vector3D(0., 0., 0.5 * (dim[i + 1].second + dim[i].second))));
1559 
1560  Trk::TrackingVolume* bpVolPos =
1561  new Trk::TrackingVolume(bpPos, bpBounds, m_caloMaterial, dummyLayers,
1562  dummyVolumes, "BeamPipe::Positive" + name);
1563  bpVolPos->sign(Trk::BeamPipe);
1564 
1565  Trk::TrackingVolume* bpVolGap = nullptr;
1566  if (dim[i].first < outerRadius) {
1567 
1569  dim[i].first, outerRadius, 0.5 * (dim[i + 1].second - dim[i].second));
1570 
1571  Amg::Transform3D* bpPB = new Amg::Transform3D(*bpPos);
1572 
1573  bpVolGap = new Trk::TrackingVolume(bpPB, bpGB, m_caloMaterial,
1574  dummyLayers, dummyVolumes,
1575  "Calo::GapVolumes::Positive" + name);
1576  }
1577 
1578  Trk::TrackingVolume* bpSector = bpVolPos;
1579 
1580  if (bpVolGap) {
1581  std::vector<Trk::TrackingVolume*> gapVols;
1582  gapVols.push_back(bpVolPos);
1583  gapVols.push_back(bpVolGap);
1584  bpSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1585  gapVols, m_caloMaterial, "Calo::Container::PositiveBPSector" + name);
1586  }
1587  posVols.push_back(bpSector);
1588  }
1589 
1590  Trk::TrackingVolume* bpPosSector =
1591  m_trackingVolumeCreator->createContainerTrackingVolume(
1592  posVols, m_caloMaterial, "Calo::Container::PositiveBP" + name);
1593 
1594  // loop over z sections, prepare volumes for gluing
1595  std::vector<Trk::TrackingVolume*> negVols;
1596 
1597  for (unsigned int i = 0; i < dim.size() - 1; i++) {
1598 
1599  float zmax2 = -1. * (dim[i].second);
1600  float zmin2 = -1. * (dim[i + 1].second);
1601 
1602  if (zmin2 == zmax2)
1603  continue;
1604 
1605  // beam pipe volume
1606  Trk::CylinderVolumeBounds* bpBounds =
1607  new Trk::CylinderVolumeBounds(0., dim[i].first, 0.5 * (zmax2 - zmin2));
1608 
1609  Amg::Transform3D* bpNeg = new Amg::Transform3D(
1610  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (zmin2 + zmax2))));
1611 
1612  Trk::TrackingVolume* bpVolNeg =
1613  new Trk::TrackingVolume(bpNeg, bpBounds, m_caloMaterial, dummyLayers,
1614  dummyVolumes, "BeamPipe::Negative" + name);
1615  bpVolNeg->sign(Trk::BeamPipe);
1616 
1617  Trk::TrackingVolume* bpVolGap =
1618  dim[i].first < outerRadius
1619  ? new Trk::TrackingVolume(
1620  new Amg::Transform3D(*bpNeg),
1621  new Trk::CylinderVolumeBounds(dim[i].first, outerRadius,
1622  0.5 * (zmax2 - zmin2)),
1623  m_caloMaterial, dummyLayers, dummyVolumes,
1624  "Calo::GapVolumes::Negative" + name)
1625  : nullptr;
1626 
1627  Trk::TrackingVolume* bpSector = bpVolNeg;
1628 
1629  if (bpVolGap) {
1630  std::vector<Trk::TrackingVolume*> gapVols;
1631  gapVols.push_back(bpVolNeg);
1632  gapVols.push_back(bpVolGap);
1633  bpSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1634  gapVols, m_caloMaterial, "Calo::Container::NegativeBPSector" + name);
1635  }
1636 
1637  if (negVols.empty())
1638  negVols.push_back(bpSector);
1639  else
1640  negVols.insert(negVols.begin(), bpSector);
1641  }
1642 
1643  Trk::TrackingVolume* bpNegSector =
1644  m_trackingVolumeCreator->createContainerTrackingVolume(
1645  negVols, m_caloMaterial, "Calo::Container::NegativeBP" + name);
1646 
1647  return std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*>(bpPosSector,
1648  bpNegSector);
1649 }
1650 
BinnedMaterial.h
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
TrapezoidBounds.h
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
DiscBounds.h
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
python.App.bins
bins
Definition: App.py:410
MaterialProperties.h
RZPairVector
std::vector< RZPair > RZPairVector
Definition: RZPair.h:18
Trk::binZ
@ binZ
Definition: BinningType.h:49
PixelAthClusterMonAlgCfg.zmin
zmin
Definition: PixelAthClusterMonAlgCfg.py:176
Calo::CaloTrackingGeometryBuilderImpl::initialize
virtual StatusCode initialize() override
AlgTool initailize method.
Definition: CaloTrackingGeometryBuilderImpl.cxx:47
BinnedArray.h
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
Trk::BinnedMaterial
Definition: BinnedMaterial.h:38
Calo::CaloTrackingGeometryBuilderImpl::createTrackingGeometry
std::unique_ptr< Trk::TrackingGeometry > createTrackingGeometry(Trk::TrackingVolume *innerVol, const CaloDetDescrManager *caloDDM) const
TrackingGeometry Interface method.
Definition: CaloTrackingGeometryBuilderImpl.cxx:96
BinUtility.h
DiscLayer.h
VolumeBounds.h
HomogeneousLayerMaterial.h
BinnedArray1D1D.h
Trk::binEta
@ binEta
Definition: BinningType.h:54
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CaloTrackingGeometryBuilderImpl.h
Trk::Calo
@ Calo
Definition: GeometrySignature.h:28
CaloCell_ID_FCS::TileGap3
@ TileGap3
Definition: FastCaloSim_CaloCell_ID.h:36
ILayerArrayCreator.h
Trk::BinUtility::bins
size_t bins(size_t ba=0) const
Number of bins.
Definition: BinUtility.h:223
Trk::BeamPipe
@ BeamPipe
Definition: GeometrySignature.h:27
Trk::LayerIndexSampleMap
std::map< Trk::LayerIndex, int > LayerIndexSampleMap
Definition: LayerIndexSampleMap.h:29
TRT::Hit::side
@ side
Definition: HitInfo.h:83
Trk::MS
@ MS
Definition: GeometrySignature.h:29
Trk::TrackingVolume::confinedLayers
const LayerArray * confinedLayers() const
Return the subLayer array.
SCT_CalibAlgs::nbins
@ nbins
Definition: SCT_CalibNumbers.h:10
Calo::CaloTrackingGeometryBuilderImpl::~CaloTrackingGeometryBuilderImpl
virtual ~CaloTrackingGeometryBuilderImpl()
Destructor.
GeometryStatics.h
CylinderVolumeBounds.h
Trk::GeometrySignature
GeometrySignature
Definition: GeometrySignature.h:24
beamspotman.steps
int steps
Definition: beamspotman.py:505
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Trk::DiscBounds::clone
virtual DiscBounds * clone() const override final
Virtual constructor.
Calo::CaloTrackingGeometryBuilderImpl::createBeamPipeVolumes
std::pair< Trk::TrackingVolume *, Trk::TrackingVolume * > createBeamPipeVolumes(const RZPairVector &bpCutouts, float, float, const std::string &, float &) const
method to build enclosed beam pipe volumes
Definition: CaloTrackingGeometryBuilderImpl.cxx:1478
lumiFormat.i
int i
Definition: lumiFormat.py:92
z
#define z
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Calo::CaloTrackingGeometryBuilderImpl::registerInLayerIndexCaloSampleMap
void registerInLayerIndexCaloSampleMap(Trk::LayerIndexSampleMap &licsMAp, std::vector< CaloCell_ID::CaloSample > ccid, const Trk::TrackingVolume &vol, int side=1) const
method to establish a link between the LayerIndex and the CaloCell_ID in an associative container
Definition: CaloTrackingGeometryBuilderImpl.cxx:1419
Trk::CylinderVolumeBounds::halflengthZ
double halflengthZ() const
This method returns the halflengthZ.
Definition: CylinderVolumeBounds.h:207
PixelAthClusterMonAlgCfg.zmax
zmax
Definition: PixelAthClusterMonAlgCfg.py:176
Trk::Volume::center
const Amg::Vector3D & center() const
returns the center of the volume
Definition: Volume.h:86
Trk::DiscLayer
Definition: DiscLayer.h:45
SharedObject.h
Trk::BinUtility
Definition: BinUtility.h:39
Trk::CylinderVolumeBounds
Definition: CylinderVolumeBounds.h:70
IOVInfiniteRange.h
Trk::TrackingVolume::volumeName
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
GlueVolumesDescriptor.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
Trk::CylinderVolumeBounds::outerRadius
double outerRadius() const
This method returns the outer radius.
Definition: CylinderVolumeBounds.h:191
Trk::BinnedArray::arrayObjects
virtual BinnedArraySpan< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
Trk::Volume::transform
const Amg::Transform3D & transform() const
Return methods for geometry transform.
Definition: Volume.h:81
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
CaloDetDescrManager_Base::is_in
bool is_in(double eta, double phi, CaloCell_ID::CaloSample sample, double &etadist) const
return true if direction eta,phi crosses ANY of the corresponding descriptors
Definition: CaloDetDescrManager.cxx:1348
Trk::open
@ open
Definition: BinningType.h:40
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
IDynamicLayerCreator.h
Trk::MaterialProperties
Definition: MaterialProperties.h:40
TrackingVolume.h
CaloDetDescrManager
This class provides the client interface for accessing the detector description information common to...
Definition: CaloDetDescrManager.h:473
Trk::CylinderVolumeBounds::innerRadius
double innerRadius() const
This method returns the inner radius.
Definition: CylinderVolumeBounds.h:187
Calo::CaloTrackingGeometryBuilderImpl::CaloTrackingGeometryBuilderImpl
CaloTrackingGeometryBuilderImpl(const std::string &, const std::string &, const IInterface *)
Constructor.
Definition: CaloTrackingGeometryBuilderImpl.cxx:37
Trk::TrackingVolume::sign
void sign(GeometrySignature signat, GeometryType gtype=Static)
sign the volume - the geometry builder has to do that
Definition: TrackingVolume.cxx:941
DeMoScan.first
bool first
Definition: DeMoScan.py:534
Amg::Translation3D
Eigen::Translation< double, 3 > Translation3D
Definition: GeoPrimitives.h:44
Trk::Volume::volumeBounds
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition: Volume.h:97
DiscSurface.h
TrackingGeometry.h
Trk::Material
Definition: Material.h:116
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
Trk::BinnedArray
Definition: BinnedArray.h:38
AthAlgTool
Definition: AthAlgTool.h:26
Trk::HomogeneousLayerMaterial
Definition: HomogeneousLayerMaterial.h:53
Trk::TrackingVolume
Definition: TrackingVolume.h:121
Trk::CylinderVolumeBounds::clone
CylinderVolumeBounds * clone() const override
Virtual constructor.
Definition: CylinderVolumeBounds.h:171
Material
@ Material
Definition: MaterialTypes.h:8
AlignableTrackingVolume.h
Trk::BinnedArraySpan
std::span< T > BinnedArraySpan
Definition: BinnedArray.h:34
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
Trk::DiscBounds
Definition: DiscBounds.h:44
Trk::TrackingVolume::screenDump
void screenDump(MsgStream &msg) const
Definition: TrackingVolume.cxx:1506
Trk::AlignableTrackingVolume
Definition: AlignableTrackingVolume.h:36