From c7cbb7168ef12770eda98c6aba729252c93aff21 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 6 Mar 2026 07:37:01 +0100 Subject: [PATCH 1/2] Improve safety calculations in Tessellated solid Optimization: Cache safety and only recalculate when becoming invalid. This works since safety can be underestimated and does not need to be precise. Precise safety evaluation for Tessellated is expensive. --- .../include/DetectorsBase/O2Tessellated.h | 8 +++++++ Detectors/Base/src/O2Tessellated.cxx | 24 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Detectors/Base/include/DetectorsBase/O2Tessellated.h b/Detectors/Base/include/DetectorsBase/O2Tessellated.h index 0a1cee8b3e01f..7a1a3945c80d8 100644 --- a/Detectors/Base/include/DetectorsBase/O2Tessellated.h +++ b/Detectors/Base/include/DetectorsBase/O2Tessellated.h @@ -133,6 +133,14 @@ class O2Tessellated : public TGeoBBox template Double_t SafetyKernel(const Double_t* point, bool in, int* closest_facet_id = nullptr) const; + // cached values for safety + mutable float mLast_x; + mutable float mLast_y; + mutable float mLast_z; + mutable float mCachedSafety; + mutable size_t cached_counter = 0; + mutable size_t call_counter = 0; + ClassDefOverride(O2Tessellated, 1) // tessellated shape class }; diff --git a/Detectors/Base/src/O2Tessellated.cxx b/Detectors/Base/src/O2Tessellated.cxx index 256a70e5a697a..80d5935eff615 100644 --- a/Detectors/Base/src/O2Tessellated.cxx +++ b/Detectors/Base/src/O2Tessellated.cxx @@ -1349,8 +1349,30 @@ Double_t O2Tessellated::Safety(const Double_t* point, Bool_t in) const // we could use some caching here (in future) since queries to the solid will likely // be made with some locality + if (in) { + call_counter++; + // distance to last known evaluation + const auto xd = float(point[0]) - mLast_x; + const auto yd = float(point[1]) - mLast_y; + const auto zd = float(point[2]) - mLast_z; + const auto d2 = xd * xd + yd * yd + zd * zd; + + if (d2 < mCachedSafety * mCachedSafety) { + // we moved less than known safety + mCachedSafety - std::sqrt(d2); + cached_counter++; + } + } + // fall-back to precise safety kernel - return SafetyKernel(point, in); + const auto safety = SafetyKernel(point, in); + if (in) { + mLast_x = point[0]; + mLast_y = point[1]; + mLast_z = point[2]; + mCachedSafety = safety; + } + return safety; } //////////////////////////////////////////////////////////////////////////////// From 5afccc84cfd693fd53df0b1d679d06d649085310 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 6 Mar 2026 16:56:23 +0100 Subject: [PATCH 2/2] Fix cached safety calculation in O2Tessellated --- Detectors/Base/src/O2Tessellated.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/Base/src/O2Tessellated.cxx b/Detectors/Base/src/O2Tessellated.cxx index 80d5935eff615..5c52625841868 100644 --- a/Detectors/Base/src/O2Tessellated.cxx +++ b/Detectors/Base/src/O2Tessellated.cxx @@ -1359,8 +1359,8 @@ Double_t O2Tessellated::Safety(const Double_t* point, Bool_t in) const if (d2 < mCachedSafety * mCachedSafety) { // we moved less than known safety - mCachedSafety - std::sqrt(d2); cached_counter++; + return mCachedSafety - std::sqrt(d2); } } @@ -1528,4 +1528,4 @@ void O2Tessellated::CalculateNormals() } } -// NOLINTEND \ No newline at end of file +// NOLINTEND