Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 09:06:15

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file orange/univ/detail/LazySenseCalculator.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Assert.hh"
0010 #include "corecel/Macros.hh"
0011 #include "orange/OrangeTypes.hh"
0012 #include "orange/SenseUtils.hh"
0013 #include "orange/surf/LocalSurfaceVisitor.hh"
0014 
0015 #include "SurfaceFunctors.hh"
0016 #include "Types.hh"
0017 #include "../VolumeView.hh"
0018 
0019 namespace celeritas
0020 {
0021 namespace detail
0022 {
0023 //---------------------------------------------------------------------------//
0024 /*!
0025  * Calculate senses with a fixed particle position.
0026  *
0027  * This is an implementation detail used in initialization, boundary crossing,
0028  * simple *and* complex intersection. Instances of this class are specific to a
0029  * volume, and a position. Calling an instance evaluates the sense of a
0030  * volume's face with respect to the given position. This class is used to
0031  * lazily calculate sense during evaluation of a logic expression, contrary to
0032  * CachedLazySenseCalculator, this class does not cache the calculated sense:
0033  * potentially recomputing the same sense value multiple time. The advantage
0034  * is that we do not need to access global memory to store the cached sense.
0035  *
0036  * The OnFace constructor's parameter is used to store the first face that we
0037  * are "on".
0038  */
0039 class LazySenseCalculator
0040 {
0041   public:
0042     // Construct from persistent, current, and temporary data
0043     inline CELER_FUNCTION LazySenseCalculator(LocalSurfaceVisitor const& visit,
0044                                               VolumeView const& vol,
0045                                               Real3 const& pos,
0046                                               OnFace& face);
0047 
0048     // Calculate senses for a single face of the given volume, possibly on a
0049     // face
0050     inline CELER_FUNCTION Sense operator()(FaceId face_id);
0051 
0052   private:
0053     //! Apply a function to a local surface
0054     LocalSurfaceVisitor visit_;
0055 
0056     //! Volume to calculate senses for
0057     VolumeView const& vol_;
0058 
0059     //! Local position
0060     Real3 const& pos_;
0061 
0062     //! The first face encountered that we are "on"
0063     OnFace& face_;
0064 };
0065 
0066 //---------------------------------------------------------------------------//
0067 // INLINE DEFINITIONS
0068 //---------------------------------------------------------------------------//
0069 /*!
0070  * Construct from persistent, current, and temporary data.
0071  */
0072 CELER_FUNCTION
0073 LazySenseCalculator::LazySenseCalculator(LocalSurfaceVisitor const& visit,
0074                                          VolumeView const& vol,
0075                                          Real3 const& pos,
0076                                          OnFace& face)
0077     : visit_{visit}, vol_{vol}, pos_{pos}, face_{face}
0078 {
0079 }
0080 
0081 //---------------------------------------------------------------------------//
0082 /*!
0083  * Calculate senses for the given volume.
0084  *
0085  * If the point is exactly on one of the volume's surfaces, the \c face
0086  * reference passed during instance construction will be set.
0087  */
0088 CELER_FUNCTION auto LazySenseCalculator::operator()(FaceId face_id) -> Sense
0089 {
0090     CELER_EXPECT(face_id < vol_.num_faces());
0091     CELER_EXPECT(!face_ || face_.id() < vol_.num_faces());
0092 
0093     Sense sense;
0094     if (face_id != face_.id())
0095     {
0096         // Calculate sense
0097         SignedSense ss = visit_(CalcSense{pos_}, vol_.get_surface(face_id));
0098         sense = to_sense(ss);
0099         if (ss == SignedSense::on && !face_)
0100         {
0101             // This is the first face that we're exactly on: save it
0102             face_ = {face_id, sense};
0103         }
0104     }
0105     else
0106     {
0107         // Sense is known a priori
0108         sense = face_.sense();
0109     }
0110 
0111     CELER_ENSURE(!face_ || face_.id() < vol_.num_faces());
0112     return sense;
0113 }
0114 
0115 //---------------------------------------------------------------------------//
0116 }  // namespace detail
0117 }  // namespace celeritas