From 0c21e07ecb76fbb0302623ee44e0aabc599e172b Mon Sep 17 00:00:00 2001 From: Julien Esseiva Date: Mon, 6 Jan 2025 14:22:43 -0800 Subject: [PATCH] Support sense caching for future lazy evaluation (#1539) --- src/corecel/math/Algorithms.hh | 4 +- src/orange/OrangeData.hh | 3 +- src/orange/OrangeTrackView.hh | 6 +- src/orange/OrangeTypes.cc | 18 -- src/orange/OrangeTypes.hh | 82 --------- src/orange/SenseUtils.hh | 173 ++++++++++++++++++ .../orangeinp/detail/InfixStringBuilder.hh | 1 + src/orange/surf/ConeAligned.hh | 1 + src/orange/surf/CylAligned.hh | 1 + src/orange/surf/CylCentered.hh | 1 + src/orange/surf/GeneralQuadric.hh | 1 + src/orange/surf/Plane.hh | 1 + src/orange/surf/PlaneAligned.hh | 1 + src/orange/surf/SimpleQuadric.hh | 1 + src/orange/surf/Sphere.hh | 1 + src/orange/surf/SphereCentered.hh | 1 + src/orange/univ/SimpleUnitTracker.hh | 1 + src/orange/univ/detail/InfixEvaluator.hh | 4 +- src/orange/univ/detail/LazySenseCalculator.hh | 138 ++++++++++++++ src/orange/univ/detail/LogicEvaluator.hh | 24 ++- src/orange/univ/detail/SenseCalculator.hh | 8 +- src/orange/univ/detail/Types.hh | 3 +- test/orange/OrangeGeoTestBase.cc | 2 +- test/orange/OrangeGeoTestBase.hh | 2 +- test/orange/surf/LocalSurfaceVisitor.test.hh | 4 +- test/orange/univ/RectArrayTracker.test.cc | 2 +- test/orange/univ/SimpleUnitTracker.test.cc | 2 +- test/orange/univ/SimpleUnitTracker.test.hh | 3 +- test/orange/univ/TrackerVisitor.test.cc | 3 +- .../orange/univ/detail/LogicEvaluator.test.cc | 2 +- .../univ/detail/SenseCalculator.test.cc | 4 +- 31 files changed, 371 insertions(+), 127 deletions(-) create mode 100644 src/orange/SenseUtils.hh create mode 100644 src/orange/univ/detail/LazySenseCalculator.hh diff --git a/src/corecel/math/Algorithms.hh b/src/corecel/math/Algorithms.hh index a4fa4881e1..456c3b9623 100644 --- a/src/corecel/math/Algorithms.hh +++ b/src/corecel/math/Algorithms.hh @@ -739,9 +739,9 @@ CELER_FORCEINLINE_FUNCTION void sincospi(double a, double* s, double* c) */ template #if defined(_MSC_VER) -inline int popcount(T x) noexcept +CELER_FORCEINLINE_FUNCTION int popcount(T x) noexcept #else -inline constexpr int popcount(T x) noexcept +CELER_CONSTEXPR_FUNCTION int popcount(T x) noexcept #endif { static_assert(sizeof(T) <= 8, diff --git a/src/orange/OrangeData.hh b/src/orange/OrangeData.hh index 0f2af9042c..278b1501a0 100644 --- a/src/orange/OrangeData.hh +++ b/src/orange/OrangeData.hh @@ -16,6 +16,7 @@ #include "geocel/BoundingBox.hh" #include "OrangeTypes.hh" +#include "SenseUtils.hh" #include "univ/detail/Types.hh" #include "detail/BIHData.hh" @@ -471,7 +472,7 @@ struct OrangeStateData Items universe; // Scratch space with dimensions {track}{max_faces} - Items temp_sense; + Items temp_sense; // Scratch space with dimensions {track}{max_intersections} Items temp_face; diff --git a/src/orange/OrangeTrackView.hh b/src/orange/OrangeTrackView.hh index cd248f1394..14ed342e2e 100644 --- a/src/orange/OrangeTrackView.hh +++ b/src/orange/OrangeTrackView.hh @@ -196,7 +196,7 @@ class OrangeTrackView find_next_step_impl(detail::Intersection isect); // Create local sense reference - inline CELER_FUNCTION Span make_temp_sense() const; + inline CELER_FUNCTION Span make_temp_sense() const; // Create local distance inline CELER_FUNCTION detail::TempNextFace make_temp_next() const; @@ -1038,11 +1038,11 @@ CELER_FUNCTION real_type OrangeTrackView::find_safety(real_type) /*! * Get a reference to the current volume, or to world volume if outside. */ -CELER_FUNCTION Span OrangeTrackView::make_temp_sense() const +CELER_FUNCTION Span OrangeTrackView::make_temp_sense() const { auto const max_faces = params_.scalars.max_faces; auto offset = track_slot_.get() * max_faces; - return states_.temp_sense[AllItems{}].subspan( + return states_.temp_sense[AllItems{}].subspan( offset, max_faces); } diff --git a/src/orange/OrangeTypes.cc b/src/orange/OrangeTypes.cc index 3aa14f183f..7e8b740eb5 100644 --- a/src/orange/OrangeTypes.cc +++ b/src/orange/OrangeTypes.cc @@ -144,24 +144,6 @@ char const* to_cstring(TransformType value) return to_cstring_impl(value); } -//---------------------------------------------------------------------------// -/*! - * Get a string corresponding to a signed sense. - */ -char const* to_cstring(SignedSense s) -{ - switch (s) - { - case SignedSense::inside: - return "inside"; - case SignedSense::on: - return "on"; - case SignedSense::outside: - return "outside"; - } - return ""; -} - //---------------------------------------------------------------------------// /*! * Get a string corresponding to a transform type. diff --git a/src/orange/OrangeTypes.hh b/src/orange/OrangeTypes.hh index cc603f1cf8..b59f26099e 100644 --- a/src/orange/OrangeTypes.hh +++ b/src/orange/OrangeTypes.hh @@ -10,7 +10,6 @@ #include #include #include -#include #include "corecel/Macros.hh" #include "corecel/OpaqueId.hh" @@ -349,34 +348,6 @@ extern template struct Tolerance; //---------------------------------------------------------------------------// // HELPER FUNCTIONS (HOST/DEVICE) -//---------------------------------------------------------------------------// -/*! - * Convert a boolean value to a Sense enum. - */ -CELER_CONSTEXPR_FUNCTION Sense to_sense(bool s) -{ - return static_cast(s); -} - -//---------------------------------------------------------------------------// -/*! - * Change the sense across a surface. - */ -[[nodiscard]] CELER_CONSTEXPR_FUNCTION Sense flip_sense(Sense orig) -{ - return static_cast(!static_cast(orig)); -} - -//---------------------------------------------------------------------------// -/*! - * Change the sense across a surface. - */ -[[nodiscard]] CELER_CONSTEXPR_FUNCTION SignedSense flip_sense(SignedSense orig) -{ - using IntT = std::underlying_type_t; - return static_cast(-static_cast(orig)); -} - //---------------------------------------------------------------------------// /*! * Change whether a boundary crossing is reentrant or exiting. @@ -387,50 +358,6 @@ flip_boundary(BoundaryResult orig) return static_cast(!static_cast(orig)); } -//---------------------------------------------------------------------------// -/*! - * Evaluate the sense based on the LHS expression of the quadric equation. - * - * This is an optimized jump-free version of: - * \code - return quadric == 0 ? SignedSense::on - : quadric < 0 ? SignedSense::inside - : SignedSense::outside; - * \endcode - * as - * \code - int gz = !(quadric <= 0) ? 1 : 0; - int lz = quadric < 0 ? 1 : 0; - return static_cast(gz - lz); - * \endcode - * and compressed into a single line. - * - * NaN values are treated as "outside". - */ -[[nodiscard]] CELER_CONSTEXPR_FUNCTION SignedSense -real_to_sense(real_type quadric) -{ - return static_cast(!(quadric <= 0) - (quadric < 0)); -} - -//---------------------------------------------------------------------------// -/*! - * Convert a signed sense to a Sense enum. - */ -CELER_CONSTEXPR_FUNCTION Sense to_sense(SignedSense s) -{ - return Sense(static_cast(s) >= 0); -} - -//---------------------------------------------------------------------------// -/*! - * Convert a signed sense to a surface state. - */ -CELER_CONSTEXPR_FUNCTION SurfaceState to_surface_state(SignedSense s) -{ - return s == SignedSense::on ? SurfaceState::on : SurfaceState::off; -} - //---------------------------------------------------------------------------// /*! * Sentinel value indicating "no intersection". @@ -466,21 +393,12 @@ CELER_CONSTEXPR_FUNCTION bool is_operator_token(logic_int lv) //---------------------------------------------------------------------------// // HELPER FUNCTIONS (HOST) //---------------------------------------------------------------------------// -//! Get a printable character corresponding to a sense. -inline constexpr char to_char(Sense s) -{ - return s == Sense::inside ? '-' : '+'; -} - // Get a string corresponding to a surface type char const* to_cstring(SurfaceType); // Get a string corresponding to a transform type char const* to_cstring(TransformType); -// Get a string corresponding to a signed sense -char const* to_cstring(SignedSense); - // Get a string corresponding to a surface state inline char const* to_cstring(SurfaceState s) { diff --git a/src/orange/SenseUtils.hh b/src/orange/SenseUtils.hh new file mode 100644 index 0000000000..c3bc1dd427 --- /dev/null +++ b/src/orange/SenseUtils.hh @@ -0,0 +1,173 @@ +//------------------------------- -*- C++ -*- -------------------------------// +// Copyright Celeritas contributors: see top-level COPYRIGHT file for details +// SPDX-License-Identifier: (Apache-2.0 OR MIT) +//---------------------------------------------------------------------------// +//! \file orange/SenseUtils.hh +//! \brief Sense helper functions and types. +//---------------------------------------------------------------------------// +#pragma once + +#include "corecel/Macros.hh" +#include "corecel/cont/Bitset.hh" + +#include "OrangeTypes.hh" + +namespace celeritas +{ +//---------------------------------------------------------------------------// +// HELPER FUNCTIONS (HOST/DEVICE) +//---------------------------------------------------------------------------// +/*! + * Convert a boolean value to a Sense enum. + */ +CELER_CONSTEXPR_FUNCTION Sense to_sense(bool s) +{ + return static_cast(s); +} + +//---------------------------------------------------------------------------// +/*! + * Change the sense across a surface. + */ +[[nodiscard]] CELER_CONSTEXPR_FUNCTION Sense flip_sense(Sense orig) +{ + return static_cast(!static_cast(orig)); +} + +//---------------------------------------------------------------------------// +/*! + * Change the sense across a surface. + */ +[[nodiscard]] CELER_CONSTEXPR_FUNCTION SignedSense flip_sense(SignedSense orig) +{ + using IntT = std::underlying_type_t; + return static_cast(-static_cast(orig)); +} + +//---------------------------------------------------------------------------// +/*! + * Evaluate the sense based on the LHS expression of the quadric equation. + * + * This is an optimized jump-free version of: + * \code + return quadric == 0 ? SignedSense::on + : quadric < 0 ? SignedSense::inside + : SignedSense::outside; + * \endcode + * as + * \code + int gz = !(quadric <= 0) ? 1 : 0; + int lz = quadric < 0 ? 1 : 0; + return static_cast(gz - lz); + * \endcode + * and compressed into a single line. + * + * NaN values are treated as "outside". + */ +[[nodiscard]] CELER_CONSTEXPR_FUNCTION SignedSense +real_to_sense(real_type quadric) +{ + return static_cast(!(quadric <= 0) - (quadric < 0)); +} + +//---------------------------------------------------------------------------// +/*! + * Convert a signed sense to a Sense enum. + */ +CELER_CONSTEXPR_FUNCTION Sense to_sense(SignedSense s) +{ + return Sense(static_cast(s) >= 0); +} + +//---------------------------------------------------------------------------// +/*! + * Convert a signed sense to a surface state. + */ +CELER_CONSTEXPR_FUNCTION SurfaceState to_surface_state(SignedSense s) +{ + return s == SignedSense::on ? SurfaceState::on : SurfaceState::off; +} + +//---------------------------------------------------------------------------// +// HELPER FUNCTIONS (HOST) +//---------------------------------------------------------------------------// +//! Get a printable character corresponding to a sense. +inline constexpr char to_char(Sense s) +{ + return s == Sense::inside ? '-' : '+'; +} + +// Get a string corresponding to a signed sense +inline char const* to_cstring(SignedSense s) +{ + switch (s) + { + case SignedSense::inside: + return "inside"; + case SignedSense::on: + return "on"; + case SignedSense::outside: + return "outside"; + } + return ""; +} + +//---------------------------------------------------------------------------// +// CLASSES +//---------------------------------------------------------------------------// +/*! + * Wrapper for a sense value that is optionally set. + */ +class SenseValue +{ + private: + enum : char + { + sense_bit, + is_assigned_bit, + }; + + public: + constexpr SenseValue() = default; + + //! Construct with a sense value + CELER_CONSTEXPR_FUNCTION SenseValue(Sense sense) + { + sense_[sense_bit] = static_cast(sense); + sense_[is_assigned_bit] = true; + } + + //! Convert to a sense value + CELER_CONSTEXPR_FUNCTION operator Sense() const + { + return to_sense(sense_[sense_bit]); + } + + //! Convert to a boolean value + CELER_CONSTEXPR_FUNCTION explicit operator bool() const + { + return sense_[sense_bit]; + } + + //! Assign a sense value + CELER_CONSTEXPR_FUNCTION SenseValue& operator=(Sense sense) + { + sense_[sense_bit] = static_cast(sense); + sense_[is_assigned_bit] = true; + return *this; + } + + //! Check wether there is a cached sense value + CELER_CONSTEXPR_FUNCTION bool is_assigned() const + { + return sense_[is_assigned_bit]; + } + + //! Clear the sense value + CELER_CONSTEXPR_FUNCTION void clear() { sense_.reset(); } + + private: + Bitset<2> sense_; +}; + +} // namespace celeritas diff --git a/src/orange/orangeinp/detail/InfixStringBuilder.hh b/src/orange/orangeinp/detail/InfixStringBuilder.hh index 44668dde17..4f89ebab8d 100644 --- a/src/orange/orangeinp/detail/InfixStringBuilder.hh +++ b/src/orange/orangeinp/detail/InfixStringBuilder.hh @@ -9,6 +9,7 @@ #include #include "corecel/cont/VariantUtils.hh" +#include "orange/SenseUtils.hh" #include "../CsgTree.hh" diff --git a/src/orange/surf/ConeAligned.hh b/src/orange/surf/ConeAligned.hh index 0a0a8c08e8..1010a7bfc8 100644 --- a/src/orange/surf/ConeAligned.hh +++ b/src/orange/surf/ConeAligned.hh @@ -11,6 +11,7 @@ #include "corecel/cont/Span.hh" #include "corecel/math/ArrayUtils.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" #include "detail/QuadraticSolver.hh" diff --git a/src/orange/surf/CylAligned.hh b/src/orange/surf/CylAligned.hh index fababf1ffe..37026c6712 100644 --- a/src/orange/surf/CylAligned.hh +++ b/src/orange/surf/CylAligned.hh @@ -11,6 +11,7 @@ #include "corecel/cont/Span.hh" #include "corecel/math/ArrayUtils.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" #include "detail/QuadraticSolver.hh" diff --git a/src/orange/surf/CylCentered.hh b/src/orange/surf/CylCentered.hh index 1a0d1dc4be..d0decfd35b 100644 --- a/src/orange/surf/CylCentered.hh +++ b/src/orange/surf/CylCentered.hh @@ -11,6 +11,7 @@ #include "corecel/cont/Span.hh" #include "corecel/math/ArrayUtils.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" #include "detail/QuadraticSolver.hh" diff --git a/src/orange/surf/GeneralQuadric.hh b/src/orange/surf/GeneralQuadric.hh index e7c2652852..44f8c7bd71 100644 --- a/src/orange/surf/GeneralQuadric.hh +++ b/src/orange/surf/GeneralQuadric.hh @@ -13,6 +13,7 @@ #include "corecel/cont/Span.hh" #include "corecel/math/ArrayUtils.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" #include "detail/QuadraticSolver.hh" diff --git a/src/orange/surf/Plane.hh b/src/orange/surf/Plane.hh index 99555f2690..d63319eb8a 100644 --- a/src/orange/surf/Plane.hh +++ b/src/orange/surf/Plane.hh @@ -11,6 +11,7 @@ #include "corecel/cont/Span.hh" #include "corecel/math/ArrayUtils.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" namespace celeritas { diff --git a/src/orange/surf/PlaneAligned.hh b/src/orange/surf/PlaneAligned.hh index 7f6dfe0085..62ae28751b 100644 --- a/src/orange/surf/PlaneAligned.hh +++ b/src/orange/surf/PlaneAligned.hh @@ -10,6 +10,7 @@ #include "corecel/cont/Array.hh" #include "corecel/cont/Span.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" namespace celeritas { diff --git a/src/orange/surf/SimpleQuadric.hh b/src/orange/surf/SimpleQuadric.hh index 825ab2ae18..b2815d6149 100644 --- a/src/orange/surf/SimpleQuadric.hh +++ b/src/orange/surf/SimpleQuadric.hh @@ -13,6 +13,7 @@ #include "corecel/cont/Span.hh" #include "corecel/math/ArrayUtils.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" #include "detail/QuadraticSolver.hh" diff --git a/src/orange/surf/Sphere.hh b/src/orange/surf/Sphere.hh index 04943610d2..c882db6461 100644 --- a/src/orange/surf/Sphere.hh +++ b/src/orange/surf/Sphere.hh @@ -11,6 +11,7 @@ #include "corecel/cont/Span.hh" #include "corecel/math/Algorithms.hh" #include "corecel/math/ArrayUtils.hh" +#include "orange/SenseUtils.hh" #include "detail/QuadraticSolver.hh" diff --git a/src/orange/surf/SphereCentered.hh b/src/orange/surf/SphereCentered.hh index 71311b0a8a..2800bc157a 100644 --- a/src/orange/surf/SphereCentered.hh +++ b/src/orange/surf/SphereCentered.hh @@ -11,6 +11,7 @@ #include "corecel/cont/Span.hh" #include "corecel/math/Algorithms.hh" #include "corecel/math/ArrayUtils.hh" +#include "orange/SenseUtils.hh" #include "detail/QuadraticSolver.hh" diff --git a/src/orange/univ/SimpleUnitTracker.hh b/src/orange/univ/SimpleUnitTracker.hh index 8bc4b7fa97..2277d3af58 100644 --- a/src/orange/univ/SimpleUnitTracker.hh +++ b/src/orange/univ/SimpleUnitTracker.hh @@ -9,6 +9,7 @@ #include "corecel/Assert.hh" #include "corecel/math/Algorithms.hh" #include "orange/OrangeData.hh" +#include "orange/OrangeTypes.hh" #include "orange/detail/BIHEnclosingVolFinder.hh" #include "orange/surf/LocalSurfaceVisitor.hh" diff --git a/src/orange/univ/detail/InfixEvaluator.hh b/src/orange/univ/detail/InfixEvaluator.hh index 347a52738a..6869508e82 100644 --- a/src/orange/univ/detail/InfixEvaluator.hh +++ b/src/orange/univ/detail/InfixEvaluator.hh @@ -80,7 +80,7 @@ CELER_FUNCTION bool InfixEvaluator::operator()(F&& eval_sense) const { if (logic_int const lgc{logic_[i]}; !logic::is_operator_token(lgc)) { - result = eval_sense(FaceId{lgc}); + result = static_cast(eval_sense(FaceId{lgc})); } else if ((lgc == logic::lor && result) || (lgc == logic::land && !result)) @@ -110,7 +110,7 @@ CELER_FUNCTION bool InfixEvaluator::operator()(F&& eval_sense) const // negation of a sub-expression is not supported CELER_ASSUME(i + 1 < logic_.size()); CELER_EXPECT(!logic::is_operator_token(logic_[i + 1])); - result = !eval_sense(FaceId{logic_[++i]}); + result = !static_cast(eval_sense(FaceId{logic_[++i]})); } ++i; } diff --git a/src/orange/univ/detail/LazySenseCalculator.hh b/src/orange/univ/detail/LazySenseCalculator.hh new file mode 100644 index 0000000000..e576253a22 --- /dev/null +++ b/src/orange/univ/detail/LazySenseCalculator.hh @@ -0,0 +1,138 @@ +//------------------------------- -*- C++ -*- -------------------------------// +// Copyright Celeritas contributors: see top-level COPYRIGHT file for details +// SPDX-License-Identifier: (Apache-2.0 OR MIT) +//---------------------------------------------------------------------------// +//! \file orange/univ/detail/LazySenseCalculator.hh +//---------------------------------------------------------------------------// +#pragma once + +#include "corecel/Assert.hh" +#include "corecel/Macros.hh" +#include "corecel/cont/Span.hh" +#include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" +#include "orange/surf/LocalSurfaceVisitor.hh" +#include "orange/univ/detail/Types.hh" + +#include "SurfaceFunctors.hh" +#include "../VolumeView.hh" + +namespace celeritas +{ +namespace detail +{ +//---------------------------------------------------------------------------// +/*! + * Calculate senses with a fixed particle position. + * + * This is an implementation detail used in initialization, boundary crossing, + * simple *and* complex intersection. Instances of this class are specific to a + * volume, and a position. Calling an instance evaluates the sense of a + * volume's face with respect to the given position. This class is used to + * lazily calculate sense during evaluation of a logic expression, caching + * previously calculated senses, allowing potential short-circuiting + * of unnecessary sense evaluation. + * + * The OnFace constructor's parameter is used to store the first face that we + * are "on". + */ +class LazySenseCalculator +{ + public: + // Construct from persistent, current, and temporary data + inline CELER_FUNCTION LazySenseCalculator(LocalSurfaceVisitor const& visit, + VolumeView const& vol, + Real3 const& pos, + Span sense_cache, + OnFace& face); + + // Calculate senses for a single face of the given volume, possibly on a + // face + inline CELER_FUNCTION Sense operator()(FaceId face_id); + + //! Flip the sense of a face + CELER_FUNCTION void flip_sense(FaceId face_id) + { + sense_cache_[face_id.get()] = celeritas::flip_sense((*this)(face_id)); + } + + private: + //! Apply a function to a local surface + LocalSurfaceVisitor visit_; + + //! Volume to calculate senses for + VolumeView const& vol_; + + //! Local position + Real3 pos_; + + //! Temporary senses + Span sense_cache_; + + //! The first face encountered that we are "on" + OnFace& face_; +}; + +//---------------------------------------------------------------------------// +// INLINE DEFINITIONS +//---------------------------------------------------------------------------// +/*! + * Construct from persistent, current, and temporary data. + */ +CELER_FUNCTION +LazySenseCalculator::LazySenseCalculator(LocalSurfaceVisitor const& visit, + VolumeView const& vol, + Real3 const& pos, + Span sense_cache, + OnFace& face) + : visit_{visit} + , vol_(vol) + , pos_{pos} + , sense_cache_{sense_cache.first(vol_.num_faces())} + , face_(face) +{ + for (auto& sense : sense_cache_) + { + sense.clear(); + } +} + +//---------------------------------------------------------------------------// +/*! + * Calculate senses for the given volume. + * + * If the point is exactly on one of the volume's surfaces, the \c face + * reference passed during instance construction will be set. + */ +CELER_FUNCTION auto LazySenseCalculator::operator()(FaceId face_id) -> Sense +{ + auto& cached_sense = sense_cache_[face_id.get()]; + if (cached_sense.is_assigned()) + { + return cached_sense; + } + + if (face_id != face_.id()) + { + // Calculate sense + SignedSense ss = visit_(CalcSense{pos_}, vol_.get_surface(face_id)); + cached_sense = to_sense(ss); + if (ss == SignedSense::on && !face_) + { + // This is the first face that we're exactly on: save it + face_ = {face_id, cached_sense}; + } + } + else + { + // Sense is known a priori + cached_sense = face_.sense(); + } + + CELER_ENSURE(!face_ || face_.id() < vol_.num_faces()); + return cached_sense; +} + +//---------------------------------------------------------------------------// +} // namespace detail +} // namespace celeritas diff --git a/src/orange/univ/detail/LogicEvaluator.hh b/src/orange/univ/detail/LogicEvaluator.hh index 2c5d5845a0..b4e032460b 100644 --- a/src/orange/univ/detail/LogicEvaluator.hh +++ b/src/orange/univ/detail/LogicEvaluator.hh @@ -6,10 +6,13 @@ //---------------------------------------------------------------------------// #pragma once +#include + #include "corecel/Assert.hh" #include "corecel/cont/Span.hh" #include "corecel/data/LdgIterator.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" #include "LogicStack.hh" @@ -27,7 +30,7 @@ class LogicEvaluator //@{ //! \name Type aliases using SpanConstLogic = LdgSpan; - using SpanConstSense = Span; + using SpanConstSense = Span; //@} public: @@ -37,6 +40,10 @@ class LogicEvaluator // Evaluate a logical expression, substituting bools from the vector inline CELER_FUNCTION bool operator()(SpanConstSense values) const; + // Evaluate a logical expression, with on-the-fly sense evaluation + template, bool> = true> + inline CELER_FUNCTION bool operator()(F&& eval_sense) const; + private: //// DATA //// @@ -58,6 +65,18 @@ CELER_FUNCTION LogicEvaluator::LogicEvaluator(SpanConstLogic logic) * Evaluate a logical expression, substituting bools from the sense view. */ CELER_FUNCTION bool LogicEvaluator::operator()(SpanConstSense values) const +{ + auto calc_sense + = [&](FaceId face_id) -> Sense { return values[face_id.get()]; }; + return (*this)(calc_sense); +} + +//---------------------------------------------------------------------------// +/*! + * Evaluate a logical expression, with on-the-fly sense evaluation. + */ +template, bool>> +CELER_FUNCTION bool LogicEvaluator::operator()(F&& eval_sense) const { LogicStack stack; @@ -66,8 +85,7 @@ CELER_FUNCTION bool LogicEvaluator::operator()(SpanConstSense values) const if (!logic::is_operator_token(lgc)) { // Push a boolean from the senses onto the stack - CELER_EXPECT(lgc < values.size()); - stack.push(static_cast(values[lgc])); + stack.push(static_cast(eval_sense(FaceId{lgc}))); continue; } diff --git a/src/orange/univ/detail/SenseCalculator.hh b/src/orange/univ/detail/SenseCalculator.hh index 2f83586c25..ff40b0cc18 100644 --- a/src/orange/univ/detail/SenseCalculator.hh +++ b/src/orange/univ/detail/SenseCalculator.hh @@ -31,7 +31,7 @@ class SenseCalculator //! Return result struct result_type { - Span senses; //!< Calculated senses for the volume + Span senses; //!< Calculated senses for the volume OnFace face; //!< The first face encountered that we are "on" }; @@ -39,7 +39,7 @@ class SenseCalculator // Construct from persistent, current, and temporary data inline CELER_FUNCTION SenseCalculator(LocalSurfaceVisitor const& visit, Real3 const& pos, - Span storage); + Span storage); // Calculate senses for the given volume, possibly on a face inline CELER_FUNCTION result_type operator()(VolumeView const& vol, @@ -53,7 +53,7 @@ class SenseCalculator Real3 pos_; //! Temporary senses - Span sense_storage_; + Span sense_storage_; }; //---------------------------------------------------------------------------// @@ -65,7 +65,7 @@ class SenseCalculator CELER_FUNCTION SenseCalculator::SenseCalculator(LocalSurfaceVisitor const& visit, Real3 const& pos, - Span storage) + Span storage) : visit_{visit}, pos_(pos), sense_storage_(storage) { } diff --git a/src/orange/univ/detail/Types.hh b/src/orange/univ/detail/Types.hh index 111c552915..b540fb7754 100644 --- a/src/orange/univ/detail/Types.hh +++ b/src/orange/univ/detail/Types.hh @@ -9,6 +9,7 @@ #include "corecel/OpaqueId.hh" #include "corecel/cont/Span.hh" #include "orange/OrangeTypes.hh" +#include "orange/SenseUtils.hh" namespace celeritas { @@ -163,7 +164,7 @@ struct LocalState Real3 dir; LocalVolumeId volume; OnLocalSurface surface; - Span temp_sense; + Span temp_sense; TempNextFace temp_next; }; diff --git a/test/orange/OrangeGeoTestBase.cc b/test/orange/OrangeGeoTestBase.cc index 54d39c160e..e7707a4141 100644 --- a/test/orange/OrangeGeoTestBase.cc +++ b/test/orange/OrangeGeoTestBase.cc @@ -48,7 +48,7 @@ OrangeInput to_input(UnitInput u) /*! * Convert a vector of senses to a string. */ -std::string OrangeGeoTestBase::senses_to_string(Span senses) +std::string OrangeGeoTestBase::senses_to_string(Span senses) { std::ostringstream os; os << '{' << join(senses.begin(), senses.end(), ' ', [](Sense s) { diff --git a/test/orange/OrangeGeoTestBase.hh b/test/orange/OrangeGeoTestBase.hh index b3092c1bcc..895cd9f6e4 100644 --- a/test/orange/OrangeGeoTestBase.hh +++ b/test/orange/OrangeGeoTestBase.hh @@ -60,7 +60,7 @@ class OrangeGeoTestBase : public OrangeTestBase public: // Convert a vector of senses to a string - static std::string senses_to_string(Span senses); + static std::string senses_to_string(Span senses); // Convert a string to a sense vector static std::vector string_to_senses(std::string const& s); diff --git a/test/orange/surf/LocalSurfaceVisitor.test.hh b/test/orange/surf/LocalSurfaceVisitor.test.hh index 83a3dd148c..4c3baddb7c 100644 --- a/test/orange/surf/LocalSurfaceVisitor.test.hh +++ b/test/orange/surf/LocalSurfaceVisitor.test.hh @@ -28,7 +28,7 @@ struct OrangeMiniStateData StateItems pos; StateItems dir; - StateItems sense; + StateItems sense; StateItems distance; //! True if sizes are consistent and nonzero @@ -86,7 +86,7 @@ struct CalcSenseDistance { Real3 const& pos; Real3 const& dir; - Sense* sense; + SenseValue* sense; real_type* distance; template diff --git a/test/orange/univ/RectArrayTracker.test.cc b/test/orange/univ/RectArrayTracker.test.cc index 4172a3a532..fdb1d08406 100644 --- a/test/orange/univ/RectArrayTracker.test.cc +++ b/test/orange/univ/RectArrayTracker.test.cc @@ -78,7 +78,7 @@ LocalState RectArrayTrackerTest::make_state(Real3 pos, Real3 dir) auto const& hsref = this->host_state(); auto face_storage = hsref.temp_face[AllItems{}]; - state.temp_sense = hsref.temp_sense[AllItems{}]; + state.temp_sense = hsref.temp_sense[AllItems{}]; state.temp_next.face = face_storage.data(); state.temp_next.distance = hsref.temp_distance[AllItems{}].data(); diff --git a/test/orange/univ/SimpleUnitTracker.test.cc b/test/orange/univ/SimpleUnitTracker.test.cc index d0f71aa93e..0fdfb7ac62 100644 --- a/test/orange/univ/SimpleUnitTracker.test.cc +++ b/test/orange/univ/SimpleUnitTracker.test.cc @@ -140,7 +140,7 @@ LocalState SimpleUnitTrackerTest::make_state(Real3 pos, Real3 dir) auto const& hsref = this->host_state(); auto face_storage = hsref.temp_face[AllItems{}]; - state.temp_sense = hsref.temp_sense[AllItems{}]; + state.temp_sense = hsref.temp_sense[AllItems{}]; state.temp_next.face = face_storage.data(); state.temp_next.distance = hsref.temp_distance[AllItems{}].data(); diff --git a/test/orange/univ/SimpleUnitTracker.test.hh b/test/orange/univ/SimpleUnitTracker.test.hh index c369d1ae37..55923cd82c 100644 --- a/test/orange/univ/SimpleUnitTracker.test.hh +++ b/test/orange/univ/SimpleUnitTracker.test.hh @@ -58,7 +58,8 @@ inline CELER_FUNCTION LocalState build_local_state(ParamsRef params, lstate.surface = {}; size_type const max_faces = params.scalars.max_faces; - lstate.temp_sense = states.temp_sense[build_range(max_faces, tid)]; + lstate.temp_sense + = states.temp_sense[build_range(max_faces, tid)]; size_type const max_isect = params.scalars.max_intersections; lstate.temp_next.face diff --git a/test/orange/univ/TrackerVisitor.test.cc b/test/orange/univ/TrackerVisitor.test.cc index 3d56df9714..9d726baac4 100644 --- a/test/orange/univ/TrackerVisitor.test.cc +++ b/test/orange/univ/TrackerVisitor.test.cc @@ -8,6 +8,7 @@ #include "orange/univ/TrackerVisitor.hh" #include "orange/OrangeGeoTestBase.hh" +#include "orange/OrangeTypes.hh" #include "orange/univ/detail/Types.hh" #include "celeritas_test.hh" @@ -46,7 +47,7 @@ detail::LocalState TrackerVisitorTest::make_state(Real3 pos, Real3 dir) auto const& hsref = this->host_state(); auto face_storage = hsref.temp_face[AllItems{}]; - state.temp_sense = hsref.temp_sense[AllItems{}]; + state.temp_sense = hsref.temp_sense[AllItems{}]; state.temp_next.face = face_storage.data(); state.temp_next.distance = hsref.temp_distance[AllItems{}].data(); diff --git a/test/orange/univ/detail/LogicEvaluator.test.cc b/test/orange/univ/detail/LogicEvaluator.test.cc index 395660b3d3..b48b4cda09 100644 --- a/test/orange/univ/detail/LogicEvaluator.test.cc +++ b/test/orange/univ/detail/LogicEvaluator.test.cc @@ -18,7 +18,7 @@ namespace test { //---------------------------------------------------------------------------// -using VecSense = std::vector; +using VecSense = std::vector; constexpr auto lbegin = logic::lbegin; constexpr auto ltrue = logic::ltrue; diff --git a/test/orange/univ/detail/SenseCalculator.test.cc b/test/orange/univ/detail/SenseCalculator.test.cc index d2a4321dbd..a7bc40af1e 100644 --- a/test/orange/univ/detail/SenseCalculator.test.cc +++ b/test/orange/univ/detail/SenseCalculator.test.cc @@ -62,9 +62,9 @@ class SenseCalculatorTest : public ::celeritas::test::OrangeGeoTestBase } //! Access the shared CPU storage space for senses - Span sense_storage() + Span sense_storage() { - return this->host_state().temp_sense[AllItems{}]; + return this->host_state().temp_sense[AllItems{}]; } };