diff --git a/Core/include/Acts/Geometry/BoundarySurfaceT.hpp b/Core/include/Acts/Geometry/BoundarySurfaceT.hpp index 6dd3dbe8b14b2080d863193f8ddbe27a874cb99d..52bb1f2283f7c5efa06b949ced79e69b1ce4ea44 100644 --- a/Core/include/Acts/Geometry/BoundarySurfaceT.hpp +++ b/Core/include/Acts/Geometry/BoundarySurfaceT.hpp @@ -127,17 +127,18 @@ class BoundarySurfaceT { /// Virtual Destructor virtual ~BoundarySurfaceT() = default; - /// Helper metho: attach a Volume to this BoundarySurfaceT - /// this si done during the geometry construction and only called by + protected: + /// Helper method: attach a Volume to this BoundarySurfaceT + /// this is done during the geometry construction and only called by /// the friend templated volume /// /// @param gctx The current geometry context object, e.g. alignment /// @param volume The volume to be attached /// @param inout The boundary orientation @todo update to along/opposite - void attachVolume(VolumePtr volume, BoundaryOrientation inout); + void attachVolume(const T* volume, BoundaryOrientation inout); - /// Helper metho: attach a Volume to this BoundarySurfaceT - /// this si done during the geometry construction and only called by + /// Helper method: attach a Volume to this BoundarySurfaceT + /// this is done during the geometry construction and only called by /// the friend templated volume /// /// @param volumes The volume array to be attached @@ -164,12 +165,12 @@ inline const Surface& BoundarySurfaceT<T>::surfaceRepresentation() const { } template <class T> -void BoundarySurfaceT<T>::attachVolume(VolumePtr volume, +void BoundarySurfaceT<T>::attachVolume(const T* volume, BoundaryOrientation inout) { if (inout == insideVolume) { - m_insideVolume = volume.get(); + m_insideVolume = volume; } else { - m_outsideVolume = volume.get(); + m_outsideVolume = volume; } } diff --git a/Core/include/Acts/Geometry/CuboidVolumeBuilder.hpp b/Core/include/Acts/Geometry/CuboidVolumeBuilder.hpp index 64f0fa9fbc6f398d87ce44641af74f782f8b5f64..417bc2f7ba109740909096ff5f3ad31d5a4e061d 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeBuilder.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeBuilder.hpp @@ -13,6 +13,7 @@ #include <vector> #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/ITrackingVolumeBuilder.hpp" +#include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Definitions.hpp" namespace Acts { @@ -79,6 +80,10 @@ class CuboidVolumeBuilder : public ITrackingVolumeBuilder { std::vector<LayerConfig> layerCfg; // Stored layers std::vector<std::shared_ptr<const Layer>> layers; + // Configurations of confined volumes + std::vector<VolumeConfig> volumeCfg; + // Stored confined volumes + std::vector<std::shared_ptr<TrackingVolume>> trackingVolumes; // Name of the volume std::string name = "Volume"; // Material @@ -152,6 +157,9 @@ class CuboidVolumeBuilder : public ITrackingVolumeBuilder { std::pair<double, double> binningRange(const GeometryContext& gctx, const VolumeConfig& cfg) const; + void sortVolumes(std::vector<std::pair<TrackingVolumePtr, Vector3D>>& tapVec, + BinningValue bValue) const; + /// @brief This function builds a world TrackingVolume based on a given /// configuration /// @@ -167,5 +175,4 @@ class CuboidVolumeBuilder : public ITrackingVolumeBuilder { /// Configuration of the world volume Config m_cfg; }; - -} // namespace Acts +} // namespace Acts \ No newline at end of file diff --git a/Core/include/Acts/Geometry/CylinderLayer.hpp b/Core/include/Acts/Geometry/CylinderLayer.hpp index 1360143431fa61d88acd5e8c6bfb15157ed075f9..02a2b9622866b0f5f9934e4301355e2a602512d2 100644 --- a/Core/include/Acts/Geometry/CylinderLayer.hpp +++ b/Core/include/Acts/Geometry/CylinderLayer.hpp @@ -108,4 +108,4 @@ class CylinderLayer : public CylinderSurface, public Layer { CylinderLayer(const CylinderLayer& cla, const Transform3D& shift); }; -} // namespace Acts +} // namespace Acts \ No newline at end of file diff --git a/Core/include/Acts/Geometry/CylinderVolumeBuilder.hpp b/Core/include/Acts/Geometry/CylinderVolumeBuilder.hpp index 68805d61332cea43cd56d939bcc71774f9e6e3d9..fbfd797747b822614a0f189c40d5461a1b0874b5 100644 --- a/Core/include/Acts/Geometry/CylinderVolumeBuilder.hpp +++ b/Core/include/Acts/Geometry/CylinderVolumeBuilder.hpp @@ -17,6 +17,7 @@ #include <string> #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/IConfinedTrackingVolumeBuilder.hpp" #include "Acts/Geometry/ILayerBuilder.hpp" #include "Acts/Geometry/ITrackingVolumeBuilder.hpp" #include "Acts/Geometry/ITrackingVolumeHelper.hpp" @@ -53,13 +54,14 @@ enum WrappingCondition { /// VolumeConfig struct to understand the layer config struct VolumeConfig { - bool present{false}; ///< layers are present - bool wrapping{false}; ///< in what way they are binned - double rMin; ///< min parameter r - double rMax; ///< max parameter r - double zMin; ///< min parameter z - double zMax; ///< max parameter z - LayerVector layers; ///< the layers you have + bool present{false}; ///< layers are present + bool wrapping{false}; ///< in what way they are binned + double rMin; ///< min parameter r + double rMax; ///< max parameter r + double zMin; ///< min parameter z + double zMax; ///< max parameter z + LayerVector layers; ///< the layers you have + MutableTrackingVolumeVector volumes; ///< the confined volumes you have /// Default constructor VolumeConfig() @@ -474,14 +476,15 @@ class CylinderVolumeBuilder : public ITrackingVolumeBuilder { std::shared_ptr<const ITrackingVolumeHelper> trackingVolumeHelper = nullptr; /// the string based indenfication std::string volumeName = ""; - /// The dimensions of the manually created world - std::vector<double> volumeDimension = {}; /// the world material std::shared_ptr<const IVolumeMaterial> volumeMaterial = nullptr; /// build the volume to the beam line bool buildToRadiusZero = false; /// needed to build layers within the volume std::shared_ptr<const ILayerBuilder> layerBuilder = nullptr; + /// needed to build confined volumes within the volume + std::shared_ptr<const IConfinedTrackingVolumeBuilder> ctVolumeBuilder = + nullptr; /// the additional envelope in R to create rMin, rMax std::pair<double, double> layerEnvelopeR = {1. * UnitConstants::mm, 1. * UnitConstants::mm}; @@ -538,14 +541,15 @@ class CylinderVolumeBuilder : public ITrackingVolumeBuilder { /// @param [in] newLogger is the logging istance to be set void setLogger(std::unique_ptr<const Logger> newLogger); - /// Analyze the layer config to gather needed dimension + /// Analyze the config to gather needed dimension /// /// @param [in] gctx the geometry context for this building /// @param [in] lVector is the vector of layers that are parsed /// /// @return a VolumeConfig representing this layer - VolumeConfig analyzeLayers(const GeometryContext& gctx, - const LayerVector& lVector) const; + VolumeConfig analyzeContent( + const GeometryContext& gctx, const LayerVector& lVector, + const MutableTrackingVolumeVector& mtvVector) const; private: /// Configuration struct @@ -583,4 +587,4 @@ inline CylinderVolumeBuilder::Config CylinderVolumeBuilder::getConfiguration() return m_cfg; } -} // namespace Acts +} // namespace Acts \ No newline at end of file diff --git a/Core/include/Acts/Geometry/CylinderVolumeHelper.hpp b/Core/include/Acts/Geometry/CylinderVolumeHelper.hpp index d5de14615305969006c5050fce2d0c104610fae0..6188aaca6b6f46051d8c39e993dcb259da14d328 100644 --- a/Core/include/Acts/Geometry/CylinderVolumeHelper.hpp +++ b/Core/include/Acts/Geometry/CylinderVolumeHelper.hpp @@ -80,6 +80,7 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { /// together with the volume enevlope parameters /// @param volumeMaterial material properties for this TrackingVolume /// @param volumeBounds: confinement of this TrackingVolume + /// @param mtvVector (optiona) Vector of confined TrackingVolumes /// @param transform (optional) placement of this TrackingVolume /// @param volumeName volume name to be given /// @param bType (optional) BinningType - arbitrary(default) or equidistant @@ -88,7 +89,7 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { MutableTrackingVolumePtr createTrackingVolume( const GeometryContext& gctx, const LayerVector& layers, std::shared_ptr<const IVolumeMaterial> volumeMaterial, - VolumeBoundsPtr volumeBounds, + VolumeBoundsPtr volumeBounds, MutableTrackingVolumeVector mtvVector = {}, std::shared_ptr<const Transform3D> transform = nullptr, const std::string& volumeName = "UndefinedVolume", BinningType bType = arbitrary) const override; @@ -100,6 +101,7 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { /// if no bounds or HepTransform is given, they define the size /// together with the volume enevlope parameters /// @param volumeMaterial material properties for this TrackingVolume + /// @param mtvVector Vector of confined TrackingVolumes /// @param rMin minimum radius /// @param rMax maximum radius /// @param zMin minimum z @@ -110,6 +112,7 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { /// @return shared pointer to a new TrackingVolume MutableTrackingVolumePtr createTrackingVolume( const GeometryContext& gctx, const LayerVector& layers, + MutableTrackingVolumeVector mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin, double rMax, double zMin, double zMax, const std::string& volumeName = "UndefinedVolume", @@ -119,6 +122,7 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { /// @note this TrackingVolume is restricted to Translation only /// /// @param [in] gctx the geometry context for this building + /// @param mtvVector Vector of confined TrackingVolumes /// @param volumeMaterial dense material properties for this TrackingVolume /// @param rMin minimum radius /// @param rMax maximum radius @@ -130,7 +134,7 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { /// /// @return shared pointer to a new TrackingVolume MutableTrackingVolumePtr createGapTrackingVolume( - const GeometryContext& gctx, + const GeometryContext& gctx, MutableTrackingVolumeVector& mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin, double rMax, double zMin, double zMax, unsigned int materialLayers, bool cylinder = true, @@ -139,6 +143,7 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { /// Create a gap volume from dimensions and /// /// @param [in] gctx the geometry context for this building + /// @param mtvVector Vector of confined TrackingVolumes /// @param volumeMaterial dense material properties for this TrackingVolume /// @param rMin minimum radius /// @param rMax maximum radius @@ -151,7 +156,7 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { /// /// @return shared pointer to a new TrackingVolume MutableTrackingVolumePtr createGapTrackingVolume( - const GeometryContext& gctx, + const GeometryContext& gctx, MutableTrackingVolumeVector& mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin, double rMax, double zMin, double zMax, const std::vector<double>& layerPositions, bool cylinder = true, @@ -290,4 +295,4 @@ inline CylinderVolumeHelper::Config CylinderVolumeHelper::getConfiguration() const { return m_cfg; } -} // namespace Acts \ No newline at end of file +} // namespace Acts diff --git a/Core/include/Acts/Geometry/IConfinedTrackingVolumeBuilder.hpp b/Core/include/Acts/Geometry/IConfinedTrackingVolumeBuilder.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bf7f5e0dee12760394823e86608659e5f6f56b17 --- /dev/null +++ b/Core/include/Acts/Geometry/IConfinedTrackingVolumeBuilder.hpp @@ -0,0 +1,37 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2016-2018 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/////////////////////////////////////////////////////////////////// +// ITrackingVolumeBuilder.h, Acts project +/////////////////////////////////////////////////////////////////// + +#pragma once +#include <memory> +#include <vector> + +namespace Acts { + +class TrackingVolume; +using MutableTrackingVolumePtr = std::shared_ptr<TrackingVolume>; +using MutableTrackingVolumeVector = std::vector<MutableTrackingVolumePtr>; + +/// @brief This is an interface class for constructing TrackingVolumes whose are +/// confined in a mother-TrackingVolume +class IConfinedTrackingVolumeBuilder { + public: + /// Virtual destructor + virtual ~IConfinedTrackingVolumeBuilder() = default; + + /// Interface for constructing a vector of confined TrackingVolumes + virtual MutableTrackingVolumeVector centralVolumes() const = 0; + + /// Interface for retreiving the identification string of the confined volumes + virtual const std::string& identification() const = 0; +}; + +} // namespace Acts \ No newline at end of file diff --git a/Core/include/Acts/Geometry/ITrackingVolumeBuilder.hpp b/Core/include/Acts/Geometry/ITrackingVolumeBuilder.hpp index df4bd5117a1832afa4573420af2572b9923dce38..1231d1886b1c00a26ebcdbf3aa3365ff6f002323 100644 --- a/Core/include/Acts/Geometry/ITrackingVolumeBuilder.hpp +++ b/Core/include/Acts/Geometry/ITrackingVolumeBuilder.hpp @@ -56,4 +56,4 @@ class ITrackingVolumeBuilder { VolumeBoundsPtr outsideBounds = nullptr) const = 0; }; -} // namespace Acts \ No newline at end of file +} // namespace Acts diff --git a/Core/include/Acts/Geometry/ITrackingVolumeHelper.hpp b/Core/include/Acts/Geometry/ITrackingVolumeHelper.hpp index 1d94d366cf9e782091eacb84ca912f8eec1b2cb2..874e07682cbd71429f83731558f4edb2af89dde3 100644 --- a/Core/include/Acts/Geometry/ITrackingVolumeHelper.hpp +++ b/Core/include/Acts/Geometry/ITrackingVolumeHelper.hpp @@ -32,6 +32,7 @@ using VolumeBoundsPtr = std::shared_ptr<const VolumeBounds>; using LayerVector = std::vector<LayerPtr>; using TrackingVolumeVector = std::vector<TrackingVolumePtr>; +using MutableTrackingVolumeVector = std::vector<MutableTrackingVolumePtr>; /// @class ITrackingVolumeHelper /// @@ -56,6 +57,7 @@ class ITrackingVolumeHelper { /// together with the volume enevlope parameters /// @param volumeMaterial material properties for this TrackingVolume /// @param volumeBounds: confinement of this TrackingVolume + /// @param mtvVector (optional) Vector of confined TrackingVolumes /// @param transform (optional) placement of this TrackingVolume /// @param volumeName volume name to be given /// @param btype (optional) BinningType - arbitrary(default) or equidistant @@ -64,7 +66,7 @@ class ITrackingVolumeHelper { virtual MutableTrackingVolumePtr createTrackingVolume( const GeometryContext& gctx, const LayerVector& layers, std::shared_ptr<const IVolumeMaterial> volumeMaterial, - VolumeBoundsPtr volumeBounds, + VolumeBoundsPtr volumeBounds, MutableTrackingVolumeVector mtvVector = {}, std::shared_ptr<const Transform3D> transform = nullptr, const std::string& volumeName = "UndefinedVolume", BinningType btype = arbitrary) const = 0; @@ -76,6 +78,7 @@ class ITrackingVolumeHelper { /// if no bounds or HepTransform is given, they define the size /// together with the volume enevlope parameters /// @param volumeMaterial material properties for this TrackingVolume + /// @param mtvVector Vector of confined TrackingVolumes /// @param loc0Min, loc0Max, loc1Min, loc1Max : local position in space, /// this TrackingVolume is restricted to Translation only /// @param volumeName volume name to be given @@ -84,6 +87,7 @@ class ITrackingVolumeHelper { /// @return shared pointer to a new TrackingVolume virtual MutableTrackingVolumePtr createTrackingVolume( const GeometryContext& gctx, const LayerVector& layers, + MutableTrackingVolumeVector mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double loc0Min, double loc0Max, double loc1Min, double loc1Max, const std::string& volumeName = "UndefinedVolume", @@ -92,6 +96,7 @@ class ITrackingVolumeHelper { /// Create a gap volume from dimensions and /// /// @param gctx is the geometry context for witch the volume is built + /// @param mtvVector Vector of confined TrackingVolumes /// @param volumeMaterial material properties for this TrackingVolume /// @param loc0Min, loc0Max, loc1Min, loc1Max : local position in space, /// this TrackingVolume is restricted to Translation only @@ -101,7 +106,7 @@ class ITrackingVolumeHelper { /// /// @return shared pointer to a new TrackingVolume virtual MutableTrackingVolumePtr createGapTrackingVolume( - const GeometryContext& gctx, + const GeometryContext& gctx, MutableTrackingVolumeVector& mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double loc0Min, double loc0Max, double loc1Min, double loc1Max, unsigned int materialLayers, bool cylinder = true, @@ -110,6 +115,7 @@ class ITrackingVolumeHelper { /// Create a gap volume from dimensions and /// /// @param gctx is the geometry context for witch the volume is built + /// @param mtvVector Vector of confined TrackingVolumes /// @param volumeMaterial material properties for this TrackingVolume /// @param loc0Min, loc0Max, loc1Min, loc1Max local position in space, /// @param layerPositions custom layer positions @@ -119,7 +125,7 @@ class ITrackingVolumeHelper { /// /// @return shared pointer to a new TrackingVolume virtual MutableTrackingVolumePtr createGapTrackingVolume( - const GeometryContext& gctx, + const GeometryContext& gctx, MutableTrackingVolumeVector& mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double loc0Min, double loc0Max, double loc1Min, double loc1Max, const std::vector<double>& layerPositions, bool cylinder = true, @@ -137,4 +143,4 @@ class ITrackingVolumeHelper { const TrackingVolumeVector& volumes) const = 0; }; -} // namespace Acts \ No newline at end of file +} // namespace Acts diff --git a/Core/include/Acts/Geometry/TrackingVolume.hpp b/Core/include/Acts/Geometry/TrackingVolume.hpp index c0a3c0888cae2609392a0e07dc4446ceb96399b8..7a011107f869e1128d785b4a72589a97f598c77b 100644 --- a/Core/include/Acts/Geometry/TrackingVolume.hpp +++ b/Core/include/Acts/Geometry/TrackingVolume.hpp @@ -45,6 +45,7 @@ using TrackingVolumeBoundaryPtr = // possible contained using TrackingVolumeArray = BinnedArray<TrackingVolumePtr>; using TrackingVolumeVector = std::vector<TrackingVolumePtr>; +using MutableTrackingVolumeVector = std::vector<MutableTrackingVolumePtr>; using LayerArray = BinnedArray<LayerPtr>; using LayerVector = std::vector<LayerPtr>; @@ -147,10 +148,12 @@ class TrackingVolume : public Volume { std::shared_ptr<const IVolumeMaterial> volumeMaterial, std::unique_ptr<const LayerArray> containedLayers = nullptr, std::shared_ptr<const TrackingVolumeArray> containedVolumes = nullptr, + MutableTrackingVolumeVector denseVolumes = {}, const std::string& volumeName = "undefined") { return MutableTrackingVolumePtr(new TrackingVolume( std::move(htrans), std::move(volumeBounds), std::move(volumeMaterial), - std::move(containedLayers), std::move(containedVolumes), volumeName)); + std::move(containedLayers), std::move(containedVolumes), + std::move(denseVolumes), volumeName)); } /// Return the associated Layer to the global position @@ -270,10 +273,12 @@ class TrackingVolume : public Volume { /// /// @param gctx The current geometry context object, e.g. alignment /// @param gp is the global position associated with that search + /// @param tol Search position tolerance for dense volumes /// /// @return plain pointer to associated with the position const TrackingVolume* lowestTrackingVolume(const GeometryContext& gctx, - const Vector3D& gp) const; + const Vector3D& gp, + const double tol = 0.) const; /// Return the confined static layer array - if it exists /// @return the BinnedArray of static layers if exists @@ -282,6 +287,9 @@ class TrackingVolume : public Volume { /// Return the confined volumes of this container array - if it exists std::shared_ptr<const TrackingVolumeArray> confinedVolumes() const; + /// Return the confined dense volumes + const MutableTrackingVolumeVector denseVolumes() const; + /// @brief Visit all sensitive surfaces /// /// @param visitor The callable. Will be called for each sensitive surface @@ -333,8 +341,7 @@ class TrackingVolume : public Volume { /// @param neighbor is the TrackingVolume to be glued /// @param bsfNeighbor is the boudnary surface of the neighbor void glueTrackingVolume(const GeometryContext& gctx, - BoundarySurfaceFace bsfMine, - const MutableTrackingVolumePtr& neighbor, + BoundarySurfaceFace bsfMine, TrackingVolume* neighbor, BoundarySurfaceFace bsfNeighbor); /// Glue another tracking volume to this one @@ -451,9 +458,13 @@ class TrackingVolume : public Volume { std::shared_ptr<const IVolumeMaterial> volumeMaterial, std::unique_ptr<const LayerArray> staticLayerArray = nullptr, std::shared_ptr<const TrackingVolumeArray> containedVolumeArray = nullptr, + MutableTrackingVolumeVector denseVolumeVector = {}, const std::string& volumeName = "undefined"); private: + void connectDenseBoundarySurfaces( + MutableTrackingVolumeVector& confinedDenseVolumes); + /// Create Boundary Surface void createBoundarySurfaces(); @@ -499,6 +510,9 @@ class TrackingVolume : public Volume { /// Array of Volumes inside the Volume when actin as container std::shared_ptr<const TrackingVolumeArray> m_confinedVolumes = nullptr; + /// confined dense + MutableTrackingVolumeVector m_confinedDenseVolumes; + /// Volumes to glue Volumes from the outside GlueVolumesDescriptor* m_glueVolumeDescriptor{nullptr}; @@ -508,7 +522,7 @@ class TrackingVolume : public Volume { /// The gometry type for the navigation schema GeometryType m_geometryType{NumberOfGeometryTypes}; - //// Volume name for debug reasons & screen output + /// Volume name for debug reasons & screen output std::string m_name; /// color code for displaying @@ -542,6 +556,10 @@ inline const LayerArray* TrackingVolume::confinedLayers() const { return m_confinedLayers.get(); } +inline const MutableTrackingVolumeVector TrackingVolume::denseVolumes() const { + return m_confinedDenseVolumes; +} + inline std::shared_ptr<const TrackingVolumeArray> TrackingVolume::confinedVolumes() const { return m_confinedVolumes; @@ -577,4 +595,4 @@ inline bool TrackingVolume::hasBoundingVolumeHierarchy() const { #include "detail/TrackingVolume.ipp" -} // namespace Acts +} // namespace Acts \ No newline at end of file diff --git a/Core/include/Acts/Geometry/detail/TrackingVolume.ipp b/Core/include/Acts/Geometry/detail/TrackingVolume.ipp index 6fd478351b8512583a6e3328452ec680fa1ba8e5..7cdd1437dd9f332e1293b78f7e0aedf7a4df85ff 100644 --- a/Core/include/Acts/Geometry/detail/TrackingVolume.ipp +++ b/Core/include/Acts/Geometry/detail/TrackingVolume.ipp @@ -102,6 +102,23 @@ std::vector<BoundaryIntersection> TrackingVolume::compatibleBoundaries( } nonExcludedBoundaries.push_back(bSurface); } + + const std::vector<std::shared_ptr<TrackingVolume>> confinedDenseVolumes = + denseVolumes(); + for (const auto& dv : confinedDenseVolumes) { + auto& bSurfacesConfined = dv->boundarySurfaces(); + for (auto& bsIter : bSurfacesConfined) { + // get the boundary surface pointer + const BoundarySurfaceT<TrackingVolume>* bSurface = bsIter.get(); + const auto& bSurfaceRep = bSurface->surfaceRepresentation(); + // exclude the on boundary object + if (excludeObject && excludeObject == &bSurfaceRep) { + continue; + } + nonExcludedBoundaries.push_back(bSurface); + } + } + return sorter(gctx, nonExcludedBoundaries, position, direction, options, corrfnc); } diff --git a/Core/include/Acts/Propagator/detail/ConstrainedStep.hpp b/Core/include/Acts/Propagator/detail/ConstrainedStep.hpp index 8968912d85579b160667f6b7a6b6759250277814..ec66aa2a12591e24b06819c3754923bec751bc00 100644 --- a/Core/include/Acts/Propagator/detail/ConstrainedStep.hpp +++ b/Core/include/Acts/Propagator/detail/ConstrainedStep.hpp @@ -23,7 +23,7 @@ namespace detail { struct ConstrainedStep { /// the types of constraints /// from accuracy - this can vary up and down given a good step estimator - /// form actor - this would be a typical navigation step + /// from actor - this would be a typical navigation step /// from aborter - this would be a target condition /// from user - this is user given for what reason ever enum Type : int { accuracy = 0, actor = 1, aborter = 2, user = 3 }; diff --git a/Core/src/Geometry/CuboidVolumeBuilder.cpp b/Core/src/Geometry/CuboidVolumeBuilder.cpp index 119b51137ae4abd0145465e15622bc0855caad9b..b0fcfe2aba3df58cc47ad878b581163435376c65 100644 --- a/Core/src/Geometry/CuboidVolumeBuilder.cpp +++ b/Core/src/Geometry/CuboidVolumeBuilder.cpp @@ -143,10 +143,23 @@ std::shared_ptr<Acts::TrackingVolume> Acts::CuboidVolumeBuilder::buildVolume( layArrCreator.layerArray(gctx, layVec, minMax.first, minMax.second, BinningType::arbitrary, BinningValue::binX)); - // Build TrackingVolume - auto trackVolume = TrackingVolume::create( - std::make_shared<const Transform3D>(trafo), bounds, cfg.volumeMaterial, - std::move(layArr), nullptr, cfg.name); + // Build confined volumes + if (cfg.trackingVolumes.empty()) + for (VolumeConfig vc : cfg.volumeCfg) + cfg.trackingVolumes.push_back(buildVolume(gctx, vc)); + + std::shared_ptr<TrackingVolume> trackVolume; + if (layVec.empty()) { + // Build TrackingVolume + trackVolume = TrackingVolume::create( + std::make_shared<const Transform3D>(trafo), bounds, cfg.volumeMaterial, + nullptr, nullptr, cfg.trackingVolumes, cfg.name); + } else { + // Build TrackingVolume + trackVolume = TrackingVolume::create( + std::make_shared<const Transform3D>(trafo), bounds, cfg.volumeMaterial, + std::move(layArr), nullptr, cfg.trackingVolumes, cfg.name); + } trackVolume->sign(GeometrySignature::Global); return trackVolume; @@ -165,10 +178,10 @@ Acts::MutableTrackingVolumePtr Acts::CuboidVolumeBuilder::trackingVolume( // Glue volumes for (unsigned int i = 0; i < volumes.size() - 1; i++) { volumes[i + 1]->glueTrackingVolume( - gctx, BoundarySurfaceFace::negativeFaceYZ, volumes[i], + gctx, BoundarySurfaceFace::negativeFaceYZ, volumes[i].get(), BoundarySurfaceFace::positiveFaceYZ); volumes[i]->glueTrackingVolume(gctx, BoundarySurfaceFace::positiveFaceYZ, - volumes[i + 1], + volumes[i + 1].get(), BoundarySurfaceFace::negativeFaceYZ); } @@ -210,4 +223,4 @@ Acts::MutableTrackingVolumePtr Acts::CuboidVolumeBuilder::trackingVolume( mtvp->sign(GeometrySignature::Global); return mtvp; -} +} \ No newline at end of file diff --git a/Core/src/Geometry/CylinderVolumeBuilder.cpp b/Core/src/Geometry/CylinderVolumeBuilder.cpp index d7198052aa6898d05b0ac68145a0e3f49ae540fb..790e202630a54e52102cc7b12017d5ff5e38280b 100644 --- a/Core/src/Geometry/CylinderVolumeBuilder.cpp +++ b/Core/src/Geometry/CylinderVolumeBuilder.cpp @@ -73,6 +73,13 @@ Acts::CylinderVolumeBuilder::trackingVolume( // the positive Layer positiveLayers = m_cfg.layerBuilder->positiveLayers(gctx); } + + // Build the confined volumes + MutableTrackingVolumeVector centralVolumes; + if (m_cfg.ctVolumeBuilder) { + centralVolumes = m_cfg.ctVolumeBuilder->centralVolumes(); + } + // (0) PREP WORK ------------------------------------------------ // // a) volume config of the existing volume @@ -127,9 +134,9 @@ Acts::CylinderVolumeBuilder::trackingVolume( // Find out with Layer analysis // analyze the layers - wConfig.nVolumeConfig = analyzeLayers(gctx, negativeLayers); - wConfig.cVolumeConfig = analyzeLayers(gctx, centralLayers); - wConfig.pVolumeConfig = analyzeLayers(gctx, positiveLayers); + wConfig.nVolumeConfig = analyzeContent(gctx, negativeLayers, {}); // TODO + wConfig.cVolumeConfig = analyzeContent(gctx, centralLayers, centralVolumes); + wConfig.pVolumeConfig = analyzeContent(gctx, positiveLayers, {}); // TODO std::string layerConfiguration = "|"; if (wConfig.nVolumeConfig) { @@ -184,7 +191,8 @@ Acts::CylinderVolumeBuilder::trackingVolume( auto barrel = wConfig.cVolumeConfig ? tvHelper->createTrackingVolume( - gctx, wConfig.cVolumeConfig.layers, m_cfg.volumeMaterial, + gctx, wConfig.cVolumeConfig.layers, + wConfig.cVolumeConfig.volumes, m_cfg.volumeMaterial, wConfig.cVolumeConfig.rMin, wConfig.cVolumeConfig.rMax, wConfig.cVolumeConfig.zMin, wConfig.cVolumeConfig.zMax, m_cfg.volumeName + "::Barrel") @@ -194,7 +202,8 @@ Acts::CylinderVolumeBuilder::trackingVolume( auto nEndcap = wConfig.nVolumeConfig ? tvHelper->createTrackingVolume( - gctx, wConfig.nVolumeConfig.layers, m_cfg.volumeMaterial, + gctx, wConfig.nVolumeConfig.layers, + wConfig.cVolumeConfig.volumes, m_cfg.volumeMaterial, wConfig.nVolumeConfig.rMin, wConfig.nVolumeConfig.rMax, wConfig.nVolumeConfig.zMin, wConfig.nVolumeConfig.zMax, m_cfg.volumeName + "::NegativeEndcap") @@ -204,7 +213,8 @@ Acts::CylinderVolumeBuilder::trackingVolume( auto pEndcap = wConfig.pVolumeConfig ? tvHelper->createTrackingVolume( - gctx, wConfig.pVolumeConfig.layers, m_cfg.volumeMaterial, + gctx, wConfig.pVolumeConfig.layers, + wConfig.cVolumeConfig.volumes, m_cfg.volumeMaterial, wConfig.pVolumeConfig.rMin, wConfig.pVolumeConfig.rMax, wConfig.pVolumeConfig.zMin, wConfig.pVolumeConfig.zMax, m_cfg.volumeName + "::PositiveEndcap") @@ -283,9 +293,10 @@ Acts::CylinderVolumeBuilder::trackingVolume( if (wConfig.fGapVolumeConfig) { // create the gap volume auto fGap = tvHelper->createGapTrackingVolume( - gctx, m_cfg.volumeMaterial, wConfig.fGapVolumeConfig.rMin, - wConfig.fGapVolumeConfig.rMax, wConfig.fGapVolumeConfig.zMin, - wConfig.fGapVolumeConfig.zMax, 1, false, m_cfg.volumeName + "::fGap"); + gctx, wConfig.cVolumeConfig.volumes, m_cfg.volumeMaterial, + wConfig.fGapVolumeConfig.rMin, wConfig.fGapVolumeConfig.rMax, + wConfig.fGapVolumeConfig.zMin, wConfig.fGapVolumeConfig.zMax, 1, + false, m_cfg.volumeName + "::fGap"); // push it back into the list existingContainer.push_back(fGap); } @@ -293,9 +304,10 @@ Acts::CylinderVolumeBuilder::trackingVolume( if (wConfig.sGapVolumeConfig) { // create the gap volume auto sGap = tvHelper->createGapTrackingVolume( - gctx, m_cfg.volumeMaterial, wConfig.sGapVolumeConfig.rMin, - wConfig.sGapVolumeConfig.rMax, wConfig.sGapVolumeConfig.zMin, - wConfig.sGapVolumeConfig.zMax, 1, false, m_cfg.volumeName + "::sGap"); + gctx, wConfig.cVolumeConfig.volumes, m_cfg.volumeMaterial, + wConfig.sGapVolumeConfig.rMin, wConfig.sGapVolumeConfig.rMax, + wConfig.sGapVolumeConfig.zMin, wConfig.sGapVolumeConfig.zMax, 1, + false, m_cfg.volumeName + "::sGap"); // push it back into the list existingContainer.push_back(sGap); } @@ -354,14 +366,15 @@ Acts::CylinderVolumeBuilder::trackingVolume( } // ----------------------------- -Acts::VolumeConfig Acts::CylinderVolumeBuilder::analyzeLayers( - const GeometryContext& gctx, const LayerVector& lVector) const { +Acts::VolumeConfig Acts::CylinderVolumeBuilder::analyzeContent( + const GeometryContext& gctx, const LayerVector& lVector, + const MutableTrackingVolumeVector& mtvVector) const { // @TODO add envelope tolerance // // return object VolumeConfig lConfig; // only if the vector is present it can actually be analyzed - if (!lVector.empty()) { + if (!lVector.empty() || !mtvVector.empty()) { // we have layers lConfig.present = true; // loop over the layer @@ -402,9 +415,22 @@ Acts::VolumeConfig Acts::CylinderVolumeBuilder::analyzeLayers( //!< @todo check for Endcap Ring config } } + for (auto& volume : mtvVector) { + const CylinderVolumeBounds* cvBounds = + dynamic_cast<const CylinderVolumeBounds*>(&volume->volumeBounds()); + if (cvBounds != nullptr) { + takeSmaller(lConfig.rMin, cvBounds->innerRadius()); + takeBigger(lConfig.rMax, cvBounds->outerRadius()); + takeSmaller(lConfig.zMin, -cvBounds->halflengthZ()); + takeBigger(lConfig.zMax, cvBounds->halflengthZ()); + } + } } + // set the layers to the layer vector lConfig.layers = lVector; + // set the layers to the layer vector + lConfig.volumes = mtvVector; // overwrite to radius 0 if needed if (m_cfg.buildToRadiusZero) { ACTS_VERBOSE("This layer builder is configured to build to the beamline."); @@ -413,4 +439,4 @@ Acts::VolumeConfig Acts::CylinderVolumeBuilder::analyzeLayers( // and return what you have return lConfig; -} +} \ No newline at end of file diff --git a/Core/src/Geometry/CylinderVolumeHelper.cpp b/Core/src/Geometry/CylinderVolumeHelper.cpp index 94ed74d6a7f8fca99900f76c731ef412f21f2b40..3fd0ef80ed5303e75bcd7ee2124ebcf10c33e2fc 100644 --- a/Core/src/Geometry/CylinderVolumeHelper.cpp +++ b/Core/src/Geometry/CylinderVolumeHelper.cpp @@ -53,6 +53,7 @@ Acts::CylinderVolumeHelper::createTrackingVolume( const GeometryContext& gctx, const LayerVector& layers, std::shared_ptr<const IVolumeMaterial> volumeMaterial, std::shared_ptr<const VolumeBounds> volumeBounds, + MutableTrackingVolumeVector mtvVector, std::shared_ptr<const Transform3D> transform, const std::string& volumeName, BinningType bType) const { // the final one to build / sensitive Volume / Bounds @@ -132,7 +133,8 @@ Acts::CylinderVolumeHelper::createTrackingVolume( : std::shared_ptr<const VolumeBounds>(cylinderBounds); // finally create the TrackingVolume tVolume = TrackingVolume::create(transform, volumeBoundsFinal, volumeMaterial, - std::move(layerArray), nullptr, volumeName); + std::move(layerArray), nullptr, mtvVector, + volumeName); // screen output ACTS_VERBOSE( "Created cylindrical volume at z-position :" << tVolume->center().z()); @@ -144,6 +146,7 @@ Acts::CylinderVolumeHelper::createTrackingVolume( std::shared_ptr<Acts::TrackingVolume> Acts::CylinderVolumeHelper::createTrackingVolume( const GeometryContext& gctx, const LayerVector& layers, + MutableTrackingVolumeVector mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin, double rMax, double zMin, double zMax, const std::string& volumeName, BinningType bType) const { @@ -179,13 +182,13 @@ Acts::CylinderVolumeHelper::createTrackingVolume( : nullptr; // call to the creation method with Bounds & Translation3D return createTrackingVolume(gctx, layers, volumeMaterial, - VolumeBoundsPtr(cBounds), transform, volumeName, - bType); + VolumeBoundsPtr(cBounds), mtvVector, transform, + volumeName, bType); } std::shared_ptr<Acts::TrackingVolume> Acts::CylinderVolumeHelper::createGapTrackingVolume( - const GeometryContext& gctx, + const GeometryContext& gctx, MutableTrackingVolumeVector& mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin, double rMax, double zMin, double zMax, unsigned int materialLayers, bool cylinder, const std::string& volumeName) const { @@ -211,14 +214,14 @@ Acts::CylinderVolumeHelper::createGapTrackingVolume( } // now call the main method - return createGapTrackingVolume(gctx, volumeMaterial, rMin, rMax, zMin, zMax, - layerPositions, cylinder, volumeName, - arbitrary); + return createGapTrackingVolume(gctx, mtvVector, volumeMaterial, rMin, rMax, + zMin, zMax, layerPositions, cylinder, + volumeName, arbitrary); } std::shared_ptr<Acts::TrackingVolume> Acts::CylinderVolumeHelper::createGapTrackingVolume( - const GeometryContext& gctx, + const GeometryContext& gctx, MutableTrackingVolumeVector& mtvVector, std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin, double rMax, double zMin, double zMax, const std::vector<double>& layerPositions, bool cylinder, @@ -257,8 +260,8 @@ Acts::CylinderVolumeHelper::createGapTrackingVolume( } } // now call the createTrackingVolume() method - return createTrackingVolume(gctx, layers, volumeMaterial, rMin, rMax, zMin, - zMax, volumeName, bType); + return createTrackingVolume(gctx, layers, mtvVector, volumeMaterial, rMin, + rMax, zMin, zMax, volumeName, bType); } std::shared_ptr<Acts::TrackingVolume> @@ -743,8 +746,8 @@ void Acts::CylinderVolumeHelper::glueTrackingVolumes( << glueVolTwo->volumeName() << " @ " << faceTwo << " ]"); // one to one is easy - mutableGlueVolOne->glueTrackingVolume(gctx, faceOne, mutableGlueVolTwo, - faceTwo); + mutableGlueVolOne->glueTrackingVolume(gctx, faceOne, + mutableGlueVolTwo.get(), faceTwo); } else if (volOneGlueVols <= 1) { // (ii) one -> many diff --git a/Core/src/Geometry/SurfaceArrayCreator.cpp b/Core/src/Geometry/SurfaceArrayCreator.cpp index 471ca727ce305aa7ebea0239509d4a9411b588f0..7480106cd99bda47d30e5d2db083475ae18ec5b0 100644 --- a/Core/src/Geometry/SurfaceArrayCreator.cpp +++ b/Core/src/Geometry/SurfaceArrayCreator.cpp @@ -324,7 +324,6 @@ Acts::SurfaceArrayCreator::surfaceArrayOnPlane( ACTS_VERBOSE(" -- with " << surfaces.size() << " surfaces.") ACTS_VERBOSE(" -- with " << bins1 << " x " << bins2 << " = " << bins1 * bins2 << " bins."); - // Transformation Transform3D transform = transformOpt != nullptr ? *transformOpt : Transform3D::Identity(); diff --git a/Core/src/Geometry/TrackingVolume.cpp b/Core/src/Geometry/TrackingVolume.cpp index 61c3800e44c007ee86eae3f2adb3791fcfafb930..d8e8c2b96979bf9bc5addfbfbda1370edc13b99c 100644 --- a/Core/src/Geometry/TrackingVolume.cpp +++ b/Core/src/Geometry/TrackingVolume.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2016-2018 CERN for the benefit of the Acts project +// Copyright (C) 2016-2019 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -47,14 +47,17 @@ Acts::TrackingVolume::TrackingVolume( std::shared_ptr<const IVolumeMaterial> volumeMaterial, std::unique_ptr<const LayerArray> staticLayerArray, std::shared_ptr<const TrackingVolumeArray> containedVolumeArray, + MutableTrackingVolumeVector denseVolumeVector, const std::string& volumeName) : Volume(std::move(htrans), std::move(volumeBounds)), m_volumeMaterial(std::move(volumeMaterial)), m_confinedLayers(std::move(staticLayerArray)), m_confinedVolumes(std::move(containedVolumeArray)), + m_confinedDenseVolumes({}), m_name(volumeName) { createBoundarySurfaces(); interlinkLayers(); + connectDenseBoundarySurfaces(denseVolumeVector); } // constructor for arguments @@ -84,12 +87,19 @@ Acts::TrackingVolume::~TrackingVolume() { } const Acts::TrackingVolume* Acts::TrackingVolume::lowestTrackingVolume( - const GeometryContext& /*gctx*/, const Vector3D& gp) const { + const GeometryContext& /*gctx*/, const Vector3D& gp, + const double tol) const { // confined static volumes - highest hierarchy if (m_confinedVolumes) { return (m_confinedVolumes->object(gp).get()); } + // search for dense volumes + if (!m_confinedDenseVolumes.empty()) + for (auto& denseVolume : m_confinedDenseVolumes) + if (denseVolume->inside(gp, tol)) + return denseVolume.get(); + // there is no lower sub structure return this; } @@ -110,6 +120,15 @@ void Acts::TrackingVolume::sign(GeometrySignature geosign, mutableVolumesIter->sign(geosign, geotype); } } + + // finally for confined dense volumes + if (!m_confinedDenseVolumes.empty()) { + for (auto& volumesIter : m_confinedDenseVolumes) { + auto mutableVolumesIter = + std::const_pointer_cast<TrackingVolume>(volumesIter); + mutableVolumesIter->sign(geosign, geotype); + } + } } const std::vector< @@ -118,6 +137,47 @@ Acts::TrackingVolume::boundarySurfaces() const { return (m_boundarySurfaces); } +void Acts::TrackingVolume::connectDenseBoundarySurfaces( + MutableTrackingVolumeVector& confinedDenseVolumes) { + if (!confinedDenseVolumes.empty()) { + BoundaryOrientation bo; + // Walk over each dense volume + for (auto& confDenseVol : confinedDenseVolumes) { + // Walk over each boundary surface of the volume + auto& boundSur = confDenseVol->boundarySurfaces(); + for (unsigned int i = 0; i < boundSur.size(); i++) { + // Skip empty entries since we do not know the shape of the dense volume + // and therewith the used indices + if (boundSur.at(i) == nullptr) { + continue; + } + + // Use mother volume as the opposite direction of the already used + // direction + auto mutableBs = + std::const_pointer_cast<BoundarySurfaceT<TrackingVolume>>( + boundSur.at(i)); + if (mutableBs->m_insideVolume != nullptr && + mutableBs->m_outsideVolume == nullptr) { + bo = BoundaryOrientation::outsideVolume; + mutableBs->attachVolume(this, bo); + } else { + if (mutableBs->m_insideVolume == nullptr && + mutableBs->m_outsideVolume != nullptr) { + bo = BoundaryOrientation::insideVolume; + mutableBs->attachVolume(this, bo); + } + } + + // Update the boundary + confDenseVol->updateBoundarySurface((BoundarySurfaceFace)i, mutableBs); + } + // Store the volume + m_confinedDenseVolumes.push_back(std::move(confDenseVol)); + } + } +} + void Acts::TrackingVolume::createBoundarySurfaces() { // transform Surfaces To BoundarySurfaces std::vector<std::shared_ptr<const Surface>> surfaces = @@ -143,10 +203,10 @@ void Acts::TrackingVolume::createBoundarySurfaces() { } } -void Acts::TrackingVolume::glueTrackingVolume( - const GeometryContext& gctx, BoundarySurfaceFace bsfMine, - const std::shared_ptr<TrackingVolume>& neighbor, - BoundarySurfaceFace bsfNeighbor) { +void Acts::TrackingVolume::glueTrackingVolume(const GeometryContext& gctx, + BoundarySurfaceFace bsfMine, + TrackingVolume* neighbor, + BoundarySurfaceFace bsfNeighbor) { // Find the connection of the two tracking volumes: binR returns the center // except for cylindrical volumes Vector3D bPosition(binningPosition(gctx, binR)); @@ -343,6 +403,7 @@ void Acts::TrackingVolume::closeGeometry( materialDecorator->decorate(*thisVolume); } + this->assignGeoID(volumeID); // loop over the boundary surfaces GeometryID::Value iboundary = 0; // loop over the boundary surfaces @@ -397,6 +458,16 @@ void Acts::TrackingVolume::closeGeometry( auto mutableVolumesIter = std::const_pointer_cast<TrackingVolume>(volumesIter); mutableVolumesIter->closeGeometry(materialDecorator, volumeMap, vol); + mutableVolumesIter->setMotherVolume(this); + } + } + + if (!m_confinedDenseVolumes.empty()) { + for (auto& volumesIter : m_confinedDenseVolumes) { + auto mutableVolumesIter = + std::const_pointer_cast<TrackingVolume>(volumesIter); + mutableVolumesIter->closeGeometry(materialDecorator, volumeMap, vol); + mutableVolumesIter->setMotherVolume(this); } } } @@ -422,4 +493,4 @@ void Acts::TrackingVolume::visitSurfaces( volume->visitSurfaces(visitor); } } -} +} \ No newline at end of file diff --git a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp index f05bb9686f17a0034d6f37522ea94a613b8abf63..c120a301abf4f31b789571133fc8ba598ad394c5 100644 --- a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp +++ b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp @@ -172,4 +172,12 @@ void collectCompounds_dd4hep(dd4hep::DetElement& detElement, /// detElement void collectLayers_dd4hep(dd4hep::DetElement& detElement, std::vector<dd4hep::DetElement>& layers); -} // namespace Acts + +/// Method internally used by convertDD4hepDetector +/// @param [in] detElement the dd4hep::DetElement of the volume of which the +/// volumes should be collected +/// @param [out] volumes the DD4hep::DetElements of the volumes contained by +/// detElement +void collectVolumes_dd4hep(dd4hep::DetElement& detElement, + std::vector<dd4hep::DetElement>& volumes); +} // namespace Acts \ No newline at end of file diff --git a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepVolumeBuilder.hpp b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepVolumeBuilder.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d25a200721d5175a99c3b7a15c2215545d1292b2 --- /dev/null +++ b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepVolumeBuilder.hpp @@ -0,0 +1,106 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2018 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once +#include "Acts/Geometry/IConfinedTrackingVolumeBuilder.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "Acts/Utilities/Definitions.hpp" +#include "Acts/Utilities/Logger.hpp" + +class TrackingVolume; +using MutableTrackingVolumePtr = std::shared_ptr<TrackingVolume>; +using MutableTrackingVolumeVector = std::vector<MutableTrackingVolumePtr>; + +class TGeoMatrix; + +namespace dd4hep { +class DetElement; +} + +namespace Acts { + +/// @brief build confined TrackingVolumes of one cylinder setup from DD4hep +/// input. +/// +/// This class is an implementation of the Acts::IConfinedTrackingVolumeBuilder, +/// creating the central (volumes of barrel), the negative and positive volumes +/// (volumes of endcaps) of one hierarchy (e.g. ECal, HCal...) with input from +/// DD4hep. + +class DD4hepVolumeBuilder : public IConfinedTrackingVolumeBuilder { + public: + /// @struct Config + /// Nested configuration struct for steering of the volume builder + struct Config { + /// string based identification + std::string configurationName = "undefined"; + /// Vector of central confined volumes + std::vector<dd4hep::DetElement> centralVolumes; + }; + + /// Constructor + /// @param [in] config is the configuration struct + /// @param [in] logger is the logging instance + DD4hepVolumeBuilder(const Acts::DD4hepVolumeBuilder::Config& config, + std::unique_ptr<const Logger> logger); + + /// Destructor + ~DD4hepVolumeBuilder() override; + + /// @brief Builder method for cylindrical, confined volume + /// + /// @return The vector of TrackingVolumes at the central sector + MutableTrackingVolumeVector centralVolumes() const final; + + /// Name identification + /// @return The string based identification of this configuration + const std::string& identification() const final; + + /// Set the configuration object + /// @param [in] Config is the configuration struct + void setConfiguration(const Config& config); + + /// Get the configuration object + /// @return The used configuration struct + Config getConfiguration() const; + + /// Set logging instance + /// @param [in] logger Logger in use + void setLogger(std::unique_ptr<const Logger> logger); + + private: + /// Configruation object + Config m_cfg; + + /// Logging instance + std::unique_ptr<const Logger> m_logger; + + /// Private access to the logger + /// @return Used logger + const Logger& logger() const { return *m_logger; } + + /// @brief Converter of the transformation of a volume from DD4hep to Acts + /// formalism + /// + /// @param [in] tGeoTrans Transformation of the DD4hep DetElement + /// @return Pointer to the corresponding Acts transformation + std::shared_ptr<const Acts::Transform3D> convertTransform( + const TGeoMatrix* tGeoTrans) const; +}; + +inline const std::string& DD4hepVolumeBuilder::identification() const { + return m_cfg.configurationName; +} + +inline DD4hepVolumeBuilder::Config DD4hepVolumeBuilder::getConfiguration() + const { + return m_cfg; +} + +} // namespace Acts \ No newline at end of file diff --git a/Plugins/DD4hep/src/ConvertDD4hepDetector.cpp b/Plugins/DD4hep/src/ConvertDD4hepDetector.cpp index f44d826a0cf012abb16ff234f4a98c4a7d25be98..867cddaaaae75330a1b7fb97daca4ecaf6bf84d7 100644 --- a/Plugins/DD4hep/src/ConvertDD4hepDetector.cpp +++ b/Plugins/DD4hep/src/ConvertDD4hepDetector.cpp @@ -24,6 +24,7 @@ #include "Acts/Plugins/DD4hep/ActsExtension.hpp" #include "Acts/Plugins/DD4hep/ConvertDD4hepMaterial.hpp" #include "Acts/Plugins/DD4hep/DD4hepLayerBuilder.hpp" +#include "Acts/Plugins/DD4hep/DD4hepVolumeBuilder.hpp" #include "Acts/Utilities/BinningData.hpp" #include "TGeoManager.h" @@ -424,8 +425,9 @@ std::shared_ptr<const CylinderVolumeBuilder> volumeBuilder_dd4hep( << subDetector.name() << " is a (sensitive) Barrel volume - building barrel."); /// the dd4hep::DetElements of the layers of the central volume - std::vector<dd4hep::DetElement> centralLayers; + std::vector<dd4hep::DetElement> centralLayers, centralVolumes; collectLayers_dd4hep(subDetector, centralLayers); + collectVolumes_dd4hep(subDetector, centralVolumes); // configure SurfaceArrayCreator auto surfaceArrayCreator = @@ -449,6 +451,16 @@ std::shared_ptr<const CylinderVolumeBuilder> volumeBuilder_dd4hep( Acts::getDefaultLogger(std::string("D2A_LB_") + subDetector.name(), loggingLevel)); + // Configure DD4hepVolumeBuilder + Acts::DD4hepVolumeBuilder::Config vbConfig; + vbConfig.configurationName = subDetector.name(); + vbConfig.centralVolumes = centralVolumes; + auto dd4hepVolumeBuilder = + std::make_shared<const Acts::DD4hepVolumeBuilder>( + vbConfig, + Acts::getDefaultLogger(std::string("D2A_VB_") + subDetector.name(), + loggingLevel)); + // the configuration object of the volume builder Acts::CylinderVolumeBuilder::Config cvbConfig; // get the dimensions of the volume @@ -475,6 +487,7 @@ std::shared_ptr<const CylinderVolumeBuilder> volumeBuilder_dd4hep( cvbConfig.volumeName = subDetector.name(); cvbConfig.volumeMaterial = volumeMaterial; cvbConfig.layerBuilder = dd4hepLayerBuilder; + cvbConfig.ctVolumeBuilder = dd4hepVolumeBuilder; auto cylinderVolumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>( cvbConfig, @@ -583,4 +596,22 @@ void collectLayers_dd4hep(dd4hep::DetElement& detElement, collectLayers_dd4hep(childDetElement, layers); } } -} // End of namespace Acts + +void collectVolumes_dd4hep(dd4hep::DetElement& detElement, + std::vector<dd4hep::DetElement>& volumes) { + const dd4hep::DetElement::Children& children = detElement.children(); + for (auto& child : children) { + dd4hep::DetElement childDetElement = child.second; + Acts::ActsExtension* detExtension = nullptr; + try { + detExtension = childDetElement.extension<Acts::ActsExtension>(); + } catch (std::runtime_error& e) { + } + if ((detExtension != nullptr) && detExtension->hasType("volume")) { + volumes.push_back(childDetElement); + continue; + } + collectVolumes_dd4hep(childDetElement, volumes); + } +} +} // End of namespace Acts \ No newline at end of file diff --git a/Plugins/DD4hep/src/DD4hepVolumeBuilder.cpp b/Plugins/DD4hep/src/DD4hepVolumeBuilder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f522278646eb40779040de14e529767960af241f --- /dev/null +++ b/Plugins/DD4hep/src/DD4hepVolumeBuilder.cpp @@ -0,0 +1,112 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2018 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/DD4hep/DD4hepVolumeBuilder.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Material/HomogeneousVolumeMaterial.hpp" +#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp" +#include "Acts/Plugins/TGeo/TGeoPrimitivesHelpers.hpp" +#include "Acts/Surfaces/CylinderSurface.hpp" +#include "Acts/Surfaces/RadialBounds.hpp" +#include "Acts/Utilities/Units.hpp" +#include "DD4hep/Detector.h" + +#include <boost/algorithm/string.hpp> + +Acts::DD4hepVolumeBuilder::DD4hepVolumeBuilder( + const Acts::DD4hepVolumeBuilder::Config& config, + std::unique_ptr<const Logger> logger) + : m_cfg(), m_logger(std::move(logger)) { + setConfiguration(config); +} + +Acts::DD4hepVolumeBuilder::~DD4hepVolumeBuilder() = default; + +void Acts::DD4hepVolumeBuilder::setConfiguration( + const Acts::DD4hepVolumeBuilder::Config& config) { + m_cfg = config; +} + +std::vector<std::shared_ptr<Acts::TrackingVolume>> +Acts::DD4hepVolumeBuilder::centralVolumes() const { + if (m_cfg.centralVolumes.empty()) { + ACTS_VERBOSE("[L] No layers handed over for central volume!"); + return {}; + } + + ACTS_VERBOSE( + "[L] Received layers for central volume -> creating " + "cylindrical layers"); + + // Resulting volumes + MutableTrackingVolumeVector volumes; + // Inner/outer radius and half length of the barrel + double rMin, rMax, dz; + + // Go through volumes + for (auto& detElement : m_cfg.centralVolumes) { + // Access the global transformation matrix of the volume + auto transform = + convertTransform(&(detElement.nominal().worldTransformation())); + // Get the shape of the volume + TGeoShape* geoShape = detElement.placement().ptr()->GetVolume()->GetShape(); + + if (geoShape != nullptr) { + TGeoTubeSeg* tube = dynamic_cast<TGeoTubeSeg*>(geoShape); + if (tube == nullptr) + ACTS_ERROR( + "[L] Cylinder layer has wrong shape - needs to be TGeoTubeSeg!"); + + // Extract the boundaries + rMin = tube->GetRmin() * units::_cm; + rMax = tube->GetRmax() * units::_cm; + dz = tube->GetDz() * units::_cm; + + } else { + throw std::logic_error( + std::string("Volume DetElement: ") + detElement.name() + + std::string(" has not a shape " + "added to its extension. Please check your detector " + "constructor!")); + } + // Build boundaries + CylinderVolumeBounds cvBounds(rMin, rMax, dz); + // Extract material if available + dd4hep::Material ddmaterial = detElement.volume().material(); + if (!boost::iequals(ddmaterial.name(), "vacuum")) { + Material volumeMaterial(ddmaterial.radLength() * Acts::units::_cm, + ddmaterial.intLength() * Acts::units::_cm, + ddmaterial.A(), ddmaterial.Z(), + ddmaterial.density() / pow(Acts::units::_cm, 3)); + + volumes.push_back(TrackingVolume::create( + transform, std::make_shared<const CylinderVolumeBounds>(cvBounds), + std::make_shared<const HomogeneousVolumeMaterial>(volumeMaterial))); + } else { + volumes.push_back(TrackingVolume::create( + transform, std::make_shared<const CylinderVolumeBounds>(cvBounds))); + } + } + return volumes; +} + +std::shared_ptr<const Acts::Transform3D> +Acts::DD4hepVolumeBuilder::convertTransform(const TGeoMatrix* tGeoTrans) const { + // Get the placement and orientation in respect to its mother + const Double_t* rotation = tGeoTrans->GetRotationMatrix(); + const Double_t* translation = tGeoTrans->GetTranslation(); + auto transform = + std::make_shared<const Transform3D>(TGeoPrimitivesHelpers::makeTransform( + Acts::Vector3D(rotation[0], rotation[3], rotation[6]), + Acts::Vector3D(rotation[1], rotation[4], rotation[7]), + Acts::Vector3D(rotation[2], rotation[5], rotation[8]), + Acts::Vector3D(translation[0] * units::_cm, + translation[1] * units::_cm, + translation[2] * units::_cm))); + return (transform); +} diff --git a/Plugins/TGeo/include/Acts/Plugins/TGeo/TGeoPrimitivesHelpers.hpp b/Plugins/TGeo/include/Acts/Plugins/TGeo/TGeoPrimitivesHelpers.hpp index c0c01836ec3a34a0472e8edd28c6b7610bd1df17..b7fb7469bd563e3f2a90ca865b281146ec43a99f 100644 --- a/Plugins/TGeo/include/Acts/Plugins/TGeo/TGeoPrimitivesHelpers.hpp +++ b/Plugins/TGeo/include/Acts/Plugins/TGeo/TGeoPrimitivesHelpers.hpp @@ -14,10 +14,10 @@ namespace Acts { namespace TGeoPrimitivesHelpers { -Transform3D makeTransform(const Eigen::Vector3d& rotationMatrixCol0, - const Eigen::Vector3d& rotationMatrixCol1, - const Eigen::Vector3d& rotationMatrixCol2, - const Eigen::Vector3d& translation) { +inline Transform3D makeTransform(const Eigen::Vector3d& rotationMatrixCol0, + const Eigen::Vector3d& rotationMatrixCol1, + const Eigen::Vector3d& rotationMatrixCol2, + const Eigen::Vector3d& translation) { Transform3D trf; trf.matrix().block(0, 0, 3, 1) = rotationMatrixCol0; trf.matrix().block(0, 1, 3, 1) = rotationMatrixCol1; diff --git a/Tests/Core/CommonHelpers/include/Acts/Tests/CommonHelpers/CubicTrackingGeometry.hpp b/Tests/Core/CommonHelpers/include/Acts/Tests/CommonHelpers/CubicTrackingGeometry.hpp index 66a37d89d42baf83e8a141cddb758fa09d20753d..3345b5cb0ad0f1fae6ea32720a565826d64a33a4 100644 --- a/Tests/Core/CommonHelpers/include/Acts/Tests/CommonHelpers/CubicTrackingGeometry.hpp +++ b/Tests/Core/CommonHelpers/include/Acts/Tests/CommonHelpers/CubicTrackingGeometry.hpp @@ -121,7 +121,7 @@ struct CubicTrackingGeometry { auto trackVolume1 = TrackingVolume::create( std::make_shared<const Transform3D>(trafoVol1), boundsVol, nullptr, - std::move(layArr1), nullptr, "Volume 1"); + std::move(layArr1), nullptr, {}, "Volume 1"); trackVolume1->sign(GeometrySignature::Global); // Build volume for surfaces with positive x-values @@ -137,17 +137,17 @@ struct CubicTrackingGeometry { auto trackVolume2 = TrackingVolume::create( std::make_shared<const Transform3D>(trafoVol2), boundsVol, nullptr, - std::move(layArr2), nullptr, "Volume 2"); + std::move(layArr2), nullptr, {}, "Volume 2"); trackVolume2->sign(GeometrySignature::Global); // Glue volumes trackVolume2->glueTrackingVolume( - geoContext, BoundarySurfaceFace::negativeFaceYZ, trackVolume1, + geoContext, BoundarySurfaceFace::negativeFaceYZ, trackVolume1.get(), BoundarySurfaceFace::positiveFaceYZ); trackVolume1->glueTrackingVolume( - geoContext, BoundarySurfaceFace::positiveFaceYZ, trackVolume2, + geoContext, BoundarySurfaceFace::positiveFaceYZ, trackVolume2.get(), BoundarySurfaceFace::negativeFaceYZ); // Build world volume @@ -190,4 +190,4 @@ struct CubicTrackingGeometry { std::reference_wrapper<const GeometryContext> geoContext; }; } // namespace Test -} // namespace Acts +} // namespace Acts \ No newline at end of file diff --git a/Tests/Core/CommonHelpers/include/Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp b/Tests/Core/CommonHelpers/include/Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp index 065b046e738b37c9570f27c4d3d7bdc27ef1abfa..0b0b5a5de6a9e26676aafb04a3d1f1e758d98e6c 100644 --- a/Tests/Core/CommonHelpers/include/Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp +++ b/Tests/Core/CommonHelpers/include/Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp @@ -230,7 +230,7 @@ struct CylindricalTrackingGeometry { std::make_shared<const CylinderVolumeBounds>(25., 300., 1100.); // create the Tracking volume auto pVolume = TrackingVolume::create(nullptr, pVolumeBounds, nullptr, - std::move(pLayerArray), nullptr, + std::move(pLayerArray), nullptr, {}, "Pixel::Barrel"); // The combined volume diff --git a/Tests/Core/Geometry/CuboidVolumeBuilderTests.cpp b/Tests/Core/Geometry/CuboidVolumeBuilderTests.cpp index 1bca5116fac2f7f9f5a3c01e65abe11f3770adac..9d1ba6caddafae27cddc30b8c23cefc2a56bd36f 100644 --- a/Tests/Core/Geometry/CuboidVolumeBuilderTests.cpp +++ b/Tests/Core/Geometry/CuboidVolumeBuilderTests.cpp @@ -16,11 +16,14 @@ #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Propagator/Navigator.hpp" #include "Acts/Geometry/Layer.hpp" #include "Acts/Material/HomogeneousSurfaceMaterial.hpp" #include "Acts/Material/HomogeneousVolumeMaterial.hpp" #include "Acts/Material/Material.hpp" #include "Acts/Material/MaterialProperties.hpp" +#include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/StraightLineStepper.hpp" #include "Acts/Surfaces/RectangleBounds.hpp" #include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" @@ -28,12 +31,34 @@ #include "Acts/Geometry/TrackingGeometryBuilder.hpp" #include "Acts/Utilities/Definitions.hpp" #include "Acts/Utilities/Units.hpp" +#include "Acts/Material/HomogeneousVolumeMaterial.hpp" using namespace Acts::UnitLiterals; namespace Acts { namespace Test { +struct StepVolumeCollector { + /// + /// @brief Data container for result analysis + /// + struct this_result { + // Position of the propagator after each step + std::vector<Vector3D> position; + // Volume of the propagator after each step + std::vector<TrackingVolume const*> volume; + }; + + using result_type = this_result; + + template <typename propagator_state_t, typename stepper_t> + void operator()(propagator_state_t& state, const stepper_t& stepper, + result_type& result) const { + result.position.push_back(stepper.position(state.stepping)); + result.volume.push_back(state.navigation.currentVolume); + } +}; + BOOST_AUTO_TEST_CASE(CuboidVolumeBuilderTest) { // Construct builder CuboidVolumeBuilder cvb; @@ -233,5 +258,216 @@ BOOST_AUTO_TEST_CASE(CuboidVolumeBuilderTest) { ->volumeName(), volumeConfig2.name); } + +BOOST_AUTO_TEST_CASE(CuboidVolumeBuilderTest_confinedVolumes) { + // Production factory + CuboidVolumeBuilder cvb; + + // Create a test context + GeometryContext tgContext = GeometryContext(); + MagneticFieldContext mfContext = MagneticFieldContext(); + + // Build a volume that confines another volume + CuboidVolumeBuilder::VolumeConfig vCfg; + vCfg.position = {1. * units::_m, 0., 0.}; + vCfg.length = {2. * units::_m, 1. * units::_m, 1. * units::_m}; + vCfg.name = "Test volume"; + // Build and add 2 confined volumes + CuboidVolumeBuilder::VolumeConfig cvCfg1; + cvCfg1.position = {1.1 * units::_m, 0., 0.}; + cvCfg1.length = {10. * units::_cm, 10. * units::_cm, 10. * units::_cm}; + cvCfg1.name = "Confined volume1"; + cvCfg1.volumeMaterial = + std::shared_ptr<const IVolumeMaterial>(new HomogeneousVolumeMaterial( + Material(352.8, 407., 9.012, 4., 1.848e-3))); + CuboidVolumeBuilder::VolumeConfig cvCfg2; + cvCfg2.position = {0.9 * units::_m, 0., 0.}; + cvCfg2.length = {10. * units::_cm, 10. * units::_cm, 10. * units::_cm}; + cvCfg2.name = "Confined volume2"; + vCfg.volumeCfg = {cvCfg1, cvCfg2}; + + // Build detector + CuboidVolumeBuilder::Config config; + config.position = {1. * units::_m, 0., 0.}; + config.length = {2. * units::_m, 1. * units::_m, 1. * units::_m}; + config.volumeCfg = {vCfg}; + + cvb.setConfig(config); + TrackingGeometryBuilder::Config tgbCfg; + tgbCfg.trackingVolumeBuilders.push_back( + [=](const auto& context, const auto& inner, const auto& vb) { + return cvb.trackingVolume(context, inner, vb); + }); + TrackingGeometryBuilder tgb(tgbCfg); + std::shared_ptr<const TrackingGeometry> detector = + tgb.trackingGeometry(tgContext); + + // Test that the right volume is selected + BOOST_TEST(detector->lowestTrackingVolume(tgContext, {1. * units::_m, 0., 0.}) + ->volumeName() == vCfg.name); + BOOST_TEST( + detector->lowestTrackingVolume(tgContext, {1.1 * units::_m, 0., 0.}) + ->volumeName() == cvCfg1.name); + BOOST_TEST( + detector->lowestTrackingVolume(tgContext, {0.9 * units::_m, 0., 0.}) + ->volumeName() == cvCfg2.name); + + // Set propagator and navigator + PropagatorOptions<ActionList<StepVolumeCollector>> propOpts(tgContext, + mfContext); + propOpts.maxStepSize = 10. * units::_mm; + StraightLineStepper sls; + Navigator navi(detector); + navi.resolvePassive = true; + navi.resolveMaterial = true; + navi.resolveSensitive = true; + + Propagator<StraightLineStepper, Navigator> prop(sls, navi); + + // Set initial parameters for the particle track + Vector3D startParams(0., 0., 0.), startMom(1. * units::_GeV, 0., 0.); + SingleCurvilinearTrackParameters<ChargedPolicy> sbtp( + std::nullopt, startParams, startMom, 1., 0.); + + // Launch and collect results + const auto& result = prop.propagate(sbtp, propOpts).value(); + const StepVolumeCollector::this_result& stepResult = + result.get<typename StepVolumeCollector::result_type>(); + + // Check the identified volumes + for (unsigned int i = 0; i < stepResult.position.size(); i++) { + if (i > 0) { + BOOST_TEST(stepResult.position[i].x() > 0.); + } + if (stepResult.position[i].x() >= 0.85 * units::_m && + stepResult.position[i].x() < 0.95 * units::_m) { + BOOST_TEST(stepResult.volume[i]->volumeName() == cvCfg2.name); + BOOST_TEST(stepResult.volume[i]->volumeMaterial() == nullptr); + } else { + if (stepResult.position[i].x() >= 1.05 * units::_m && + stepResult.position[i].x() < 1.15 * units::_m) { + BOOST_TEST(stepResult.volume[i]->volumeName() == cvCfg1.name); + BOOST_TEST(stepResult.volume[i]->volumeMaterial() != nullptr); + } else { + if (stepResult.position[i].x() < 2. * units::_m) { + BOOST_TEST(stepResult.volume[i]->volumeName() == vCfg.name); + BOOST_TEST(stepResult.volume[i]->volumeMaterial() == nullptr); + } + } + } + } +} + +BOOST_AUTO_TEST_CASE(CuboidVolumeBuilderTest_confinedVolumes_edgecases) { + // Production factory + CuboidVolumeBuilder cvb; + + // Create a test context + GeometryContext tgContext = GeometryContext(); + MagneticFieldContext mfContext = MagneticFieldContext(); + + // Build a volume that confines another volume + CuboidVolumeBuilder::VolumeConfig vCfg1; + vCfg1.position = {1. * units::_m, 0., 0.}; + vCfg1.length = {2. * units::_m, 1. * units::_m, 1. * units::_m}; + vCfg1.name = "Test volume1"; + // Build and add 4 confined volumes + // Volume that is missed and quite orthogonal to the starting position + CuboidVolumeBuilder::VolumeConfig cvCfg1; + cvCfg1.position = {0.1 * units::_m, 0.4 * units::_m, 0.4 * units::_m}; + cvCfg1.length = {10. * units::_cm, 10. * units::_cm, 10. * units::_cm}; + cvCfg1.name = "Confined volume1"; + cvCfg1.volumeMaterial = + std::shared_ptr<const IVolumeMaterial>(new HomogeneousVolumeMaterial( + Material(352.8, 407., 9.012, 4., 1.848e-3))); + // Volume that is missed but far away such that it may be hit + CuboidVolumeBuilder::VolumeConfig cvCfg2; + cvCfg2.position = {1.9 * units::_m, -0.4 * units::_m, -0.4 * units::_m}; + cvCfg2.length = {10. * units::_cm, 10. * units::_cm, 10. * units::_cm}; + cvCfg2.name = "Confined volume2"; + // Volume that is hit but with identical boundary as its mother + // TODO: Moved slightly inside the volume since otherwise the navigation + // breaks due to overlapping boundary surfaces. The corresponding test below + // is changed accordingly. + CuboidVolumeBuilder::VolumeConfig cvCfg3; + cvCfg3.position = {1.9 * units::_m, 0., 0.}; + cvCfg3.length = {10. * units::_cm, 10. * units::_cm, 10. * units::_cm}; + cvCfg3.name = "Confined volume3"; + // Volume to grind along the boundary + CuboidVolumeBuilder::VolumeConfig cvCfg4; + cvCfg4.position = {1. * units::_m, 5. * units::_cm, 0.}; + cvCfg4.length = {10. * units::_cm, 10. * units::_cm, 10. * units::_cm}; + cvCfg4.name = "Confined volume4"; + vCfg1.volumeCfg = {cvCfg1, cvCfg2, cvCfg3, cvCfg4}; + + // Build a volume that confines another volume + CuboidVolumeBuilder::VolumeConfig vCfg2; + vCfg2.position = {2.5 * units::_m, 0., 0.}; + vCfg2.length = {1. * units::_m, 1. * units::_m, 1. * units::_m}; + vCfg2.name = "Test volume2"; + + // Build detector + CuboidVolumeBuilder::Config config; + config.position = {1.5 * units::_m, 0., 0.}; + config.length = {3. * units::_m, 1. * units::_m, 1. * units::_m}; + config.volumeCfg = {vCfg1, vCfg2}; + + cvb.setConfig(config); + TrackingGeometryBuilder::Config tgbCfg; + tgbCfg.trackingVolumeBuilders.push_back( + [=](const auto& context, const auto& inner, const auto& vb) { + return cvb.trackingVolume(context, inner, vb); + }); + TrackingGeometryBuilder tgb(tgbCfg); + std::shared_ptr<const TrackingGeometry> detector = + tgb.trackingGeometry(tgContext); + + // Set propagator and navigator + PropagatorOptions<ActionList<StepVolumeCollector>> propOpts(tgContext, + mfContext); + propOpts.maxStepSize = 10. * units::_mm; + StraightLineStepper sls; + Navigator navi(detector); + navi.resolvePassive = true; + navi.resolveMaterial = true; + navi.resolveSensitive = true; + + Propagator<StraightLineStepper, Navigator> prop(sls, navi); + + // Set initial parameters for the particle track + Vector3D startParams(0., 0., 0.), startMom(1. * units::_GeV, 0., 0.); + SingleCurvilinearTrackParameters<ChargedPolicy> sbtp( + std::nullopt, startParams, startMom, 1., 0.); + + // Launch and collect results + const auto& result = prop.propagate(sbtp, propOpts).value(); + const StepVolumeCollector::this_result& stepResult = + result.get<typename StepVolumeCollector::result_type>(); + + for (unsigned int i = 0; i < stepResult.position.size(); i++) { + // Check the movement in the right direction + if (i > 0) { + BOOST_TEST(stepResult.position[i].x() > 0.); + } + // Check the identified volumes + if (stepResult.position[i].x() >= 0.95 * units::_m && + stepResult.position[i].x() < 1.05 * units::_m) { + BOOST_TEST(stepResult.volume[i]->volumeName() == cvCfg4.name); + } else { + if (stepResult.position[i].x() >= 1.85 * units::_m && + stepResult.position[i].x() < 1.95 * units::_m) { + BOOST_TEST(stepResult.volume[i]->volumeName() == cvCfg3.name); + } else { + if (stepResult.position[i].x() < 2. * units::_m) { + BOOST_TEST(stepResult.volume[i]->volumeName() == vCfg1.name); + } else { + if (stepResult.position[i].x() < 3. * units::_m) { + BOOST_TEST(stepResult.volume[i]->volumeName() == vCfg2.name); + } + } + } + } + } +} } // namespace Test -} // namespace Acts +} // namespace Acts \ No newline at end of file diff --git a/Tests/Core/Geometry/TrackingVolumeCreation.hpp b/Tests/Core/Geometry/TrackingVolumeCreation.hpp index c38327ebe3f07adedb605b665b0a4463bd4c5932..06a76eff553473bc4f13e2a5ecc3cac2daeb4cdd 100644 --- a/Tests/Core/Geometry/TrackingVolumeCreation.hpp +++ b/Tests/Core/Geometry/TrackingVolumeCreation.hpp @@ -78,7 +78,7 @@ TrackingVolumePtr constructCylinderVolume( innerVolumeR, outerVolumeR, bUmax + volumeEnvelope); TrackingVolumePtr volume = TrackingVolume::create( - nullptr, volumeBounds, nullptr, std::move(layerArray), nullptr, name); + nullptr, volumeBounds, nullptr, std::move(layerArray), nullptr, {}, name); /// return the volume return volume; } diff --git a/Tests/Core/Propagator/StepperTests.cpp b/Tests/Core/Propagator/StepperTests.cpp index 0d59bb0227595f2d7d7a4ba3d2fe2087ff142a09..bb278160b3dee54e09c26e8475d100a407ee6260 100644 --- a/Tests/Core/Propagator/StepperTests.cpp +++ b/Tests/Core/Propagator/StepperTests.cpp @@ -15,6 +15,7 @@ #include <fstream> #include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Propagator/MaterialInteractor.hpp" #include "Acts/Propagator/Navigator.hpp" #include "Acts/MagneticField/ConstantBField.hpp" #include "Acts/Material/HomogeneousVolumeMaterial.hpp" @@ -29,6 +30,10 @@ #include "Acts/Utilities/Definitions.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/MagneticField/MagneticFieldContext.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Material/HomogeneousSurfaceMaterial.hpp" +#include "Acts/Material/ISurfaceMaterial.hpp" +#include "Acts/Material/IVolumeMaterial.hpp" namespace tt = boost::test_tools; using namespace Acts::UnitLiterals; @@ -545,6 +550,19 @@ BOOST_AUTO_TEST_CASE(step_extension_vacmatvac_test) { CHECK_CLOSE_ABS(endParams.first, endParamsControl.first, 1_um); CHECK_CLOSE_ABS(endParams.second, endParamsControl.second, 1_um); + BOOST_TEST(endParams.first.x() == endParamsControl.first.x(), + tt::tolerance(1e-5)); + BOOST_TEST(endParams.first.y() == endParamsControl.first.y(), + tt::tolerance(1e-5)); + BOOST_TEST(endParams.first.z() == endParamsControl.first.z(), + tt::tolerance(1e-5)); + BOOST_TEST(endParams.second.x() == endParamsControl.second.x(), + tt::tolerance(1e-5)); + BOOST_TEST(endParams.second.y() == endParamsControl.second.y(), + tt::tolerance(1e-5)); + BOOST_TEST(endParams.second.z() == endParamsControl.second.z(), + tt::tolerance(1e-5)); + // Build launcher through material // Set initial parameters for the particle track by using the result of the // first volume @@ -598,5 +616,158 @@ BOOST_AUTO_TEST_CASE(step_extension_vacmatvac_test) { CHECK_CLOSE_ABS(endParams.first, endParamsControl.first, 1_um); CHECK_CLOSE_ABS(endParams.second, endParamsControl.second, 1_um); } + +// Test case a). The DenseEnvironmentExtension should state that it is not +// valid in this case. +BOOST_AUTO_TEST_CASE(step_extension_trackercalomdt_test) { + double rotationAngle = M_PI * 0.5; + Vector3D xPos(cos(rotationAngle), 0., sin(rotationAngle)); + Vector3D yPos(0., 1., 0.); + Vector3D zPos(-sin(rotationAngle), 0., cos(rotationAngle)); + MaterialProperties matProp(352.8, 407., 9.012, 4., 1.848e-3, 0.5_mm); + + CuboidVolumeBuilder cvb; + CuboidVolumeBuilder::SurfaceConfig sConf1; + sConf1.position = Vector3D(0.3_m, 0., 0.); + sConf1.rotation.col(0) = xPos; + sConf1.rotation.col(1) = yPos; + sConf1.rotation.col(2) = zPos; + sConf1.rBounds = + std::make_shared<const RectangleBounds>(RectangleBounds(0.5_m, 0.5_m)); + sConf1.surMat = std::shared_ptr<const ISurfaceMaterial>( + new HomogeneousSurfaceMaterial(matProp)); + sConf1.thickness = 1._mm; + CuboidVolumeBuilder::LayerConfig lConf1; + lConf1.surfaceCfg = sConf1; + + CuboidVolumeBuilder::SurfaceConfig sConf2; + sConf2.position = Vector3D(0.6_m, 0., 0.); + sConf2.rotation.col(0) = xPos; + sConf2.rotation.col(1) = yPos; + sConf2.rotation.col(2) = zPos; + sConf2.rBounds = + std::make_shared<const RectangleBounds>(RectangleBounds(0.5_m, 0.5_m)); + sConf2.surMat = std::shared_ptr<const ISurfaceMaterial>( + new HomogeneousSurfaceMaterial(matProp)); + sConf2.thickness = 1._mm; + CuboidVolumeBuilder::LayerConfig lConf2; + lConf2.surfaceCfg = sConf2; + + CuboidVolumeBuilder::VolumeConfig muConf1; + muConf1.position = {2.3_m, 0., 0.}; + muConf1.length = {20._cm, 20._cm, 20._cm}; + muConf1.volumeMaterial = + std::shared_ptr<const IVolumeMaterial>(new HomogeneousVolumeMaterial( + Material(352.8, 407., 9.012, 4., 1.848e-3))); + muConf1.name = "MDT1"; + CuboidVolumeBuilder::VolumeConfig muConf2; + muConf2.position = {2.7_m, 0., 0.}; + muConf2.length = {20._cm, 20._cm, 20._cm}; + muConf2.volumeMaterial = + std::shared_ptr<const IVolumeMaterial>(new HomogeneousVolumeMaterial( + Material(352.8, 407., 9.012, 4., 1.848e-3))); + muConf2.name = "MDT2"; + + CuboidVolumeBuilder::VolumeConfig vConf1; + vConf1.position = {0.5_m, 0., 0.}; + vConf1.length = {1._m, 1._m, 1._m}; + vConf1.layerCfg = {lConf1, lConf2}; + vConf1.name = "Tracker"; + CuboidVolumeBuilder::VolumeConfig vConf2; + vConf2.position = {1.5_m, 0., 0.}; + vConf2.length = {1._m, 1._m, 1._m}; + vConf2.volumeMaterial = + std::shared_ptr<const IVolumeMaterial>(new HomogeneousVolumeMaterial( + Material(352.8, 407., 9.012, 4., 1.848e-3))); + vConf2.name = "Calorimeter"; + CuboidVolumeBuilder::VolumeConfig vConf3; + vConf3.position = {2.5_m, 0., 0.}; + vConf3.length = {1._m, 1._m, 1._m}; + vConf3.volumeCfg = {muConf1, muConf2}; + vConf3.name = "Muon system"; + CuboidVolumeBuilder::Config conf; + conf.volumeCfg = {vConf1, vConf2, vConf3}; + conf.position = {1.5_m, 0., 0.}; + conf.length = {3._m, 1._m, 1._m}; + + // Build detector + cvb.setConfig(conf); + TrackingGeometryBuilder::Config tgbCfg; + tgbCfg.trackingVolumeBuilders.push_back( + [=](const auto& context, const auto& inner, const auto& vb) { + return cvb.trackingVolume(context, inner, vb); + }); + TrackingGeometryBuilder tgb(tgbCfg); + std::shared_ptr<const TrackingGeometry> detector = + tgb.trackingGeometry(tgContext); + + // Build navigator + Navigator naviVac(detector); + naviVac.resolvePassive = true; + naviVac.resolveMaterial = true; + naviVac.resolveSensitive = true; + + // Set initial parameters for the particle track + Covariance cov = Covariance::Identity(); + Vector3D startParams(0., 0., 0.), startMom(1._GeV, 0., 0.); + SingleCurvilinearTrackParameters<ChargedPolicy> sbtp(cov, startParams, + startMom, 1., 0.); + + // Set options for propagator + DenseStepperPropagatorOptions<ActionList<StepCollector, MaterialInteractor>, + AbortList<EndOfWorld>> + propOpts(tgContext, mfContext); + propOpts.abortList.get<EndOfWorld>().maxX = 3._m; + + // Build stepper and propagator + ConstantBField bField(Vector3D(0., 0., 0.)); + EigenStepper< + ConstantBField, VoidIntersectionCorrector, + StepperExtensionList<DefaultExtension, DenseEnvironmentExtension>, + detail::HighestValidAuctioneer> + es(bField); + Propagator<EigenStepper<ConstantBField, VoidIntersectionCorrector, + StepperExtensionList<DefaultExtension, + DenseEnvironmentExtension>, + detail::HighestValidAuctioneer>, + Navigator> + prop(es, naviVac); + + // Launch and collect results + const auto& result = prop.propagate(sbtp, propOpts).value(); + const StepCollector::this_result& stepResult = + result.get<typename StepCollector::result_type>(); + + // Test that momentum changes only occured at the right detector parts + double lastMomentum = stepResult.momentum[0].x(); + for (unsigned int i = 0; i < stepResult.position.size(); i++) { + // Test for changes + if ((stepResult.position[i].x() > 0.3_m && + stepResult.position[i].x() < 0.6_m) || + (stepResult.position[i].x() > 0.6_m && + stepResult.position[i].x() <= 1._m) || + (stepResult.position[i].x() > 1._m && + stepResult.position[i].x() <= 2._m) || + (stepResult.position[i].x() > 2.2_m && + stepResult.position[i].x() <= 2.4_m) || + (stepResult.position[i].x() > 2.6_m && + stepResult.position[i].x() <= 2.8_m)) { + BOOST_TEST(stepResult.momentum[i].x() <= lastMomentum); + lastMomentum = stepResult.momentum[i].x(); + } else + // Test the absence of momentum loss + { + if (stepResult.position[i].x() < 0.3_m || + (stepResult.position[i].x() > 2._m && + stepResult.position[i].x() <= 2.2_m) || + (stepResult.position[i].x() > 2.4_m && + stepResult.position[i].x() <= 2.6_m) || + (stepResult.position[i].x() > 2.8_m && + stepResult.position[i].x() <= 3._m)) { + BOOST_TEST(stepResult.momentum[i].x() == lastMomentum); + } + } + } +} } // namespace Test -} // namespace Acts +} // namespace Acts \ No newline at end of file