ATLAS Offline Software
Loading...
Searching...
No Matches
TrackingVolumeHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// TrackingVolumeHelper.cxx, (c) ATLAS Detector software
8
9// Trk include
15#include "TrkSurfaces/Surface.h"
29// Amg
31
32#include <memory>
33#include <stdexcept>
34
35namespace {
36 template <class Obj>
37 std::vector<Obj*> toRawVec(const std::vector<std::shared_ptr<Obj>>& in) {
38
39 std::vector<Obj*> out{};
40 out.reserve(in.size());
41 for (const std::shared_ptr<Obj>& obj : in) {
42 out.emplace_back(obj.get());
43 }
44 return out;
45 }
46}
47
48namespace Trk {
49// constructor
50TrackingVolumeHelper::TrackingVolumeHelper(const std::string& t, const std::string& n, const IInterface* p)
51: AthAlgTool(t,n,p),
53 declareInterface<ITrackingVolumeHelper>(this);
54}
55
56
57// the interface methods
59
60 ATH_MSG_DEBUG( "initialize() " );
63 return StatusCode::SUCCESS;
64}
65
66
69 BoundarySurfaceFace firstFace,
70 TrackingVolume& secondVol,
71 BoundarySurfaceFace secondFace,
72 bool buildBoundaryLayer) const
73{
74 TrackingVolumeManipulator::glueVolumes( firstVol, firstFace, secondVol, secondFace );
75
76 // ----------------------------------------------------------------------------------------
77 // create a MaterialLayer as a boundary
78 if (buildBoundaryLayer){
79 auto& bSurfacesFirst = firstVol.boundarySurfaces();
80 auto& bSurfacesSecond = secondVol.boundarySurfaces();
81 // get the boundary surfaces
82 Surface& firstFaceSurface = bSurfacesFirst[firstFace]->surfaceRepresentation();
83 Surface& secondFaceSurface = bSurfacesSecond[secondFace]->surfaceRepresentation();
84 // dynamic_cast to the right type
85 std::unique_ptr<LayerMaterialProperties> lmps = layerMaterialProperties(firstFaceSurface);
86 // LayerMaterialProperties will be cloned in MaterialLayer
87
88 // set the layer to the two surfaces
89 if (lmps){
90 auto mLayer = std::make_shared<MaterialLayerNoOwnSurf>(&firstFaceSurface, std::move(lmps));
91 ATH_MSG_VERBOSE( "Set MaterialLayer to the BoundarySurface of first volume." );
92 firstFaceSurface.setMaterialLayer(mLayer);
93 ATH_MSG_VERBOSE("Set MaterialLayer to the BoundarySurface of second volume.");
94 secondFaceSurface.setMaterialLayer(mLayer);
95 }
96 }
97}
98
101 BoundarySurfaceFace firstFace,
102 const std::vector<TrackingVolume*>& secondVolumes,
103 BoundarySurfaceFace secondFace,
104 bool buildBoundaryLayer,
105 bool boundaryFaceExchange) const
106{
107
108 if (msgLvl(MSG::VERBOSE)) {
109 ATH_MSG_VERBOSE( "Glue Volume '" << firstVol.volumeName() << "' to " << secondVolumes.size() << " volume(s): " );
110 for (const auto & volIter : secondVolumes)
111 ATH_MSG_VERBOSE( " -> " << (volIter)->volumeName() );
112 }
113 // prepare the material layer if needed
114 std::shared_ptr<MaterialLayer> mLayer{};
115 // ----------------------------------------------------------------------------------------
116 // create a MaterialLayer as a boundary
117 if (buildBoundaryLayer){
118 // the first face surface
119 Surface& firstFaceSurface = firstVol.boundarySurfaces()[firstFace]->surfaceRepresentation();
120 std::unique_ptr<LayerMaterialProperties> lmps = layerMaterialProperties(firstFaceSurface);
121 // LayerMaterialProperties are cloned by MaterialLayer
122
123 // the material layer is ready - it can be assigned
124 mLayer = std::make_shared<MaterialLayerNoOwnSurf>(&firstFaceSurface, std::move(lmps));
125 ATH_MSG_VERBOSE( "Set MaterialLayer to the BoundarySurface of first volume (may be shared with second volume)." );
126 firstFaceSurface.setMaterialLayer(mLayer);
127 }
128 // if only one volume was given in the vector call the standard one-to-one glueing
129 // 1-to-1 case
130 if (secondVolumes.size() == 1) {
131 // self call for one-on-one
132 glueTrackingVolumes(firstVol, firstFace, *(secondVolumes[0]), secondFace);
133 } else {
134 // create the navigation bin array
135 std::unique_ptr<BinnedArray<TrackingVolume>> navArray = nullptr;
136 // create the Array - either r-binned or z-binned
137 if (firstFace == negativeFaceXY || firstFace == positiveFaceXY )
138 navArray = m_trackingVolumeArrayCreator->cylinderVolumesArrayInR(secondVolumes, true);
139 else
140 navArray = m_trackingVolumeArrayCreator->cylinderVolumesArrayInZ(secondVolumes, true);
141
142 // set the volume array to the first boundary surface - this must always happen
143 if (firstFace != tubeInnerCover){
144 setOutsideTrackingVolumeArray( firstVol, firstFace, std::move(navArray) );
145 }
146 else{
147 setInsideTrackingVolumeArray( firstVol, firstFace, std::move(navArray) );
148 }
149 // the navigation arrays are completed now - check if the boundary face should be exchanged
150 // [1] the boundary face exchange ----------------------------------------------------------------------------------------
151 if (boundaryFaceExchange){
152 // creating only one boundary surface
153 ATH_MSG_VERBOSE("Creating a joint boundary surface for 1-to-n glueing case.");
154 // get the dimension of boundary surface of the first volume
155 std::shared_ptr<BoundarySurface<TrackingVolume> > bSurface = firstVol.boundarySurfaces()[firstFace];
156 // replace the boundary surface
157 for ( const auto & volIter: secondVolumes )
158 setBoundarySurface(*volIter, bSurface, secondFace);
159 } else {
160 // [2] the traditional way, keeping two boundary surfaces
161 // now set the face to the volume array -------------------------------------------------------------------------------
162 for ( const auto & volIter: secondVolumes ) {
163 // the secondGlueFace
164 BoundarySurfaceFace secondGlueFace = secondFace;
165 if (secondFace == tubeOuterCover) {
166 //check for cylinder case
167 const CylinderVolumeBounds* currentVolBounds = dynamic_cast<const CylinderVolumeBounds*>(&((volIter)->volumeBounds()));
168 // protection : there may be a cylinder within the tube vector
169 if (currentVolBounds && currentVolBounds->innerRadius() < 10e-3)
170 secondGlueFace = cylinderCover;
171 setOutsideTrackingVolume(*volIter, secondGlueFace, (&(firstVol)));
172 } // for all surfaces except the tunbeInnerCover outside of the surface is identical to outside of the volume
173 else if (secondGlueFace != tubeInnerCover)
174 setOutsideTrackingVolume(*volIter, secondGlueFace, (&(firstVol)));
175 else
176 setInsideTrackingVolume(*volIter, secondGlueFace, (&(firstVol)));
177 // if existing, set the material Layer
178 // get the second face surface and set the new MaterialLayer
179 Surface& secondFaceSurface = volIter->boundarySurfaces()[secondFace]->surfaceRepresentation();
180 secondFaceSurface.setMaterialLayer(mLayer);
181 }
182 }
183 } // 1-to-n case
184}
185
186
188void TrackingVolumeHelper::glueTrackingVolumes(const std::vector<TrackingVolume*>& firstVolumes,
189 BoundarySurfaceFace firstFace,
190 const std::vector<TrackingVolume*>& secondVolumes,
191 BoundarySurfaceFace secondFace,
192 bool buildBoundaryLayer,
193 bool boundaryFaceExchange) const
194{
195
196
197 std::unique_ptr<BinnedArray<TrackingVolume>> navArrayOne = nullptr;
198 std::unique_ptr<BinnedArray<TrackingVolume>> navArrayTwo = nullptr;
199
200 std::unique_ptr<Surface> mLayerSurface;
201 std::shared_ptr<MaterialLayer> mLayer;
202
203 ATH_MSG_VERBOSE("Glue configuration firstFace | secondFace = " << firstFace << " | " << secondFace );
204
205 // create the Arrays - assuming cylindrical TrackingVolumes
206 if (firstFace < 2 && secondFace < 2 ) {
207 ATH_MSG_VERBOSE( "The glueing is done along z axis" );
208 navArrayOne = m_trackingVolumeArrayCreator->cylinderVolumesArrayInR(firstVolumes, true);
209 navArrayTwo = m_trackingVolumeArrayCreator->cylinderVolumesArrayInR(secondVolumes, true);
210 // build a disc to separate the two
211 if (buildBoundaryLayer || boundaryFaceExchange){
212 double rmin = 10e10; double rmax = 0; double boundaryz = 0.; double centerzOne = 0.;
213 for (const auto & volIter : firstVolumes ){
214 const CylinderVolumeBounds* cb = dynamic_cast<const CylinderVolumeBounds*>(&(volIter->volumeBounds()));
215 if (cb) {
216 takeSmaller(rmin,cb->innerRadius());
217 takeBigger(rmax,cb->outerRadius());
218 // get the z of the surface
219 boundaryz = volIter->boundarySurfaces()[firstFace]->surfaceRepresentation().center().z();
220 }
221 centerzOne = volIter->center().z();
222 }
223 if (buildBoundaryLayer){
224 Amg::Transform3D mLayerTransform =
225 Amg::Transform3D(Amg::Translation3D(0., 0., boundaryz));
226 // layer surface
227 mLayerSurface = std::make_unique<DiscSurface>(mLayerTransform, rmin, rmax);
228 // create a MaterialLayer
229 std::unique_ptr<LayerMaterialProperties> lmps = layerMaterialProperties(*mLayerSurface);
230 // MaterialLayer clones the LayerMaterialPropteries.
231
232 if (lmps) {
233 mLayer = std::make_shared<MaterialLayerOwnSurf>(std::move(mLayerSurface), std::move(lmps));
234 }
235 }
236 if (boundaryFaceExchange){
237 // creating only one boundary surface
238 ATH_MSG_VERBOSE("Creating a joint boundary surface for n-to-n glueing case.");
239 // check if the seconf volumes have a bigger z value or a smaller one
240 double centerzTwo = secondVolumes[secondVolumes.size()-1]->center().z();
241 // thi sboundary surface is having a z-axix along the global z-axis
242 Amg::Transform3D boundaryTransform = Amg::getTranslateZ3D(boundaryz);
243 // disc surfaces
244 DiscSurface dSurface(boundaryTransform, rmin, rmax);
245 // swap if needed
246 if (centerzTwo < centerzOne){
247 std::swap(navArrayTwo, navArrayOne);
248 }
249 // create the new boudnary surface which spans over the entire volume border
250 std::shared_ptr< BinnedArray<TrackingVolume> > navArrayInside(std::move(navArrayOne));
251 std::shared_ptr< BinnedArray<TrackingVolume> > navArrayOutside(std::move(navArrayTwo));
252 BoundaryDiscSurface<TrackingVolume>* boundarySurface = new BoundaryDiscSurface<TrackingVolume>(navArrayInside,navArrayOutside,dSurface);
253 std::shared_ptr<BoundarySurface<TrackingVolume> > sharedBoundarySurface(boundarySurface);
254 // attach the material layer to the shared boundary if existing
255 if (mLayer) {
256 ATH_MSG_VERBOSE( "Set MaterialLayer to the BoundarySurface of volume from second array." );
257 boundarySurface->surfaceRepresentation().setMaterialLayer(std::move(mLayer));
258 }
259 // set the boundary surface to the volumes of both sides
260 for (const auto & volIter : firstVolumes){
261 ATH_MSG_VERBOSE(" -> first array : setting a newly created boundary surface to " << volIter->volumeName());
262 setBoundarySurface(*volIter,sharedBoundarySurface,firstFace);
263 }
264 for (const auto & volIter : secondVolumes){
265 ATH_MSG_VERBOSE(" -> second array : setting a newly created boundary surface to " << volIter->volumeName());
266 setBoundarySurface(*volIter,sharedBoundarySurface,secondFace);
267 }
268 // we are done here
269 return;
270 }
271 }
272 } else {
273 ATH_MSG_VERBOSE( "The glueing is done along the radius." );
274 navArrayOne = m_trackingVolumeArrayCreator->cylinderVolumesArrayInZ(firstVolumes, true);
275 navArrayTwo = m_trackingVolumeArrayCreator->cylinderVolumesArrayInZ(secondVolumes, true);
276 // check if the boundary layer was configured to be built
277 if (buildBoundaryLayer || boundaryFaceExchange){
278 // build a cylinder to separate the two
279 double zmin = 10e10; double zmax = -10e10; double boundaryr = 0.; double volumerOne = 0.; double volumerTwo = 10e10;
280 for (const auto & volIter : firstVolumes ){
281 const CylinderVolumeBounds* cb = dynamic_cast<const CylinderVolumeBounds*>(&(volIter->volumeBounds()));
282 if (cb) {
283 takeSmaller(zmin,volIter->center().z()-cb->halflengthZ());
284 takeBigger(zmax,volIter->center().z()+cb->halflengthZ());
285 // get the z of the surface
286 boundaryr = volIter->boundarySurfaces()[firstFace]->surfaceRepresentation().bounds().r();
287 // get the volume radius
288 volumerOne = cb->outerRadius();
289 }
290 }
291 // check if boundary layer should be built
292 if (buildBoundaryLayer){
293 std::unique_ptr<Amg::Transform3D> mLayerTransform =
294 ((zmin + zmax) * (zmin + zmax) < 10e-4)
295 ? nullptr
296 : std::make_unique < Amg::Transform3D>();
297
298 if (mLayerTransform) (*mLayerTransform) = Amg::Translation3D(0.,0.,0.5*(zmin+zmax));
299 mLayerSurface.reset( mLayerTransform ? new CylinderSurface(*mLayerTransform,boundaryr,0.5*(zmax-zmin)) :
300 new CylinderSurface(boundaryr,0.5*(zmax-zmin)) );
301 // create a MaterialLayer
302 std::unique_ptr<LayerMaterialProperties> lmps = layerMaterialProperties(*mLayerSurface);
303 // LayerMaterialProperties will be cloned in MaterialLayer
304 if (lmps) mLayer = std::make_shared<MaterialLayerOwnSurf>(
305 std::move(mLayerSurface),
306 std::move(lmps) );
307 }
308 // check if boundary face should be exchanged
309 if (boundaryFaceExchange) {
310 // creating only one boundary surface
311 ATH_MSG_VERBOSE("Creating a joint boundary surface for n-to-n glueing case.");
312 // the boundary transform can be 0 for cylinder surfaces
313 std::unique_ptr<Amg::Transform3D> boundaryTransform =
314 ((zmin + zmax) * (zmin + zmax) < 10e-4)
315 ? nullptr
316 : std::make_unique<Amg::Transform3D>();
317
318 if (boundaryTransform) (*boundaryTransform) = Amg::getTranslateZ3D(0.5*(zmin+zmax));
319 // create the cylinder surface for the shared boundary
320 CylinderSurface cSurface = boundaryTransform ? CylinderSurface(*boundaryTransform,boundaryr,0.5*(zmax-zmin)) :
321 CylinderSurface(boundaryr,0.5*(zmax-zmin));
322 // get the volume outer radius of the sconf volumes
323 const CylinderVolumeBounds* cbTwo = dynamic_cast<const CylinderVolumeBounds*>(&(secondVolumes[secondVolumes.size()-1]->volumeBounds()));
324 if (cbTwo){
325 volumerTwo = cbTwo->outerRadius();
326 }
327 // swap if needed
328 if (volumerTwo < volumerOne){
329 std::swap(navArrayTwo, navArrayOne);
330 }
331 // create the new boudnary surface which spans over the entire volume border
332 std::shared_ptr< BinnedArray<TrackingVolume> > navArrayInside(std::move(navArrayOne));
333 std::shared_ptr< BinnedArray<TrackingVolume> > navArrayOutside(std::move(navArrayTwo));
334 BoundaryCylinderSurface<TrackingVolume>* boundarySurface = new BoundaryCylinderSurface<TrackingVolume>(navArrayInside,navArrayOutside,cSurface);
335 std::shared_ptr<BoundarySurface<TrackingVolume> > sharedBoundarySurface(boundarySurface);
336 // attach the material layer to the shared boundary if existing
337 if (mLayer) {
338 ATH_MSG_VERBOSE("Set MaterialLayer to the BoundarySurface of volume from second array.");
339 // assume that now the mlayer onwership goes over to the TrackingVolume
340 boundarySurface->surfaceRepresentation().setMaterialLayer(std::move(mLayer));
341 }
342 // set the boundary surface to the volumes of both sides
343 for (const auto & volIter : firstVolumes){
344 ATH_MSG_VERBOSE(" -> first array : setting a newly created boundary surface to " << volIter->volumeName());
345 setBoundarySurface(*volIter,sharedBoundarySurface,firstFace);
346 }
347 for (const auto & volIter : secondVolumes){
348 ATH_MSG_VERBOSE(" -> second array : setting a newly created boundary surface to " << volIter->volumeName());
349 setBoundarySurface(*volIter,sharedBoundarySurface,secondFace);
350 }
351 // we are done here
352 return;
353 }
354 } // build either boundary layer or exchange the face
355 } // radial glueing
356
357
358 // create the boundary faces - not creating a joint one
359 ATH_MSG_VERBOSE("Leaving individual boundary surfaces for n-to-n glueing case.");
360
361 // assign the navigation arrays
362 std::shared_ptr< BinnedArray< TrackingVolume> > navArrayOneShared(std::move(navArrayOne));
363 std::shared_ptr< BinnedArray< TrackingVolume> > navArrayTwoShared(std::move(navArrayTwo));
364
365 // (a) to the first set of volumes
366 for (const auto & tVolIter: firstVolumes) {
367 // take care of the orientation of the normal vector
368 if (firstFace != tubeInnerCover) {
369 setOutsideTrackingVolumeArray(*tVolIter,firstFace,navArrayTwoShared);
370 ATH_MSG_VERBOSE( "Set outsideTrackingVolumeArray at face " << firstFace << " to " << (*tVolIter).volumeName() );
371 } else {
372 setInsideTrackingVolumeArray(*tVolIter,firstFace,navArrayTwoShared);
373 ATH_MSG_VERBOSE( "Set insideTrackingVolumeArray at face " << firstFace << " to " << (*tVolIter).volumeName() );
374 }
375 // set the boundary layer if it exists
376 if (mLayer) {
377 ATH_MSG_VERBOSE( "Set MaterialLayer to the BoundarySurface of volume from first array." );
378 Surface& firstFaceSurface = tVolIter->boundarySurfaces()[firstFace]->surfaceRepresentation();
379 // assume that now the mlayer onwership goes over to the TrackingVolume
380 //cppcheck-suppress ignoredReturnValue
381 firstFaceSurface.setMaterialLayer(mLayer);
382 }
383
384 }
385 // (b) to the second set of volumes
386 for (const auto & tVolIter : secondVolumes) {
387 // take care of the orientation of the normal vector
388 if (secondFace != tubeInnerCover) {
389 ATH_MSG_VERBOSE( "Set outsideTrackingVolumeArray at face " << secondFace << " to " << (*tVolIter).volumeName() );
390 setOutsideTrackingVolumeArray(*tVolIter,secondFace,navArrayOneShared);
391 } else {
392 ATH_MSG_VERBOSE( "Set insideTrackingVolumeArray at face " << secondFace << " to " << (*tVolIter).volumeName() );
393 setInsideTrackingVolumeArray(*tVolIter,secondFace,navArrayOneShared);
394 }
395 if (mLayer) {
396 ATH_MSG_VERBOSE( "Set MaterialLayer to the BoundarySurface of volume from second array." );
397 Surface& secondFaceSurface = tVolIter->boundarySurfaces()[secondFace]->surfaceRepresentation();
398 // assume that now the mlayer onwership goes over to the TrackingVolume
399 //cppcheck-suppress ignoredReturnValue
400 secondFaceSurface.setMaterialLayer(mLayer);
401 }
402 }
403 // coverity will report a bug here for mLayer running out of scope, but the memory management is done later in the TrackingVolume
404}
405
406std::unique_ptr<TrackingVolume> TrackingVolumeHelper::glueTrackingVolumeArrays(std::shared_ptr<TrackingVolume> firstVol,
407 BoundarySurfaceFace firstFace,
408 std::shared_ptr<TrackingVolume> secondVol,
409 BoundarySurfaceFace secondFace,
410 const std::string& name) const {
411 std::unique_ptr<TrackingVolume> enclosingVolume{};
412
413 const auto *cyl1 = dynamic_cast<const CylinderVolumeBounds*>(&(firstVol->volumeBounds()));
414 const auto *cyl2 = dynamic_cast<const CylinderVolumeBounds*>(&(secondVol->volumeBounds()));
415
416 if (!cyl1 || !cyl2) {
417 ATH_MSG_ERROR( "TrackingVolumeHelper::glueTrackingVolumeArrays: input volumes not cylinders, return 0" );
418 return enclosingVolume;
419 }
420 if (cyl1->halfPhiSector()!= M_PI || cyl2->halfPhiSector()!= M_PI ) {
421 ATH_MSG_ERROR( "TrackingVolumeHelper::glueTrackingVolumeArrays: not coded for cylinder Phi sectors yet, return 0" );
422 return enclosingVolume;
423 }
424
425 // if the swap is required
426 BoundarySurfaceFace firstFaceCorr = firstFace;
427 BoundarySurfaceFace secondFaceCorr = secondFace;
428
429
430 // build volume envelope
431 std::vector<std::shared_ptr<TrackingVolume>> vols;
432 std::shared_ptr<CylinderVolumeBounds> envBounds{};
433 std::unique_ptr<Amg::Transform3D> envTransf{};
434 std::unique_ptr<BinnedArray<TrackingVolume>> subVols{};
435 vols.push_back(firstVol);
436 vols.push_back(secondVol);
437 std::vector<std::shared_ptr<TrackingVolume>> envGlueNegXY{};
438 std::vector<std::shared_ptr<TrackingVolume>> envGluePosXY{};
439 std::vector<std::shared_ptr<TrackingVolume>> envGlueOuter;
440 std::vector<std::shared_ptr<TrackingVolume>> envGlueInner{};
441
442 if (firstFace==positiveFaceXY) {
443 envBounds = std::make_shared<CylinderVolumeBounds>(cyl1->innerRadius(),
444 cyl1->outerRadius(),
445 cyl1->halflengthZ() + cyl2->halflengthZ());
446
447 const Amg::Vector3D center{firstVol->center()};
448 envTransf = std::make_unique<Amg::Transform3D>(Amg::getTranslate3D(center.x(),
449 center.y(),
450 center.z() + cyl2->halflengthZ()));
451
452 subVols = m_trackingVolumeArrayCreator->cylinderVolumesArrayInZ(vols, false);
453 envGlueNegXY.push_back(firstVol);
454 envGluePosXY.push_back(secondVol);
455 envGlueOuter = vols;
456 envGlueInner = vols;
457 } else if (firstFace==negativeFaceXY) {
458 envBounds = std::make_shared<CylinderVolumeBounds>(cyl1->innerRadius(),
459 cyl1->outerRadius(),
460 cyl1->halflengthZ()+cyl2->halflengthZ());
461 const Amg::Vector3D center{firstVol->center()};
462 envTransf = std::make_unique<Amg::Transform3D>(Amg::getTranslate3D(center.x(),
463 center.y(),
464 center.z() - cyl2->halflengthZ()));
465 envGlueNegXY.push_back(secondVol);
466 envGluePosXY.push_back(firstVol);
467 // revert vols
468 vols.clear();
469 vols.push_back(secondVol);
470 vols.push_back(firstVol);
471 // --- account for the swapping
472 firstFaceCorr = secondFace;
473 secondFaceCorr = firstFace;
474 //
475 subVols = m_trackingVolumeArrayCreator->cylinderVolumesArrayInZ(vols,false);
476 envGlueOuter = vols;
477 envGlueInner = vols;
478 } else if (firstFace==tubeInnerCover) {
479 if (secondFace==tubeOuterCover){
480 envBounds = std::make_shared<CylinderVolumeBounds>(cyl2->innerRadius(),
481 cyl1->outerRadius(),
482 cyl1->halflengthZ());
483 } else {
484 envBounds = std::make_shared<CylinderVolumeBounds>(cyl1->outerRadius(),
485 cyl1->halflengthZ());
486 }
487 if (!firstVol->transform().isApprox(Amg::Transform3D::Identity())) {
488 envTransf = std::make_unique<Amg::Transform3D>(Amg::getTranslate3D(firstVol->center()));
489 }
490 // revert vols
491 vols.clear();
492 vols.push_back(secondVol);
493 vols.push_back(firstVol);
494 // account for the swapping
495 firstFaceCorr = secondFace;
496 secondFaceCorr = firstFace;
497 //
498 subVols = m_trackingVolumeArrayCreator->cylinderVolumesArrayInR(vols,false);
499 envGlueNegXY = vols;
500 envGluePosXY = vols;
501 envGlueOuter.push_back(firstVol);
502 envGlueInner.push_back(secondVol);
503 } else {
504 envBounds = std::make_shared<CylinderVolumeBounds>(cyl1->innerRadius(),
505 cyl2->outerRadius(),
506 cyl1->halflengthZ());
507 if(!firstVol->transform().isApprox(Amg::Transform3D::Identity())){
508 envTransf = std::make_unique<Amg::Transform3D>(Amg::getTranslate3D(firstVol->center()));
509 }
510 subVols = m_trackingVolumeArrayCreator->cylinderVolumesArrayInR(vols, false);
511 envGlueNegXY = vols;
512 envGluePosXY = vols;
513 envGlueOuter.push_back(secondVol);
514 envGlueInner.push_back(firstVol);
515 // account for the swapping
516 firstFaceCorr = secondFace;
517 secondFaceCorr = firstFace;
518 }
519
520 // create the enveloping volume
521 enclosingVolume = std::make_unique<TrackingVolume>(std::move(envTransf),
522 envBounds,
523 *firstVol,
524 nullptr, std::move(subVols), name);
525
526 // ENVELOPE GLUE DESCRIPTION -----------------------------------------------------------------
527 // glue descriptors ---- they jump to the first one
528 GlueVolumesDescriptor& glueDescr = enclosingVolume->glueVolumesDescriptor();
529
530 // for the outside volumes, could be done in a loop as well, but will only save 4 lines
531 std::vector<TrackingVolume*> glueNegXY{};
532 std::vector<TrackingVolume*> gluePosXY{};
533 std::vector<TrackingVolume*> glueInner{};
534 std::vector<TrackingVolume*> glueOuter{};
535 fillGlueVolumes(vols, envGlueNegXY, negativeFaceXY,glueNegXY);
536 fillGlueVolumes(vols, envGluePosXY, positiveFaceXY,gluePosXY);
537 fillGlueVolumes(vols, envGlueInner, tubeInnerCover,glueInner);
538 fillGlueVolumes(vols, envGlueOuter, tubeOuterCover,glueOuter);
539 // set them to the envelopGlueDescriptor
540 glueDescr.registerGlueVolumes(negativeFaceXY, glueNegXY);
541 glueDescr.registerGlueVolumes(positiveFaceXY, gluePosXY);
542 glueDescr.registerGlueVolumes(tubeInnerCover, glueInner);
543 glueDescr.registerGlueVolumes(tubeOuterCover, glueOuter);
544 glueDescr.registerGlueVolumes(cylinderCover, glueOuter);
545
546 // INTERNAL GLUEING ---------------------------------------------------------------------------
547 glueTrackingVolumes(vols, firstFaceCorr, secondFaceCorr);
548
549 return enclosingVolume;
550}
551
552
553
554void TrackingVolumeHelper::fillGlueVolumes(const std::vector<std::shared_ptr<TrackingVolume>>& topLevelVolumes,
555 const std::vector<std::shared_ptr<TrackingVolume>>& envelopeFaceVolumes,
556 BoundarySurfaceFace glueFace,
557 std::vector<TrackingVolume*>& glueVols){
558 std::vector<std::shared_ptr<TrackingVolume>> sharedTops{};
559 std::vector<std::shared_ptr<TrackingVolume>> sharedFaces{};
560 return fillGlueVolumes(::toRawVec(topLevelVolumes),
561 ::toRawVec(envelopeFaceVolumes),
562 glueFace, glueVols);
563
564}
565void TrackingVolumeHelper::fillGlueVolumes(const std::vector<TrackingVolume*>& topLevelVolumes,
566 const std::vector<TrackingVolume*>& envelopeFaceVolumes,
567 BoundarySurfaceFace glueFace,
568 std::vector<TrackingVolume*>& glueVols) {
569 // loop over the topLevel Volumes
570 auto refVolIter = topLevelVolumes.begin();
571 for ( ; refVolIter != topLevelVolumes.end(); ++refVolIter ) {
572 // loop over the faceVolumes
573 for (auto *envelopeFaceVolume : envelopeFaceVolumes){
574 // check whether this volume was assigned to on this face
575 if (envelopeFaceVolume==(*refVolIter)) {
576 // get the GlueVolumesDescriptor
577 GlueVolumesDescriptor& glueVolDescriptor = (*refVolIter)->glueVolumesDescriptor();
578 // if the size of glue volumes is 0 -> the referenceVolume is at navigation level
579 if ( (glueVolDescriptor.glueVolumes(glueFace)).empty()) {
580 glueVols.push_back(*refVolIter);
581 } else {
582 // fill all the sub-volumes described by the glueVolumeDescriptor
583 for (auto *isubNavVol : glueVolDescriptor.glueVolumes(glueFace))
584 glueVols.push_back( isubNavVol );
585 }
586 }
587 }// loop over envelopeFaceVolumes
588 } // loop over reference Volumes
589}
590
591
593void TrackingVolumeHelper::glueTrackingVolumes(const std::vector<std::shared_ptr<TrackingVolume>>& glueVols,
594 BoundarySurfaceFace firstFace,
595 BoundarySurfaceFace secondFace) const {
596 glueTrackingVolumes(::toRawVec(glueVols), firstFace, secondFace);
597
598}
599void TrackingVolumeHelper::glueTrackingVolumes(const std::vector<TrackingVolume*>& glueVols,
600 BoundarySurfaceFace firstFace,
601 BoundarySurfaceFace secondFace) const {
602
603 if (glueVols.size()<2) {
604 ATH_MSG_VERBOSE( "Nothing to do in glueVolumes() " );
605 return;
606 }
607
608
609 ATH_MSG_VERBOSE( " glueTrackingVolumes() called with boundary faces " << static_cast<int>(firstFace)
610 << " and " << static_cast<int>(secondFace) << "." );
611
612 // the iterators through the volumes
613 std::vector<TrackingVolume*>::const_iterator firstVol = glueVols.begin();
614 std::vector<TrackingVolume*>::const_iterator secondVol = firstVol + 1;
615 for ( ; secondVol != glueVols.end(); ++firstVol, ++secondVol) {
616
617 if (msgLvl(MSG::VERBOSE))
618 ATH_MSG_VERBOSE( "Processing '" << (*firstVol)->volumeName() << "' and '" << (*secondVol)->volumeName() << "'." );
619
620 // get the glue volume descriptors to see that we have all subvolumes
621 GlueVolumesDescriptor& glueDescr1 = (*firstVol)->glueVolumesDescriptor();
622 GlueVolumesDescriptor& glueDescr2 = (*secondVol)->glueVolumesDescriptor();
623
624 // glue volumes at navigation level
625 std::vector<TrackingVolume*> glueVols1{};
626 std::vector<TrackingVolume*> glueVols2{};
627 glueVols1 = glueDescr1.glueVolumes(firstFace);
628 glueVols2 = glueDescr2.glueVolumes(secondFace);
629
630 // trivial cases
631 // (glue one to the other)
632 if (glueVols1.empty() && glueVols2.empty()) {
633 glueTrackingVolumes(**firstVol,firstFace,**secondVol,secondFace);
634 continue;
635 // (glue one to many)
636 } else if (glueVols1.empty() && !glueVols2.empty()) {
637 glueVols1.push_back(*firstVol);
638 // (glue the other one to many)
639 } else if (!glueVols1.empty() && glueVols2.empty()) {
640 glueVols2.push_back(*secondVol);
641 }
642
643 // non-trivial case :: array against array
644 // in Z : assume 2dim R/Phi
645 if (firstFace==negativeFaceXY || firstFace==positiveFaceXY ) {
646 // turn both vectors into R/Phi 2dim binnedArrays; assume equidistant binning in Phi
647 std::shared_ptr<BinnedArray<TrackingVolume>> sgv1{m_trackingVolumeArrayCreator->cylinderVolumesArrayInPhiR(glueVols1,true)};
648 std::shared_ptr<BinnedArray<TrackingVolume>> sgv2{m_trackingVolumeArrayCreator->cylinderVolumesArrayInPhiR(glueVols2,true)};
649
650 // array vs. array in Z
651 if (glueVols2.size()>1)
652 for (auto & vol : glueVols1) setOutsideTrackingVolumeArray( *vol, firstFace, sgv2 );
653 else
654 for (auto & vol : glueVols1) setOutsideTrackingVolume( *vol, firstFace, glueVols2[0] );
655
656 if (glueVols1.size()>1)
657 for (auto & vol : glueVols2) setOutsideTrackingVolumeArray( *vol, secondFace, sgv1 );
658 else
659 for (auto & vol : glueVols2) setOutsideTrackingVolume( *vol, secondFace, glueVols1[0] );
660
661
662 } else {
663 // turn both vectors into Z/Phi 2dim binnedArrays; assume equidistant binning in Phi
664 std::shared_ptr<BinnedArray<TrackingVolume>> sgv1{m_trackingVolumeArrayCreator->cylinderVolumesArrayInPhiZ(glueVols1,true)};
665 std::shared_ptr<BinnedArray<TrackingVolume>> sgv2{m_trackingVolumeArrayCreator->cylinderVolumesArrayInPhiZ(glueVols2,true)};
666
667 // the glue cases -----------------------------------------------------------------------------------
668 // handle the tube with care !
669 // first vol
670 for (auto & vol : glueVols1) {
671 // set the array as the outside array of the firstVol
672 if (firstFace != tubeInnerCover) {
673 if (glueVols2.size()>1)
674 setOutsideTrackingVolumeArray( *vol, firstFace, sgv2 );
675 else
676 setOutsideTrackingVolume( *vol, firstFace, glueVols2[0] );
677 } else {
678 if (glueVols2.size()>1){
679 setInsideTrackingVolumeArray( *vol, firstFace, sgv2 );
680 setOutsideTrackingVolume( *vol, firstFace, vol );
681 } else {
682 setInsideTrackingVolume( *vol, firstFace, glueVols2[0] );
683 setOutsideTrackingVolume( *vol, firstFace, vol );
684 }
685 }
686 }
687 // second
688 for (auto & vol : glueVols2) {
689 // set the array as the outside array of the secondVol
690 if (secondFace != tubeInnerCover)
691 setOutsideTrackingVolumeArray( *vol, secondFace, sgv1 );
692 else {
693 setInsideTrackingVolumeArray( *vol, secondFace, sgv1 );
694 setOutsideTrackingVolume( *vol, secondFace, vol );
695 }
696 }
697 }
698 }
699}
700
701std::unique_ptr<LayerMaterialProperties>
703
704 std::unique_ptr<LayerMaterialProperties> layerMaterial{};
705
706 if (boundarySurface.type() == SurfaceType::Cylinder){
707 const CylinderBounds* cb = dynamic_cast<const CylinderBounds*>(&boundarySurface.bounds());
708 if (!cb) throw std::logic_error("Not CylinderBounds");
709 // --------------- material estimation ----------------------------------------------------------------
710 // -- material with 1D binning
711 double hz = cb->halflengthZ();
712 double r = cb->r();
713 BinUtility layerBinUtilityZ(m_barrelLayerBinsZ, -hz, hz, open, binZ);
714 if (m_barrelLayerBinsPhi==1){
715 layerMaterial = std::make_unique<BinnedLayerMaterial>(layerBinUtilityZ);
716 } else { // -- material with 2D binning
717 BinUtility layerBinUtilityRPhiZ(m_barrelLayerBinsPhi, -r*M_PI, r*M_PI, closed,binRPhi);
718 layerBinUtilityRPhiZ += layerBinUtilityZ;
719 layerMaterial = std::make_unique<BinnedLayerMaterial>(layerBinUtilityRPhiZ);
720 }
721 // --------------- material estimation ----------------------------------------------------------------
722 }
723 if (boundarySurface.type() == SurfaceType::Disc){
724 // --------------- material estimation ----------------------------------------------------------------
725 const DiscBounds* db = dynamic_cast<const DiscBounds*>(&boundarySurface.bounds());
726 if (!db) throw std::logic_error("Not DiscBounds");
727 double rMin = db->rMin();
728 double rMax = db->rMax();
729 BinUtility layerBinUtilityR(m_endcapLayerBinsR,rMin,rMax,open, binR);
730 // -- material with 1D binning
731 if (m_endcapLayerBinsPhi==1){
732 layerMaterial = std::make_unique<BinnedLayerMaterial>(layerBinUtilityR);
733 } else { // -- material with 2D binning
735 layerBinUtilityR += layerBinUtilityPhi;
736 layerMaterial = std::make_unique<BinnedLayerMaterial>(layerBinUtilityR);
737 }
738 // --------------- material estimation ----------------------------------------------------------------
739 }
740 // return what you have
741 return layerMaterial;
742}
743
744
745
752
753
757 std::shared_ptr<BinnedArray<TrackingVolume> > insidevolarray) const {
758 TrackingVolumeManipulator::setInsideVolumeArray(tvol,face,insidevolarray);
759}
760
761
765 TrackingVolume* outsidevol) const {
766 ATH_MSG_VERBOSE( " -> Glue '" << outsidevol->volumeName() << "' at face " << face << " to '" << tvol.volumeName() << "'.");
767 TrackingVolumeManipulator::setOutsideVolume( tvol, face, outsidevol );
768}
769
770
774 std::shared_ptr<BinnedArray<TrackingVolume> > outsidevolarray) const {
775 unsigned int numVols = outsidevolarray.get()->arrayObjects().size() ;
776 ATH_MSG_VERBOSE( " -> Glue " << numVols << " volumes at face " << face << " to '" << tvol.volumeName() );
777 TrackingVolumeManipulator::setOutsideVolumeArray( tvol, face, outsidevolarray );
778}
779}
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
#define takeSmaller(current, test)
#define takeBigger(current, test)
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
bool msgLvl(const MSG::Level lvl) const
A generic symmetric BinUtility, for fully symmetric binning in terms of binning grid and binning type...
Definition BinUtility.h:39
Binned Array for avoiding map searches/.
Definition BinnedArray.h:36
BoundaryCylinderSurface description inside the tracking realm, Extends the Surface description to mak...
virtual const Surface & surfaceRepresentation() const override final
The Surface Representation of this.
BoundaryDiscSurface description inside the tracking realm, it extends the DiscSurface description to ...
virtual const Surface & surfaceRepresentation() const override final
The Surface Representation of this.
Bounds for a cylindrical Surface.
virtual double r() const override final
This method returns the radius.
double halflengthZ() const
This method returns the halflengthZ.
Class for a CylinderSurface in the ATLAS detector.
Bounds for a cylindrical Volume, the decomposeToSurfaces method creates a vector of up to 6 surfaces:
double innerRadius() const
This method returns the inner radius.
double halflengthZ() const
This method returns the halflengthZ.
double outerRadius() const
This method returns the outer radius.
Class to describe the bounds for a planar DiscSurface.
Definition DiscBounds.h:44
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
Descriptor class to hold GlueVolumes of a TrackingGeometry object.
const std::vector< TrackingVolume * > & glueVolumes(BoundarySurfaceFace)
retrieve them again
void registerGlueVolumes(BoundarySurfaceFace, std::vector< TrackingVolume * > &)
register the volumes
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
virtual constexpr SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
void setMaterialLayer(std::shared_ptr< Trk::MaterialLayer > mlay)
set material layer
virtual const SurfaceBounds & bounds() const =0
Surface Bounds method.
void setOutsideTrackingVolume(TrackingVolume &tvol, BoundarySurfaceFace face, TrackingVolume *outsidevol) const override
protected method to set outside Volume of a BoundarySurface: input:
void setOutsideTrackingVolumeArray(TrackingVolume &tvol, BoundarySurfaceFace face, std::shared_ptr< BinnedArray< TrackingVolume > > outsidevolarray) const override
protected method to set outside VolumeArray of a BoundarySurface: input:
void glueTrackingVolumes(TrackingVolume &firstVol, BoundarySurfaceFace firstFace, TrackingVolume &secondVol, BoundarySurfaceFace secondFace, bool buildBoundaryLayer=false) const override
Method to glue two Volumes together input:
ToolHandle< ITrackingVolumeArrayCreator > m_trackingVolumeArrayCreator
Helper Tool to create TrackingVolume.
std::unique_ptr< Trk::TrackingVolume > glueTrackingVolumeArrays(std::shared_ptr< TrackingVolume > firstVol, BoundarySurfaceFace firstFace, std::shared_ptr< TrackingVolume > secondVol, BoundarySurfaceFace secondFace, const std::string &name) const override
Method to glue two VolumeArrays together (at navigation level).
Gaudi::Property< int > m_endcapLayerBinsR
material bins in R
void setInsideTrackingVolumeArray(TrackingVolume &tvol, BoundarySurfaceFace face, std::shared_ptr< BinnedArray< TrackingVolume > > insidevolarray) const override
protected method to set inside VolumeArray of a BoundarySurface: input:
std::unique_ptr< Trk::LayerMaterialProperties > layerMaterialProperties(const Trk::Surface &sf) const
< helper method to construct barrel material
TrackingVolumeHelper(const std::string &, const std::string &, const IInterface *)
Constructor.
Gaudi::Property< int > m_barrelLayerBinsPhi
material bins in Phi
Gaudi::Property< int > m_endcapLayerBinsPhi
material bins in Phi
StatusCode initialize() override
AlgTool initialize method.
Gaudi::Property< int > m_barrelLayerBinsZ
material bins in Z
void setInsideTrackingVolume(TrackingVolume &tvol, BoundarySurfaceFace face, TrackingVolume *insidevol) const override
protected method to set inside Volume of a BoundarySurface: input:
PublicToolHandle< ILayerArrayCreator > m_layerArrayCreator
A Tool for coherent LayerArray creation.
static void fillGlueVolumes(const std::vector< TrackingVolume * > &topLevelVolumes, const std::vector< TrackingVolume * > &envelopeFaceVolumes, BoundarySurfaceFace glueFace, std::vector< Trk::TrackingVolume * > &glueVols)
Private method - it takes the full vector of given volumes to create the supervolume,...
static void setBoundarySurface(TrackingVolume &tvol, std::shared_ptr< BoundarySurface< TrackingVolume > > bsurf, BoundarySurfaceFace face)
protected method to set the boundary surface of a tracking volume
static void setOutsideVolumeArray(TrackingVolume &tvol, BoundarySurfaceFace face, const std::shared_ptr< BinnedArray< TrackingVolume > > &outsidevolarray)
protected method to set outside VolumeArray of a BoundarySurface: input:
static void setInsideVolumeArray(TrackingVolume &tvol, BoundarySurfaceFace face, const std::shared_ptr< BinnedArray< TrackingVolume > > &insidevolarray)
protected method to set inside VolumeArray of a BoundarySurface: input:
void glueVolumes(TrackingVolume &firstVol, BoundarySurfaceFace firstFace, TrackingVolume &secondVol, BoundarySurfaceFace secondFace) const
protected method to glue two Volumes together input:
static void setOutsideVolume(TrackingVolume &tvol, BoundarySurfaceFace face, TrackingVolume *outsidevol)
protected method to set outside Volume of a BoundarySurface: input:
static void setInsideVolume(TrackingVolume &tvol, BoundarySurfaceFace face, TrackingVolume *insidevol)
protected method to set inside Volume of a BoundarySurface: input:
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
int r
Definition globals.cxx:22
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
Amg::Transform3D getTranslateZ3D(const double Z)
: Returns a shift transformation along the z-axis
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
Ensure that the ATLAS eigen extensions are properly loaded.
@ open
Definition BinningType.h:40
@ closed
Definition BinningType.h:41
BoundarySurfaceFace
Enum to describe the position of the BoundarySurface respectively to the frame orientatin of the volu...
@ binR
Definition BinningType.h:50
@ binPhi
Definition BinningType.h:51
@ binRPhi
Definition BinningType.h:52
@ binZ
Definition BinningType.h:49
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)