Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:41

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/Geometry/DetectorElementBase.hpp"
0014 #include "Acts/Geometry/Extent.hpp"
0015 #include "Acts/Geometry/GeometryContext.hpp"
0016 #include "Acts/Geometry/ProtoLayer.hpp"
0017 #include "Acts/Surfaces/PlaneSurface.hpp"
0018 #include "Acts/Surfaces/RectangleBounds.hpp"
0019 #include "Acts/Surfaces/Surface.hpp"
0020 #include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp"
0021 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0022 #include "Acts/Utilities/BinningType.hpp"
0023 #include "Acts/Utilities/RangeXD.hpp"
0024 
0025 #include <cmath>
0026 #include <memory>
0027 #include <numbers>
0028 #include <sstream>
0029 #include <string>
0030 #include <vector>
0031 
0032 namespace Acts::Test::Layers {
0033 
0034 GeometryContext tgContext = GeometryContext();
0035 
0036 BOOST_AUTO_TEST_SUITE(Geometry)
0037 
0038 BOOST_AUTO_TEST_CASE(ProtoLayerTests) {
0039   using enum AxisDirection;
0040 
0041   // Create a proto layer with 4 surfaces on the x/y grid
0042   auto recBounds = std::make_shared<RectangleBounds>(3., 6.);
0043 
0044   // Planar definitions to help construct the boundary surfaces
0045   static const Transform3 planeYZ =
0046       AngleAxis3(std::numbers::pi / 2., Vector3::UnitY()) *
0047       AngleAxis3(std::numbers::pi / 2., Vector3::UnitZ()) *
0048       Transform3::Identity();
0049   static const Transform3 planeZX =
0050       AngleAxis3(-std::numbers::pi / 2., Vector3::UnitX()) *
0051       AngleAxis3(-std::numbers::pi / 2., Vector3::UnitZ()) *
0052       Transform3::Identity();
0053 
0054   std::vector<std::shared_ptr<const Surface>> surfaceStore;
0055   surfaceStore.reserve(100);
0056 
0057   auto createProtoLayer = [&](const Transform3& trf,
0058                               bool shared = false) -> ProtoLayer {
0059     auto atNegX = Surface::makeShared<PlaneSurface>(
0060         Transform3(trf * Translation3(Vector3(-3., 0., 0.)) * planeYZ),
0061         recBounds);
0062 
0063     auto atPosX = Surface::makeShared<PlaneSurface>(
0064         Transform3(trf * Translation3(Vector3(3., 0., 0.)) * planeYZ),
0065         recBounds);
0066 
0067     auto atNegY = Surface::makeShared<PlaneSurface>(
0068         Transform3(trf * Translation3(Vector3(0., -3, 0.)) * planeZX),
0069         recBounds);
0070 
0071     auto atPosY = Surface::makeShared<PlaneSurface>(
0072         Transform3(trf * Translation3(Vector3(0., 3., 0.)) * planeZX),
0073         recBounds);
0074 
0075     std::vector<std::shared_ptr<const Surface>> sharedSurfaces = {
0076         atNegX, atNegY, atPosX, atPosY};
0077     surfaceStore.insert(surfaceStore.begin(), sharedSurfaces.begin(),
0078                         sharedSurfaces.end());
0079     if (!shared) {
0080       std::vector<const Surface*> surfaces = {atNegX.get(), atNegY.get(),
0081                                               atPosX.get(), atPosY.get()};
0082 
0083       return ProtoLayer(tgContext, surfaces);
0084     }
0085     return ProtoLayer(tgContext, sharedSurfaces);
0086   };
0087 
0088   // Test 0 - check constructor with surfaces and shared surfaces
0089   auto pLayerSf = createProtoLayer(Transform3::Identity());
0090   auto pLayerSfShared = createProtoLayer(Transform3::Identity());
0091 
0092   BOOST_CHECK(pLayerSf.extent.range() == pLayerSfShared.extent.range());
0093   BOOST_CHECK(pLayerSf.envelope == pLayerSfShared.envelope);
0094 
0095   // CHECK That you have 4 surfaces
0096   BOOST_CHECK_EQUAL(pLayerSf.surfaces().size(), 4);
0097   // Add one surface from a detector element (to test thickness)
0098   auto rB = std::make_shared<RectangleBounds>(30., 60.);
0099 
0100   // Create the detector element
0101   auto addSurface =
0102       Surface::makeShared<PlaneSurface>(Transform3::Identity(), rB);
0103 
0104   pLayerSf.add(tgContext, *addSurface.get());
0105   // CHECK That if you now have 5 surfaces
0106   BOOST_CHECK_EQUAL(pLayerSf.surfaces().size(), 5);
0107 
0108   // That should invalidate the ranges
0109   BOOST_CHECK(!(pLayerSf.extent.range() == pLayerSfShared.extent.range()));
0110 
0111   // Test 1 - identity transform
0112   auto protoLayer = createProtoLayer(Transform3::Identity());
0113 
0114   CHECK_CLOSE_ABS(protoLayer.range(AxisX), 12., 1e-8);
0115   CHECK_CLOSE_ABS(protoLayer.medium(AxisX), 0., 1e-8);
0116   CHECK_CLOSE_ABS(protoLayer.min(AxisX), -6., 1e-8);
0117   CHECK_CLOSE_ABS(protoLayer.max(AxisX), 6., 1e-8);
0118   CHECK_CLOSE_ABS(protoLayer.range(AxisY), 6., 1e-8);
0119   CHECK_CLOSE_ABS(protoLayer.medium(AxisY), 0., 1e-8);
0120   CHECK_CLOSE_ABS(protoLayer.min(AxisY), -3., 1e-8);
0121   CHECK_CLOSE_ABS(protoLayer.max(AxisY), 3., 1e-8);
0122   CHECK_CLOSE_ABS(protoLayer.range(AxisZ), 12., 1e-8);
0123   CHECK_CLOSE_ABS(protoLayer.medium(AxisZ), 0., 1e-8);
0124   CHECK_CLOSE_ABS(protoLayer.min(AxisZ), -6., 1e-8);
0125   CHECK_CLOSE_ABS(protoLayer.max(AxisZ), 6., 1e-8);
0126   CHECK_CLOSE_ABS(protoLayer.max(AxisR), std::hypot(3, 6), 1e-8);
0127   CHECK_CLOSE_ABS(protoLayer.min(AxisR), 3., 1e-8);
0128 
0129   // Test 1a
0130 
0131   // Test 2 - rotate around Z-Axis, should leave R, Z untouched,
0132   // only preserves medium values
0133   auto protoLayerRot = createProtoLayer(AngleAxis3(-0.345, Vector3::UnitZ()) *
0134                                         Transform3::Identity());
0135 
0136   BOOST_CHECK_NE(protoLayer.min(AxisX), -6.);
0137   CHECK_CLOSE_ABS(protoLayerRot.medium(AxisX), 0., 1e-8);
0138   CHECK_CLOSE_ABS(protoLayerRot.medium(AxisY), 0., 1e-8);
0139   CHECK_CLOSE_ABS(protoLayerRot.range(AxisZ), 12., 1e-8);
0140   CHECK_CLOSE_ABS(protoLayerRot.medium(AxisZ), 0., 1e-8);
0141   CHECK_CLOSE_ABS(protoLayerRot.min(AxisZ), -6., 1e-8);
0142   CHECK_CLOSE_ABS(protoLayerRot.max(AxisZ), 6., 1e-8);
0143   CHECK_CLOSE_ABS(protoLayerRot.min(AxisR), 3., 1e-8);
0144   CHECK_CLOSE_ABS(protoLayerRot.max(AxisR), std::hypot(3, 6), 1e-8);
0145 
0146   std::stringstream sstream;
0147   protoLayerRot.toStream(sstream);
0148   std::string oString = R"(ProtoLayer with dimensions (min/max)
0149 Extent in space :
0150   - value :     AxisX | range = [-6.66104, 6.66104]
0151   - value :     AxisY | range = [-4.85241, 4.85241]
0152   - value :     AxisZ | range = [-6, 6]
0153   - value :     AxisR | range = [3, 6.7082]
0154   - value :   AxisPhi | range = [-3.02295, 2.33295]
0155   - value :  AxisRPhi | range = [-20.2785, 15.6499]
0156   - value : AxisTheta | range = [0.61548, 2.52611]
0157   - value :   AxisEta | range = [-1.14622, 1.14622]
0158   - value :   AxisMag | range = [7.34847, 7.34847]
0159 )";
0160   BOOST_CHECK_EQUAL(sstream.str(), oString);
0161 }
0162 
0163 BOOST_AUTO_TEST_CASE(OrientedLayer) {
0164   using enum AxisDirection;
0165   using namespace Acts::UnitLiterals;
0166 
0167   Transform3 base = Transform3::Identity();
0168 
0169   auto recBounds = std::make_shared<RectangleBounds>(3_mm, 6_mm);
0170 
0171   std::vector<std::unique_ptr<DetectorElementBase>> detectorElements;
0172 
0173   auto makeFan = [&](double yrot, double thickness = 0) {
0174     detectorElements.clear();
0175 
0176     std::size_t nSensors = 8;
0177     double deltaPhi = 2 * std::numbers::pi / nSensors;
0178     double r = 20_mm;
0179     std::vector<std::shared_ptr<const Surface>> surfaces;
0180     for (std::size_t i = 0; i < nSensors; i++) {
0181       // Create a fan of sensors
0182 
0183       Transform3 trf = base * AngleAxis3{yrot, Vector3::UnitY()} *
0184                        AngleAxis3{deltaPhi * i, Vector3::UnitZ()} *
0185                        Translation3(Vector3::UnitX() * r);
0186 
0187       auto& element = detectorElements.emplace_back(
0188           std::make_unique<DetectorElementStub>(trf, recBounds, thickness));
0189 
0190       surfaces.push_back(element->surface().getSharedPtr());
0191     }
0192     return surfaces;
0193   };
0194 
0195   std::vector<std::shared_ptr<const Surface>> surfaces = makeFan(0_degree);
0196 
0197   ProtoLayer protoLayer(tgContext, surfaces);
0198 
0199   BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0200   BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -23_mm, 1e-8);
0201   BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 23_mm, 1e-8);
0202   BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0203   BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0204   BOOST_CHECK_CLOSE(protoLayer.min(AxisZ), 0_mm, 1e-8);
0205   BOOST_CHECK_CLOSE(protoLayer.max(AxisZ), 0_mm, 1e-8);
0206   BOOST_CHECK_CLOSE(protoLayer.min(AxisR), 17_mm, 1e-8);
0207   BOOST_CHECK_CLOSE(protoLayer.max(AxisR), 23.769728648_mm, 1e-8);
0208 
0209   surfaces = makeFan(45_degree);
0210 
0211   // Do NOT provide rotation matrix: sizing will be affected
0212   protoLayer = {tgContext, surfaces};
0213 
0214   BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0215   BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -16.26345596_mm, 1e-4);
0216   BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 16.26345596_mm, 1e-4);
0217   BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0218   BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0219   BOOST_CHECK_CLOSE(protoLayer.min(AxisZ), -16.26345596_mm, 1e-4);
0220   BOOST_CHECK_CLOSE(protoLayer.max(AxisZ), 16.26345596_mm, 1e-4);
0221 
0222   protoLayer = {tgContext, surfaces,
0223                 Transform3{AngleAxis3{45_degree, Vector3::UnitY()}}.inverse()};
0224 
0225   BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0226   BOOST_CHECK_CLOSE(protoLayer.range(AxisX), 46_mm, 1e-8);
0227   BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -23_mm, 1e-8);
0228   BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 23_mm, 1e-8);
0229   BOOST_CHECK_CLOSE(protoLayer.range(AxisY), 46_mm, 1e-8);
0230   BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0231   BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0232   CHECK_SMALL(protoLayer.range(AxisZ), 1e-14);
0233   CHECK_SMALL(protoLayer.min(AxisZ), 1e-14);
0234   CHECK_SMALL(protoLayer.max(AxisZ), 1e-14);
0235 
0236   surfaces = makeFan(0_degree, 10_mm);
0237 
0238   protoLayer = {tgContext, surfaces};
0239 
0240   BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0241   BOOST_CHECK_CLOSE(protoLayer.range(AxisX), 46_mm, 1e-8);
0242   BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -23_mm, 1e-8);
0243   BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 23_mm, 1e-8);
0244   BOOST_CHECK_CLOSE(protoLayer.range(AxisY), 46_mm, 1e-8);
0245   BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0246   BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0247   BOOST_CHECK_CLOSE(protoLayer.range(AxisZ), 10_mm, 1e-8);
0248   BOOST_CHECK_CLOSE(protoLayer.min(AxisZ), -5_mm, 1e-8);
0249   BOOST_CHECK_CLOSE(protoLayer.max(AxisZ), 5_mm, 1e-8);
0250 
0251   surfaces = makeFan(45_degree, 10_mm);
0252 
0253   protoLayer = {tgContext, surfaces,
0254                 Transform3{AngleAxis3{45_degree, Vector3::UnitY()}}.inverse()};
0255 
0256   BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0257   BOOST_CHECK_CLOSE(protoLayer.range(AxisX), 46_mm, 1e-8);
0258   BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -23_mm, 1e-8);
0259   BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 23_mm, 1e-8);
0260   BOOST_CHECK_CLOSE(protoLayer.range(AxisY), 46_mm, 1e-8);
0261   BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0262   BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0263   BOOST_CHECK_CLOSE(protoLayer.range(AxisZ), 10_mm, 1e-8);
0264   BOOST_CHECK_CLOSE(protoLayer.min(AxisZ), -5_mm, 1e-8);
0265   BOOST_CHECK_CLOSE(protoLayer.max(AxisZ), 5_mm, 1e-8);
0266 }
0267 
0268 BOOST_AUTO_TEST_SUITE_END()
0269 
0270 }  // namespace Acts::Test::Layers