From 3b3fceace17d24fa6fb5cf80a39f958805e93f11 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 12 Aug 2024 18:37:46 +0200 Subject: [PATCH] work on portal tests --- Core/include/Acts/Geometry/Portal.hpp | 39 ++++- Core/src/Geometry/Portal.cpp | 68 +++++++- Tests/UnitTests/Core/Geometry/PortalTests.cpp | 165 +++++++++++++++++- 3 files changed, 257 insertions(+), 15 deletions(-) diff --git a/Core/include/Acts/Geometry/Portal.hpp b/Core/include/Acts/Geometry/Portal.hpp index 7cd8780f8fa..c813fa27e91 100644 --- a/Core/include/Acts/Geometry/Portal.hpp +++ b/Core/include/Acts/Geometry/Portal.hpp @@ -26,6 +26,12 @@ class DiscSurface; class PortalLinkBase; +class PortalMergingException : public std::exception { + const char* what() const noexcept override { + return "Failure to merge portals"; + } +}; + class Portal { public: Portal(Direction direction, std::unique_ptr link); @@ -33,12 +39,33 @@ class Portal { Portal(Direction direction, std::shared_ptr surface, TrackingVolume& volume); - static std::shared_ptr fuse(const std::shared_ptr& aPortal, + Portal(std::unique_ptr alongNormal, + std::unique_ptr oppositeNormal); + + // portal1 portal2 + // +---+ +---+ + // | | | | + // | | | | + // <----+ | + | +----> + // | | | | + // | | | | + // +---+ +---+ + static std::unique_ptr fuse(const std::shared_ptr& aPortal, const std::shared_ptr& bPortal); - static std::shared_ptr mergeAdjacent( - const std::shared_ptr& aPortal, - const std::shared_ptr& bPortal); + // ^ ^ + // | | + // portal1| portal2| + // +-------+-------+ +-------+-------+ + // | | + | | + // +-------+-------+ +-------+-------+ + // | | + // | | + // v v + static std::unique_ptr merge(const std::shared_ptr& aPortal, + const std::shared_ptr& bPortal, + BinningValue direction, + const Logger& logger = getDummyLogger()); const TrackingVolume* resolveVolume(const GeometryContext& gctx, const Vector3& position, @@ -54,8 +81,8 @@ class Portal { std::shared_ptr m_surface; - std::unique_ptr m_alongNormal; - std::unique_ptr m_oppositeNormal; + std::shared_ptr m_alongNormal; + std::shared_ptr m_oppositeNormal; }; template diff --git a/Core/src/Geometry/Portal.cpp b/Core/src/Geometry/Portal.cpp index 5b4fdfc081e..145b65bcec6 100644 --- a/Core/src/Geometry/Portal.cpp +++ b/Core/src/Geometry/Portal.cpp @@ -32,6 +32,16 @@ Portal::Portal(Direction direction, std::shared_ptr surface, : Portal(direction, std::make_unique(std::move(surface), volume)) {} +Portal::Portal(std::unique_ptr alongNormal, + std::unique_ptr oppositeNormal) { + if (alongNormal != nullptr) { + setLink(Direction::AlongNormal, std::move(alongNormal)); + } + if (oppositeNormal != nullptr) { + setLink(Direction::OppositeNormal, std::move(oppositeNormal)); + } +} + void Portal::setLink(Direction direction, std::unique_ptr link) { assert(link != nullptr); @@ -82,6 +92,56 @@ const TrackingVolume* Portal::resolveVolume(const GeometryContext& gctx, } } +std::unique_ptr Portal::merge(const std::shared_ptr& aPortal, + const std::shared_ptr& bPortal, + BinningValue direction, + const Logger& logger) { + ACTS_DEBUG("Merging to portals along " << direction); + std::unique_ptr mergedAlongNormal = nullptr; + std::unique_ptr mergedOppositeNormal = nullptr; + + bool aHasAlongNormal = aPortal->m_alongNormal != nullptr; + bool aHasOppositeNormal = aPortal->m_oppositeNormal != nullptr; + bool bHasAlongNormal = bPortal->m_alongNormal != nullptr; + bool bHasOppositeNormal = bPortal->m_oppositeNormal != nullptr; + + if (aHasAlongNormal != bHasAlongNormal || + aHasOppositeNormal != bHasOppositeNormal) { + ACTS_ERROR("Portals do not have the same links attached"); + throw PortalMergingException(); + } + + if (aPortal->m_alongNormal != nullptr) { + if (bPortal->m_alongNormal == nullptr) { + ACTS_ERROR( + "Portal A has link along normal, while b does not. This is not " + "supported"); + throw PortalMergingException(); + } + + ACTS_VERBOSE("Portals have links along normal, merging"); + mergedAlongNormal = PortalLinkBase::merge( + aPortal->m_alongNormal, bPortal->m_alongNormal, direction, logger); + } + + if (aPortal->m_oppositeNormal != nullptr) { + if (bPortal->m_oppositeNormal == nullptr) { + ACTS_ERROR( + "Portal A has link opposite normal, while b does not. This is not " + "supported"); + throw PortalMergingException(); + } + + ACTS_VERBOSE("Portals have links opposite normal, merging"); + mergedOppositeNormal = + PortalLinkBase::merge(aPortal->m_oppositeNormal, + bPortal->m_oppositeNormal, direction, logger); + } + + return std::make_unique(std::move(mergedAlongNormal), + std::move(mergedOppositeNormal)); +} + void PortalLinkBase::checkMergePreconditions(const PortalLinkBase& a, const PortalLinkBase& b, BinningValue direction) { @@ -130,7 +190,7 @@ std::unique_ptr PortalLinkBase::merge( const Logger& logger) { ACTS_DEBUG("Merging two arbitrary portals"); - ACTS_VERBOSE(" - a: " << *a); + ACTS_VERBOSE(" - a: " << *a); ACTS_VERBOSE(" - b: " << *b); checkMergePreconditions(*a, *b, direction); @@ -157,7 +217,7 @@ std::unique_ptr PortalLinkBase::merge( } else if (auto bTrivial = std::dynamic_pointer_cast(b); bTrivial) { - ACTS_WARNING("Merging a grid portal with a trivial portal"); + ACTS_VERBOSE("Merging a grid portal with a trivial portal"); return GridPortalLink::merge(aGrid, bTrivial->makeGrid(direction), direction, logger); @@ -175,14 +235,14 @@ std::unique_ptr PortalLinkBase::merge( } else if (auto aTrivial = std::dynamic_pointer_cast(a); aTrivial) { if (auto bGrid = std::dynamic_pointer_cast(b); bGrid) { - ACTS_WARNING("Merging a trivial portal with a grid portal"); + ACTS_VERBOSE("Merging a trivial portal with a grid portal"); return GridPortalLink::merge(aTrivial->makeGrid(direction), bGrid, direction, logger); } else if (auto bTrivial = std::dynamic_pointer_cast(b); bTrivial) { - ACTS_WARNING("Merging two trivial portals"); + ACTS_VERBOSE("Merging two trivial portals"); return GridPortalLink::merge(aTrivial->makeGrid(direction), bTrivial->makeGrid(direction), direction, logger); diff --git a/Tests/UnitTests/Core/Geometry/PortalTests.cpp b/Tests/UnitTests/Core/Geometry/PortalTests.cpp index 1c42983fae4..90177a159c4 100644 --- a/Tests/UnitTests/Core/Geometry/PortalTests.cpp +++ b/Tests/UnitTests/Core/Geometry/PortalTests.cpp @@ -14,6 +14,7 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/GridPortalLink.hpp" #include "Acts/Geometry/Portal.hpp" #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Geometry/TrivialPortalLink.hpp" @@ -21,6 +22,9 @@ #include "Acts/Surfaces/DiscSurface.hpp" #include "Acts/Surfaces/RadialBounds.hpp" #include "Acts/Surfaces/Surface.hpp" +#include "Acts/Surfaces/SurfaceMergingException.hpp" +#include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/ThrowAssert.hpp" using namespace Acts::UnitLiterals; @@ -53,13 +57,15 @@ BOOST_AUTO_TEST_SUITE(Merging) BOOST_AUTO_TEST_CASE(Cylinder) { auto vol1 = makeDummyVolume(); + vol1->setVolumeName("vol1"); auto vol2 = makeDummyVolume(); + vol2->setVolumeName("vol2"); auto cyl1 = Surface::makeShared( - Transform3{Translation3{Vector3::UnitZ() * -50_mm}}, 50_mm, 100_mm); + Transform3{Translation3{Vector3::UnitZ() * -100_mm}}, 50_mm, 100_mm); auto cyl2 = Surface::makeShared( - Transform3{Translation3{Vector3::UnitZ() * 50_mm}}, 50_mm, 100_mm); + Transform3{Translation3{Vector3::UnitZ() * 100_mm}}, 50_mm, 100_mm); auto portal1 = std::make_shared( Direction::AlongNormal, std::make_unique(cyl1, *vol1)); @@ -76,6 +82,40 @@ BOOST_AUTO_TEST_CASE(Cylinder) { auto portal2 = std::make_shared(Direction::AlongNormal, cyl2, *vol2); BOOST_REQUIRE(portal2); + BOOST_CHECK_EQUAL(portal2->resolveVolume(gctx, Vector3{50_mm, 0_mm, -50_mm}, + -Vector3::UnitX()), + nullptr); + + BOOST_CHECK_EQUAL(portal2->resolveVolume(gctx, Vector3{50_mm, 0_mm, -50_mm}, + Vector3::UnitX()), + vol2.get()); + + auto portal3 = std::make_shared( + std::make_unique(cyl2, *vol2), nullptr); + + BOOST_CHECK_NE(portal3->getLink(Direction::AlongNormal), nullptr); + BOOST_CHECK_EQUAL(portal3->getLink(Direction::OppositeNormal), nullptr); + + auto portal4 = std::make_shared( + nullptr, std::make_unique(cyl2, *vol2)); + + BOOST_CHECK_EQUAL(portal4->getLink(Direction::AlongNormal), nullptr); + BOOST_CHECK_NE(portal4->getLink(Direction::OppositeNormal), nullptr); + + // Not mergeable because 1 has portal along but 4 has portal oppsite + // ^ + // | + // portal1| portal2 + // +-------+-------+ + +---------------+ + // | | | | + // +---------------+ +-------+-------+ + // | + // | + // v + BOOST_CHECK_THROW( + Portal::merge(portal1, portal4, BinningValue::binZ, *logger), + PortalMergingException); + BOOST_CHECK_EQUAL(portal2->resolveVolume(gctx, Vector3{50_mm, 0_mm, 50_mm}, Vector3::UnitX()), vol2.get()); @@ -84,10 +124,120 @@ BOOST_AUTO_TEST_CASE(Cylinder) { -Vector3::UnitX()), nullptr); - // @TODO: Test merging portals along z - // @TODO: Test portals in opposite directions fail to merge along z + BOOST_CHECK_THROW( + Portal::merge(portal1, portal2, BinningValue::binRPhi, *logger), + SurfaceMergingException); + + // ^ ^ + // | | + // portal1| portal2| + // +-------+-------+ + +-------+-------+ + // | | | | + // +---------------+ +---------------+ + + auto merged12 = Portal::merge(portal1, portal2, BinningValue::binZ, *logger); + BOOST_REQUIRE(merged12); + BOOST_CHECK_NE(merged12->getLink(Direction::AlongNormal), nullptr); + BOOST_CHECK_EQUAL(merged12->getLink(Direction::OppositeNormal), nullptr); + + auto grid12 = dynamic_cast( + merged12->getLink(Direction::AlongNormal)); + grid12->printContents(std::cout); + + BOOST_CHECK_EQUAL(merged12->resolveVolume(gctx, Vector3{50_mm, 0_mm, -50_mm}, + Vector3::UnitX()), + vol1.get()); + + BOOST_CHECK_EQUAL(merged12->resolveVolume(gctx, Vector3{50_mm, 0_mm, 50_mm}, + Vector3::UnitX()), + vol2.get()); + + BOOST_CHECK_EQUAL(merged12->resolveVolume(gctx, Vector3{50_mm, 0_mm, -50_mm}, + -Vector3::UnitX()), + nullptr); + + BOOST_CHECK_EQUAL(merged12->resolveVolume(gctx, Vector3{50_mm, 0_mm, 50_mm}, + -Vector3::UnitX()), + nullptr); + + // Can't merge with self because surfaces are not mergeable + BOOST_CHECK_THROW( + Portal::merge(portal1, portal1, BinningValue::binZ, *logger), + AssertionFailureException); +} + +BOOST_AUTO_TEST_CASE(Disc) { + auto vol1 = makeDummyVolume(); + vol1->setVolumeName("vol1"); + auto vol2 = makeDummyVolume(); + vol2->setVolumeName("vol2"); + auto vol3 = makeDummyVolume(); + vol3->setVolumeName("vol3"); + auto vol4 = makeDummyVolume(); + vol4->setVolumeName("vol4"); + + auto disc1 = Surface::makeShared( + Transform3::Identity(), std::make_shared(50_mm, 100_mm)); + + auto disc2 = Surface::makeShared( + Transform3::Identity(), std::make_shared(100_mm, 150_mm)); + + auto portal1 = std::make_shared( + std::make_unique(disc1, *vol1), + std::make_unique(disc1, *vol2)); + + auto portal2 = std::make_shared( + std::make_unique(disc2, *vol3), + std::make_unique(disc2, *vol4)); + + BOOST_CHECK_EQUAL(portal1->resolveVolume(gctx, Vector3{55_mm, 0_mm, 0_mm}, + Vector3::UnitZ()), + vol1.get()); + BOOST_CHECK_EQUAL(portal1->resolveVolume(gctx, Vector3{55_mm, 0_mm, 0_mm}, + -Vector3::UnitZ()), + vol2.get()); + + BOOST_CHECK_EQUAL(portal2->resolveVolume(gctx, Vector3{105_mm, 0_mm, 0_mm}, + Vector3::UnitZ()), + vol3.get()); + BOOST_CHECK_EQUAL(portal2->resolveVolume(gctx, Vector3{105_mm, 0_mm, 0_mm}, + -Vector3::UnitZ()), + vol4.get()); + + BOOST_CHECK_THROW( + Portal::merge(portal1, portal2, BinningValue::binZ, *logger), + AssertionFailureException); + + BOOST_CHECK_THROW( + Portal::merge(portal1, portal2, BinningValue::binPhi, *logger), + SurfaceMergingException); + + // ^ ^ + // | | + // portal1| portal2| + // +-------+-------+ +-------+-------+ + // | | + | | + // +-------+-------+ +-------+-------+ + // | | + // | | + // v v + auto merged12 = Portal::merge(portal1, portal2, BinningValue::binR, *logger); + BOOST_REQUIRE(merged12); + + BOOST_CHECK_EQUAL(merged12->resolveVolume(gctx, Vector3{55_mm, 0_mm, 0_mm}, + Vector3::UnitZ()), + vol1.get()); + BOOST_CHECK_EQUAL(merged12->resolveVolume(gctx, Vector3{55_mm, 0_mm, 0_mm}, + -Vector3::UnitZ()), + vol2.get()); + + BOOST_CHECK_EQUAL(merged12->resolveVolume(gctx, Vector3{105_mm, 0_mm, 0_mm}, + Vector3::UnitZ()), + vol3.get()); + BOOST_CHECK_EQUAL(merged12->resolveVolume(gctx, Vector3{105_mm, 0_mm, 0_mm}, + -Vector3::UnitZ()), + vol4.get()); } -BOOST_AUTO_TEST_CASE(Disc) {} BOOST_AUTO_TEST_SUITE_END() // Merging @@ -101,6 +251,11 @@ BOOST_AUTO_TEST_CASE(ConstructionFromVolume) { // - Cylinder } +BOOST_AUTO_TEST_CASE(Construction) { + // @TODO: Displaced surfaces fail + // @TODO: Surface unification to same instance +} + BOOST_AUTO_TEST_SUITE_END() // Portals BOOST_AUTO_TEST_SUITE_END() // Geometry