File indexing completed on 2025-08-06 08:11:17
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Detector/Detector.hpp"
0013 #include "Acts/Detector/DetectorComponents.hpp"
0014 #include "Acts/Detector/DetectorVolume.hpp"
0015 #include "Acts/Detector/GeometryIdGenerator.hpp"
0016 #include "Acts/Detector/PortalGenerators.hpp"
0017 #include "Acts/Detector/detail/CylindricalDetectorHelper.hpp"
0018 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0019 #include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
0020 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0021 #include "Acts/Geometry/GeometryContext.hpp"
0022 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0023 #include "Acts/Navigation/SurfaceCandidatesUpdaters.hpp"
0024 #include "Acts/Utilities/Enumerate.hpp"
0025 #include "Acts/Utilities/Logger.hpp"
0026
0027 #include <algorithm>
0028 #include <array>
0029 #include <cmath>
0030 #include <iterator>
0031 #include <map>
0032 #include <memory>
0033 #include <ostream>
0034 #include <stdexcept>
0035 #include <string>
0036 #include <utility>
0037 #include <vector>
0038
0039 namespace Acts::Experimental {
0040 class Portal;
0041 }
0042
0043 using namespace Acts;
0044 using namespace Experimental;
0045 using namespace Experimental::detail;
0046 using namespace Experimental::detail::CylindricalDetectorHelper;
0047
0048 Logging::Level logLevel = Logging::VERBOSE;
0049
0050 GeometryContext tContext;
0051 std::vector<std::shared_ptr<DetectorVolume>> eVolumes = {};
0052
0053 auto portalGenerator = defaultPortalGenerator();
0054
0055 BOOST_AUTO_TEST_SUITE(Experimental)
0056
0057 BOOST_AUTO_TEST_CASE(ConnectVolumeExceptions) {
0058 ACTS_LOCAL_LOGGER(getDefaultLogger("Faulty setups", logLevel));
0059
0060 auto cBounds0 = std::make_unique<CylinderVolumeBounds>(0., 100., 100);
0061 auto volume0 = DetectorVolumeFactory::construct(
0062 portalGenerator, tContext, "Volume0", Transform3::Identity(),
0063 std::move(cBounds0), tryAllPortals());
0064
0065 auto cBounds1 =
0066 std::make_unique<CylinderVolumeBounds>(0., 100., 100, 0.2, 1.);
0067 auto volume1 = DetectorVolumeFactory::construct(
0068 portalGenerator, tContext, "Volume0", Transform3::Identity(),
0069 std::move(cBounds1), tryAllPortals());
0070
0071 ACTS_INFO("*** Test: nullptr in the list of volumes");
0072
0073
0074 std::vector<std::shared_ptr<DetectorVolume>> volumesWithNullptr = {
0075 volume0, nullptr, volume1};
0076 BOOST_CHECK_THROW(connectInR(tContext, volumesWithNullptr, {}, logLevel),
0077 std::invalid_argument);
0078
0079 ACTS_INFO("*** Test: non-cylinder in the list of volumes");
0080
0081 auto cubeBounds = std::make_unique<CuboidVolumeBounds>(100., 100., 100);
0082 auto cube = DetectorVolumeFactory::construct(
0083 portalGenerator, tContext, "Cube", Transform3::Identity(),
0084 std::move(cubeBounds), tryAllPortals());
0085
0086
0087 std::vector<std::shared_ptr<DetectorVolume>> volumesWithCube = {
0088 volume0, volume1, cube};
0089 BOOST_CHECK_THROW(connectInR(tContext, volumesWithCube, {}, logLevel),
0090 std::invalid_argument);
0091
0092 ACTS_INFO("*** Test: non-aligned volume in the list of volumes");
0093 Transform3 rotated = Transform3::Identity();
0094 AngleAxis3 rotX(0.1234, Vector3::UnitX());
0095 rotated *= rotX;
0096
0097 auto cBounds2 = std::make_unique<CylinderVolumeBounds>(0., 100., 100);
0098 auto volume2 = DetectorVolumeFactory::construct(
0099 portalGenerator, tContext, "Volume2", rotated, std::move(cBounds2),
0100 tryAllPortals());
0101
0102
0103 std::vector<std::shared_ptr<DetectorVolume>> volumesWithNonaligned = {
0104 volume0, volume1, volume2};
0105 BOOST_CHECK_THROW(connectInR(tContext, volumesWithNonaligned, {}, logLevel),
0106 std::invalid_argument);
0107 }
0108
0109 BOOST_AUTO_TEST_CASE(ConnectInR) {
0110 ACTS_LOCAL_LOGGER(getDefaultLogger("Connect: R", logLevel));
0111 ACTS_INFO("*** Test: connect DetectorVolumes in R, create proto container");
0112
0113 std::vector<ActsScalar> testOpenings = {M_PI, 0.5 * M_PI};
0114
0115 std::vector<ActsScalar> radii = {0., 10., 100., 200.};
0116 ActsScalar halfZ = 100.;
0117
0118
0119 for (auto [io, opening] : enumerate(testOpenings)) {
0120 ACTS_INFO(" -> test with phi opening: " << opening);
0121 std::string opStr = "opening_" + std::to_string(io);
0122 std::vector<std::shared_ptr<DetectorVolume>> rVolumes = {};
0123
0124 for (auto [i, r] : enumerate(radii)) {
0125 if (i > 0) {
0126 auto cBounds = std::make_unique<CylinderVolumeBounds>(
0127 radii[i - 1u], r, halfZ, opening, 0.);
0128 rVolumes.push_back(DetectorVolumeFactory::construct(
0129 portalGenerator, tContext, "Cylinder_r" + std::to_string(i),
0130 Transform3::Identity(), std::move(cBounds), tryAllPortals()));
0131 }
0132 }
0133
0134 auto protoContainer = connectInR(tContext, rVolumes, {}, logLevel);
0135
0136 BOOST_CHECK_EQUAL(rVolumes[0u]->portalPtrs()[2u],
0137 rVolumes[1u]->portalPtrs()[3u]);
0138 BOOST_CHECK_EQUAL(rVolumes[1u]->portalPtrs()[2u],
0139 rVolumes[2u]->portalPtrs()[3u]);
0140 BOOST_CHECK_EQUAL(rVolumes[0u]->portalPtrs()[0u],
0141 rVolumes[1u]->portalPtrs()[0u]);
0142 BOOST_CHECK_EQUAL(rVolumes[1u]->portalPtrs()[0u],
0143 rVolumes[2u]->portalPtrs()[0u]);
0144 BOOST_CHECK_EQUAL(rVolumes[0u]->portalPtrs()[1u],
0145 rVolumes[1u]->portalPtrs()[1u]);
0146 BOOST_CHECK_EQUAL(rVolumes[1u]->portalPtrs()[1u],
0147 rVolumes[2u]->portalPtrs()[1u]);
0148 BOOST_CHECK_EQUAL(rVolumes[0u]->portalPtrs()[0u], protoContainer[0u]);
0149 BOOST_CHECK_EQUAL(rVolumes[0u]->portalPtrs()[1u], protoContainer[1u]);
0150
0151
0152 Acts::Experimental::GeometryIdGenerator::Config generatorConfig;
0153 GeometryIdGenerator generator(
0154 generatorConfig, Acts::getDefaultLogger("SequentialIdGenerator",
0155 Acts::Logging::VERBOSE));
0156 auto cache = generator.generateCache();
0157 for (auto& vol : rVolumes) {
0158 generator.assignGeometryId(cache, *vol);
0159 }
0160
0161
0162 auto detector =
0163 Detector::makeShared("DetectorInR", rVolumes, tryRootVolumes());
0164
0165
0166 const auto& volumes = detector->volumes();
0167 auto boundaries = rzphiBoundaries(tContext, volumes);
0168 const auto& rBoundaries = boundaries[0u];
0169 const auto& zBoundaries = boundaries[1u];
0170
0171
0172 std::vector<ActsScalar> zvalues = {-halfZ, halfZ};
0173 BOOST_CHECK(radii == rBoundaries);
0174 BOOST_CHECK(zvalues == zBoundaries);
0175 }
0176
0177
0178 ACTS_INFO("*** Test: faulty empty vector");
0179 BOOST_CHECK_THROW(connectInR(tContext, eVolumes, {}, logLevel),
0180 std::invalid_argument);
0181
0182
0183 ACTS_INFO("*** Test: volumes are not matching in R");
0184
0185 auto cBounds00 = std::make_unique<CylinderVolumeBounds>(0., 100., 100);
0186 auto volume00 = DetectorVolumeFactory::construct(
0187 portalGenerator, tContext, "Volume00", Transform3::Identity(),
0188 std::move(cBounds00), tryAllPortals());
0189
0190 auto cBounds01 = std::make_unique<CylinderVolumeBounds>(101., 200., 100);
0191 auto volume01 = DetectorVolumeFactory::construct(
0192 portalGenerator, tContext, "Volume01", Transform3::Identity(),
0193 std::move(cBounds01), tryAllPortals());
0194
0195 std::vector<std::shared_ptr<DetectorVolume>> volumesNotMatching = {volume00,
0196 volume01};
0197 BOOST_CHECK_THROW(connectInR(tContext, volumesNotMatching, {}, logLevel),
0198 std::runtime_error);
0199
0200 ACTS_INFO("*** Test: volume bounds are not aligned");
0201 Transform3 shifted = Transform3::Identity();
0202 shifted.pretranslate(Vector3(0., 0., 10.));
0203
0204 auto cBounds10 = std::make_unique<CylinderVolumeBounds>(0., 100., 100);
0205 auto volume10 = DetectorVolumeFactory::construct(
0206 portalGenerator, tContext, "Volume10", shifted, std::move(cBounds10),
0207 tryAllPortals());
0208
0209 auto cBounds11 = std::make_unique<CylinderVolumeBounds>(100., 200., 90);
0210 auto volume11 = DetectorVolumeFactory::construct(
0211 portalGenerator, tContext, "Volume11", shifted, std::move(cBounds11),
0212 tryAllPortals());
0213
0214 std::vector<std::shared_ptr<DetectorVolume>> volumesNotAligned = {volume10,
0215 volume11};
0216 BOOST_CHECK_THROW(connectInR(tContext, volumesNotAligned, {}, logLevel),
0217 std::runtime_error);
0218 }
0219
0220 BOOST_AUTO_TEST_CASE(ConnectInZ) {
0221 ACTS_LOCAL_LOGGER(getDefaultLogger("Connect: Z", logLevel));
0222 ACTS_INFO("*** Test: connect DetectorVolumes in Z, create proto container");
0223
0224
0225 std::vector<Transform3> transforms = {Transform3::Identity()};
0226 std::vector<std::array<ActsScalar, 2>> radii = {{0., 100.}, {20., 120.}};
0227 std::vector<ActsScalar> zValues = {-100., -20, 10., 100., 200.};
0228
0229 for (auto [it, t] : enumerate(transforms)) {
0230 ACTS_INFO(" -> test series with transform id " << it);
0231
0232 std::string trfStr = "_transform_" + std::to_string(it);
0233 for (auto [ir, r] : enumerate(radii)) {
0234 ACTS_INFO(" -> test series with radii setup "
0235 << radii[ir][0u] << ", " << radii[ir][1u]);
0236
0237 std::string radStr = "_radii_" + std::to_string(ir);
0238 std::vector<std::shared_ptr<DetectorVolume>> zVolumes = {};
0239 for (auto [i, z] : enumerate(zValues)) {
0240 if (i > 0) {
0241 auto cBounds = std::make_unique<CylinderVolumeBounds>(
0242 r[0], r[1], 0.5 * (z - zValues[i - 1u]));
0243
0244 ActsScalar zCenter = 0.5 * (z + zValues[i - 1u]);
0245 Transform3 ti = Transform3::Identity();
0246 ti.pretranslate(t.translation() +
0247 zCenter * t.rotation().matrix().col(2));
0248 ti.prerotate(t.rotation());
0249
0250 zVolumes.push_back(DetectorVolumeFactory::construct(
0251 portalGenerator, tContext,
0252 "Cylinder_z" + std::to_string(i) + trfStr + radStr, ti,
0253 std::move(cBounds), tryAllPortals()));
0254 }
0255 }
0256
0257 auto protoContainer = connectInZ(tContext, zVolumes, {}, logLevel);
0258
0259
0260
0261 BOOST_CHECK_EQUAL(zVolumes[0u]->portalPtrs()[1u],
0262 zVolumes[1u]->portalPtrs()[0u]);
0263 BOOST_CHECK_EQUAL(zVolumes[1u]->portalPtrs()[1u],
0264 zVolumes[2u]->portalPtrs()[0u]);
0265 BOOST_CHECK_EQUAL(zVolumes[2u]->portalPtrs()[1u],
0266 zVolumes[3u]->portalPtrs()[0u]);
0267 BOOST_CHECK_EQUAL(protoContainer[0u], zVolumes[0u]->portalPtrs()[0u]);
0268 BOOST_CHECK_EQUAL(protoContainer[1u], zVolumes[3u]->portalPtrs()[1u]);
0269
0270
0271 std::vector<unsigned int> checkShared = {2u};
0272 if (radii[ir][0u] > 0.) {
0273 checkShared.push_back(3u);
0274 }
0275
0276 for (const auto& ip : checkShared) {
0277 BOOST_CHECK_EQUAL(zVolumes[0u]->portalPtrs()[ip],
0278 zVolumes[1u]->portalPtrs()[ip]);
0279 BOOST_CHECK_EQUAL(zVolumes[1u]->portalPtrs()[ip],
0280 zVolumes[2u]->portalPtrs()[ip]);
0281 BOOST_CHECK_EQUAL(zVolumes[2u]->portalPtrs()[ip],
0282 zVolumes[3u]->portalPtrs()[ip]);
0283 BOOST_CHECK_EQUAL(protoContainer[ip], zVolumes[0u]->portalPtrs()[ip]);
0284 }
0285
0286
0287 Acts::Experimental::GeometryIdGenerator::Config generatorConfig;
0288 GeometryIdGenerator generator(
0289 generatorConfig, Acts::getDefaultLogger("SequentialIdGenerator",
0290 Acts::Logging::VERBOSE));
0291 auto cache = generator.generateCache();
0292 for (auto& vol : zVolumes) {
0293 generator.assignGeometryId(cache, *vol);
0294 }
0295
0296 auto detector =
0297 Detector::makeShared("DetectorInZ", zVolumes, tryRootVolumes());
0298 }
0299 }
0300
0301
0302 BOOST_CHECK_THROW(connectInZ(tContext, eVolumes, {}, logLevel),
0303 std::invalid_argument);
0304
0305
0306 auto cBounds00 = std::make_unique<CylinderVolumeBounds>(0., 100., 100);
0307 auto volume00 = DetectorVolumeFactory::construct(
0308 portalGenerator, tContext, "Volume00",
0309 Transform3::Identity() * Translation3(0., 0., -100.),
0310 std::move(cBounds00), tryAllPortals());
0311
0312 auto cBounds01 = std::make_unique<CylinderVolumeBounds>(0., 105., 100);
0313 auto volume01 = DetectorVolumeFactory::construct(
0314 portalGenerator, tContext, "Volume01",
0315 Transform3::Identity() * Translation3(0., 0., 100.), std::move(cBounds01),
0316 tryAllPortals());
0317
0318 std::vector<std::shared_ptr<DetectorVolume>> volumesNonalignedBounds = {
0319 volume00, volume01};
0320 BOOST_CHECK_THROW(connectInZ(tContext, volumesNonalignedBounds, {}, logLevel),
0321 std::runtime_error);
0322
0323
0324 auto cBounds10 = std::make_unique<CylinderVolumeBounds>(0., 100., 100);
0325 auto volume10 = DetectorVolumeFactory::construct(
0326 portalGenerator, tContext, "Volume00",
0327 Transform3::Identity() * Translation3(0., 0., -105.),
0328 std::move(cBounds10), tryAllPortals());
0329
0330 auto cBounds11 = std::make_unique<CylinderVolumeBounds>(0., 100., 100);
0331 auto volume11 = DetectorVolumeFactory::construct(
0332 portalGenerator, tContext, "Volume01",
0333 Transform3::Identity() * Translation3(0., 0., 100.), std::move(cBounds11),
0334 tryAllPortals());
0335
0336 std::vector<std::shared_ptr<DetectorVolume>> volumesNotAttached = {volume10,
0337 volume11};
0338 BOOST_CHECK_THROW(connectInZ(tContext, volumesNotAttached, {}, logLevel),
0339 std::runtime_error);
0340 }
0341
0342 BOOST_AUTO_TEST_CASE(ConnectInPhi) {
0343 ACTS_LOCAL_LOGGER(getDefaultLogger("Connect: Phi", logLevel));
0344 ACTS_INFO("*** Test: connect DetectorVolumes in Phi, create proto container");
0345
0346 std::vector<Transform3> transforms = {Transform3::Identity()};
0347 unsigned int phiSectors = 5;
0348 ActsScalar phiHalfSector = M_PI / phiSectors;
0349
0350 for (auto [it, t] : enumerate(transforms)) {
0351 ACTS_INFO(" -> test series with transform id " << it);
0352
0353 std::vector<std::shared_ptr<DetectorVolume>> phiVolumes = {};
0354 for (unsigned int i = 0; i < phiSectors; ++i) {
0355 auto cBounds = std::make_unique<CylinderVolumeBounds>(
0356 10., 100., 100., phiHalfSector,
0357 -M_PI + (2u * i + 1u) * phiHalfSector);
0358
0359
0360 phiVolumes.push_back(DetectorVolumeFactory::construct(
0361 portalGenerator, tContext, "Cylinder_phi" + std::to_string(i), t,
0362 std::move(cBounds), tryAllPortals()));
0363 }
0364
0365 auto protoContainer = connectInPhi(tContext, phiVolumes, {}, logLevel);
0366
0367
0368 std::vector<unsigned int> checkShared = {0u, 1u, 2u, 3u};
0369 for (auto [iv, v] : enumerate(phiVolumes)) {
0370 if (iv > 0u) {
0371 auto current = v;
0372 auto last = phiVolumes[iv - 1u];
0373 for (const auto& ch : checkShared) {
0374 BOOST_CHECK_EQUAL(current->portalPtrs()[ch], last->portalPtrs()[ch]);
0375 }
0376 }
0377 }
0378
0379
0380 Acts::Experimental::GeometryIdGenerator::Config generatorConfig;
0381 GeometryIdGenerator generator(
0382 generatorConfig, Acts::getDefaultLogger("SequentialIdGenerator",
0383 Acts::Logging::VERBOSE));
0384 auto cache = generator.generateCache();
0385 for (auto& vol : phiVolumes) {
0386 generator.assignGeometryId(cache, *vol);
0387 }
0388
0389 auto detector =
0390 Detector::makeShared("DetectorInPhi", phiVolumes, tryRootVolumes());
0391 }
0392
0393
0394 BOOST_CHECK_THROW(connectInPhi(tContext, eVolumes, {}, logLevel),
0395 std::invalid_argument);
0396 }
0397
0398 BOOST_AUTO_TEST_CASE(WrapVolumeinRZ) {
0399 ACTS_LOCAL_LOGGER(getDefaultLogger("Wrap: Z-R", logLevel));
0400 ACTS_INFO(
0401 "*** Test: wrap volume in Z-R with CutoutCylinderVolume, create proto "
0402 "container");
0403
0404
0405 std::vector<Transform3> transforms = {Transform3::Identity()};
0406
0407
0408 std::vector<std::array<ActsScalar, 3u>> radii = {{0., 100., 500.},
0409 {20., 120., 500.}};
0410
0411 ActsScalar innerHalfZ = 150.;
0412 ActsScalar outerHalfZ = 175.;
0413
0414
0415 for (auto [it, tf] : enumerate(transforms)) {
0416 ACTS_INFO(" Test series with transform id " << it);
0417
0418 std::string trfStr = "_transform_" + std::to_string(it);
0419 for (auto [ir, r] : enumerate(radii)) {
0420 ACTS_INFO(" -> test series with radii setup " << radii[ir][0u] << ", "
0421 << radii[ir][1u]);
0422
0423 std::vector<std::shared_ptr<DetectorVolume>> volumes = {};
0424
0425 std::string radStr = "_radii_" + std::to_string(ir);
0426
0427 auto iBounds = std::make_unique<CylinderVolumeBounds>(
0428 radii[ir][0u], radii[ir][1u], innerHalfZ);
0429 volumes.push_back(DetectorVolumeFactory::construct(
0430 portalGenerator, tContext, "InnerCylinder" + radStr + trfStr, tf,
0431 std::move(iBounds), tryAllPortals()));
0432
0433
0434 auto wBounds = std::make_unique<CutoutCylinderVolumeBounds>(
0435 radii[ir][0u], radii[ir][1u], radii[ir][2u], outerHalfZ, innerHalfZ);
0436
0437 volumes.push_back(DetectorVolumeFactory::construct(
0438 portalGenerator, tContext, "WrappingCylinder" + radStr + trfStr, tf,
0439 std::move(wBounds), tryAllPortals()));
0440
0441 wrapInZR(tContext, volumes, logLevel);
0442 }
0443 }
0444
0445
0446 BOOST_CHECK_THROW(wrapInZR(tContext, eVolumes, logLevel),
0447 std::invalid_argument);
0448 }
0449
0450 BOOST_AUTO_TEST_CASE(ProtoContainerZR) {
0451 ACTS_LOCAL_LOGGER(getDefaultLogger("Container: Z-R", logLevel));
0452 ACTS_INFO("*** Test: create a container in Z-R.");
0453
0454 auto transform = Transform3::Identity();
0455
0456 std::vector<ActsScalar> innerMostRadii = {0., 2.};
0457
0458 for (auto [ir, imr] : enumerate(innerMostRadii)) {
0459 ACTS_INFO(" -> test series innermost radius setup "
0460 << innerMostRadii[ir]);
0461
0462
0463 std::vector<ActsScalar> radii = {25., 100., 200.};
0464 ActsScalar halfZ = 200;
0465
0466
0467 auto bBounds =
0468 std::make_unique<CylinderVolumeBounds>(imr, radii[0u], halfZ);
0469
0470 auto innerPipe = DetectorVolumeFactory::construct(
0471 portalGenerator, tContext, "InnerPipe", transform, std::move(bBounds),
0472 tryAllPortals());
0473
0474
0475 std::map<unsigned int, std::shared_ptr<Portal>> ipContainer;
0476 for (auto [ip, p] : enumerate(innerPipe->portalPtrs())) {
0477 ipContainer[ip] = p;
0478 }
0479
0480
0481 std::vector<std::shared_ptr<DetectorVolume>> rVolumes = {};
0482
0483 for (auto [i, r] : enumerate(radii)) {
0484 if (i > 0) {
0485 auto cBounds =
0486 std::make_unique<CylinderVolumeBounds>(radii[i - 1u], r, halfZ);
0487 rVolumes.push_back(DetectorVolumeFactory::construct(
0488 portalGenerator, tContext, "Cylinder_r" + std::to_string(i),
0489 transform, std::move(cBounds), tryAllPortals()));
0490 }
0491 }
0492
0493 auto protoContainerInR = connectInR(tContext, rVolumes, {}, logLevel);
0494
0495 std::vector<ActsScalar> zValues = {-200., -120, 10., 100., 200.};
0496 std::vector<std::shared_ptr<DetectorVolume>> zVolumes = {};
0497 for (auto [i, z] : enumerate(zValues)) {
0498 if (i > 0) {
0499 auto cBounds = std::make_unique<CylinderVolumeBounds>(
0500 200., 300., 0.5 * (z - zValues[i - 1u]));
0501
0502 ActsScalar zCenter = 0.5 * (z + zValues[i - 1u]);
0503 Transform3 ti = transform;
0504 ti.pretranslate(transform.translation() +
0505 zCenter * transform.rotation().matrix().col(2));
0506
0507
0508 zVolumes.push_back(DetectorVolumeFactory::construct(
0509 portalGenerator, tContext, "Cylinder_z" + std::to_string(i), ti,
0510 std::move(cBounds), tryAllPortals()));
0511 }
0512 }
0513
0514 auto protoContainerInZ = connectInZ(tContext, zVolumes, {}, logLevel);
0515 auto centralContainer = connectInR(
0516 tContext, {ipContainer, protoContainerInR, protoContainerInZ}, {},
0517 logLevel);
0518
0519
0520
0521 auto necBounds = std::make_unique<CylinderVolumeBounds>(imr, 300., 50.);
0522
0523 auto necTransform = Transform3::Identity();
0524 necTransform.pretranslate(Vector3(0., 0., -250));
0525 auto necVolume = DetectorVolumeFactory::construct(
0526 portalGenerator, tContext, "Nec", necTransform, std::move(necBounds),
0527 tryAllPortals());
0528
0529 std::map<unsigned int, std::shared_ptr<Portal>> necContainer;
0530 for (auto [ip, p] : enumerate(necVolume->portalPtrs())) {
0531 necContainer[ip] = p;
0532 }
0533
0534
0535 auto pecInnerBounds =
0536 std::make_unique<CylinderVolumeBounds>(imr, 175., 100.);
0537
0538 auto pecOuterBounds =
0539 std::make_unique<CylinderVolumeBounds>(175., 300., 100.);
0540
0541 auto pecTransform = Transform3::Identity();
0542 pecTransform.pretranslate(Vector3(0., 0., 300));
0543 auto pecInner = DetectorVolumeFactory::construct(
0544 portalGenerator, tContext, "PecInner", pecTransform,
0545 std::move(pecInnerBounds), tryAllPortals());
0546 auto pecOuter = DetectorVolumeFactory::construct(
0547 portalGenerator, tContext, "PecOuter", pecTransform,
0548 std::move(pecOuterBounds), tryAllPortals());
0549
0550 std::vector<std::shared_ptr<DetectorVolume>> pecVolumes = {pecInner,
0551 pecOuter};
0552 auto pecContainer = connectInR(tContext, pecVolumes, {}, logLevel);
0553
0554 auto overallContainer = connectInZ(
0555 tContext, {necContainer, centralContainer, pecContainer}, {}, logLevel);
0556
0557
0558 std::vector<std::shared_ptr<DetectorVolume>> dVolumes;
0559 dVolumes.push_back(innerPipe);
0560 dVolumes.push_back(necVolume);
0561 dVolumes.insert(dVolumes.end(), rVolumes.begin(), rVolumes.end());
0562 dVolumes.insert(dVolumes.end(), zVolumes.begin(), zVolumes.end());
0563 dVolumes.push_back(pecInner);
0564 dVolumes.push_back(pecOuter);
0565
0566
0567 Acts::Experimental::GeometryIdGenerator::Config generatorConfig;
0568 GeometryIdGenerator generator(
0569 generatorConfig, Acts::getDefaultLogger("SequentialIdGenerator",
0570 Acts::Logging::VERBOSE));
0571 auto cache = generator.generateCache();
0572 for (auto& vol : dVolumes) {
0573 generator.assignGeometryId(cache, *vol);
0574 }
0575
0576 auto detector = Detector::makeShared("DetectorFromProtoContainer", dVolumes,
0577 tryRootVolumes());
0578 }
0579 }
0580
0581 BOOST_AUTO_TEST_CASE(WrapContainernRZ) {
0582 ACTS_LOCAL_LOGGER(getDefaultLogger("Container: Wrap", logLevel));
0583 ACTS_INFO("*** Test: create a container in Z-R by wrapping.");
0584
0585
0586 std::vector<std::array<ActsScalar, 3u>> radii = {{0., 100., 500.},
0587 {20., 120., 500.}};
0588
0589 ActsScalar innerHalfZ = 150.;
0590 ActsScalar innerBarrelHalfZ = 75.;
0591 ActsScalar innerEndcapHalfZ = 0.5 * (innerHalfZ - innerBarrelHalfZ);
0592 ActsScalar outerHalfZ = 175.;
0593
0594 Transform3 tf = Transform3::Identity();
0595
0596
0597 for (auto [ir, r] : enumerate(radii)) {
0598 std::string radStr = "_radii_" + std::to_string(ir);
0599 ACTS_INFO(" -> test series innermost radius setup " << radii[ir][0u]);
0600
0601
0602 std::vector<std::shared_ptr<DetectorVolume>> iVolumes = {};
0603
0604 auto iNecBounds = std::make_unique<CylinderVolumeBounds>(
0605 radii[ir][0u], radii[ir][1u], innerEndcapHalfZ);
0606 Transform3 ntf = tf;
0607 ntf.pretranslate(Vector3(0., 0., -innerBarrelHalfZ - innerEndcapHalfZ));
0608 iVolumes.push_back(DetectorVolumeFactory::construct(
0609 portalGenerator, tContext, "InnerNec" + radStr, ntf,
0610 std::move(iNecBounds), tryAllPortals()));
0611
0612 auto iBarrelBounds = std::make_unique<CylinderVolumeBounds>(
0613 radii[ir][0u], radii[ir][1u], innerBarrelHalfZ);
0614 iVolumes.push_back(DetectorVolumeFactory::construct(
0615 portalGenerator, tContext, "InnerBarrel" + radStr, tf,
0616 std::move(iBarrelBounds), tryAllPortals()));
0617
0618 auto iPecBounds = std::make_unique<CylinderVolumeBounds>(
0619 radii[ir][0u], radii[ir][1u], innerEndcapHalfZ);
0620 Transform3 ptf = tf;
0621 ptf.pretranslate(Vector3(0., 0., innerBarrelHalfZ + innerEndcapHalfZ));
0622 iVolumes.push_back(DetectorVolumeFactory::construct(
0623 portalGenerator, tContext, "InnerPec" + radStr, ptf,
0624 std::move(iPecBounds), tryAllPortals()));
0625
0626 auto innerContainer = connectInZ(tContext, iVolumes, {}, logLevel);
0627
0628
0629 auto wBounds = std::make_unique<CutoutCylinderVolumeBounds>(
0630 radii[ir][0u], radii[ir][1u], radii[ir][2u], outerHalfZ, innerHalfZ);
0631 auto wVolume = DetectorVolumeFactory::construct(
0632 portalGenerator, tContext, "WrappingVolume" + radStr, tf,
0633 std::move(wBounds), tryAllPortals());
0634
0635 std::vector<DetectorComponent::PortalContainer> containers;
0636 containers.push_back(innerContainer);
0637
0638 DetectorComponent::PortalContainer outerContainer;
0639 for (auto [ip, p] : enumerate(wVolume->portalPtrs())) {
0640 outerContainer[ip] = p;
0641 }
0642 containers.push_back(outerContainer);
0643
0644 auto detector = wrapInZR(tContext, containers, logLevel);
0645 }
0646 }
0647
0648 BOOST_AUTO_TEST_CASE(RZPhiBoundaries) {
0649 auto portalGenerator = defaultPortalGenerator();
0650
0651 auto innerB = std::make_unique<CylinderVolumeBounds>(0., 20., 100);
0652 auto innerV = DetectorVolumeFactory::construct(
0653 portalGenerator, tContext, "Inner", Transform3::Identity(),
0654 std::move(innerB), tryAllPortals());
0655
0656 auto middleLB = std::make_unique<CylinderVolumeBounds>(20., 60., 5);
0657 auto middleLT = Transform3::Identity();
0658 middleLT.pretranslate(Vector3(0., 0., -95));
0659 auto middleLV = DetectorVolumeFactory::construct(
0660 portalGenerator, tContext, "MiddleLeft", middleLT, std::move(middleLB),
0661 tryAllPortals());
0662
0663 auto middleDB = std::make_unique<CylinderVolumeBounds>(20., 40., 90);
0664 auto middleDV = DetectorVolumeFactory::construct(
0665 portalGenerator, tContext, "MiddleDown", Transform3::Identity(),
0666 std::move(middleDB), tryAllPortals());
0667
0668 auto middleUB = std::make_unique<CylinderVolumeBounds>(40., 60., 90);
0669 auto middleUV = DetectorVolumeFactory::construct(
0670 portalGenerator, tContext, "MiddleUp", Transform3::Identity(),
0671 std::move(middleUB), tryAllPortals());
0672
0673 auto middleRB = std::make_unique<CylinderVolumeBounds>(20., 60., 5);
0674 auto middleRT = Transform3::Identity();
0675 middleRT.pretranslate(Vector3(0., 0., 95));
0676 auto middleRV = DetectorVolumeFactory::construct(
0677 portalGenerator, tContext, "middleRight", middleRT, std::move(middleRB),
0678 tryAllPortals());
0679
0680 auto outerB = std::make_unique<CylinderVolumeBounds>(60., 120., 100);
0681 auto outerV = DetectorVolumeFactory::construct(
0682 portalGenerator, tContext, "Outer", Transform3::Identity(),
0683 std::move(outerB), tryAllPortals());
0684
0685 std::vector<std::shared_ptr<DetectorVolume>> volumes = {
0686 innerV, middleLV, middleDV, middleUV, middleRV, outerV};
0687
0688 auto boundaries =
0689 rzphiBoundaries(tContext, volumes, 0., Acts::Logging::VERBOSE);
0690 BOOST_CHECK_EQUAL(boundaries.size(), 3u);
0691
0692 std::vector<ActsScalar> rBoundaries = {0., 20., 40., 60., 120.};
0693 BOOST_CHECK(boundaries[0u] == rBoundaries);
0694
0695 std::vector<ActsScalar> zBoundaries = {-100., -90., 90., 100.};
0696 BOOST_CHECK(boundaries[1u] == zBoundaries);
0697 BOOST_CHECK_EQUAL(boundaries[2u].size(), 2u);
0698 }
0699
0700 BOOST_AUTO_TEST_CASE(RZPhiBoundariesWithTolerance) {
0701 auto innerB = std::make_unique<CylinderVolumeBounds>(0., 20., 100);
0702 auto innerV = DetectorVolumeFactory::construct(
0703 portalGenerator, tContext, "Inner", Transform3::Identity(),
0704 std::move(innerB), tryAllPortals());
0705
0706 auto outerB = std::make_unique<CylinderVolumeBounds>(20.001, 100., 100);
0707 auto outerV = DetectorVolumeFactory::construct(
0708 portalGenerator, tContext, "Inner", Transform3::Identity(),
0709 std::move(outerB), tryAllPortals());
0710
0711 std::vector<std::shared_ptr<DetectorVolume>> volumes = {innerV, outerV};
0712
0713 auto boundariesWoTol =
0714 rzphiBoundaries(tContext, volumes, 0., Acts::Logging::VERBOSE);
0715 BOOST_CHECK_EQUAL(boundariesWoTol[0u].size(), 4u);
0716
0717 auto boundariesWTol =
0718 rzphiBoundaries(tContext, volumes, 0.01, Acts::Logging::VERBOSE);
0719 BOOST_CHECK_EQUAL(boundariesWTol[0u].size(), 3u);
0720 }
0721
0722 BOOST_AUTO_TEST_SUITE_END()