Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:17:13

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2021-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file orange/univ/detail/SenseCalculator.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include "corecel/Assert.hh"
0011 #include "corecel/cont/Range.hh"
0012 #include "corecel/cont/Span.hh"
0013 #include "orange/surf/LocalSurfaceVisitor.hh"
0014 
0015 #include "SurfaceFunctors.hh"
0016 #include "../VolumeView.hh"
0017 
0018 namespace celeritas
0019 {
0020 namespace detail
0021 {
0022 //---------------------------------------------------------------------------//
0023 /*!
0024  * Calculate senses with a fixed particle position.
0025  *
0026  * This is an implementation detail used in initialization *and* complex
0027  * intersection.
0028  */
0029 class SenseCalculator
0030 {
0031   public:
0032     //! Return result
0033     struct result_type
0034     {
0035         Span<Sense> senses;  //!< Calculated senses for the volume
0036         OnFace face;  //!< The first face encountered that we are "on"
0037     };
0038 
0039   public:
0040     // Construct from persistent, current, and temporary data
0041     inline CELER_FUNCTION SenseCalculator(LocalSurfaceVisitor const& visit,
0042                                           Real3 const& pos,
0043                                           Span<Sense> storage);
0044 
0045     // Calculate senses for the given volume, possibly on a face
0046     inline CELER_FUNCTION result_type operator()(VolumeView const& vol,
0047                                                  OnFace face = {});
0048 
0049   private:
0050     //! Apply a function to a local surface
0051     LocalSurfaceVisitor visit_;
0052 
0053     //! Local position
0054     Real3 pos_;
0055 
0056     //! Temporary senses
0057     Span<Sense> sense_storage_;
0058 };
0059 
0060 //---------------------------------------------------------------------------//
0061 // INLINE DEFINITIONS
0062 //---------------------------------------------------------------------------//
0063 /*!
0064  * Construct from persistent, current, and temporary data.
0065  */
0066 CELER_FUNCTION
0067 SenseCalculator::SenseCalculator(LocalSurfaceVisitor const& visit,
0068                                  Real3 const& pos,
0069                                  Span<Sense> storage)
0070     : visit_{visit}, pos_(pos), sense_storage_(storage)
0071 {
0072 }
0073 
0074 //---------------------------------------------------------------------------//
0075 /*!
0076  * Calculate senses for the given volume.
0077  *
0078  * If the point is exactly on one of the volume's surfaces, the \c face value
0079  * of the return will be set.
0080  */
0081 CELER_FUNCTION auto
0082 SenseCalculator::operator()(VolumeView const& vol, OnFace face) -> result_type
0083 {
0084     CELER_EXPECT(vol.num_faces() <= sense_storage_.size());
0085     CELER_EXPECT(!face || face.id() < vol.num_faces());
0086 
0087     // Resulting senses are a subset of the storage; and the face is preserved
0088     result_type result;
0089     result.senses = sense_storage_.first(vol.num_faces());
0090     result.face = face;
0091 
0092     // Fill the temp logic vector with values for all surfaces in the volume
0093     for (FaceId cur_face : range(FaceId{vol.num_faces()}))
0094     {
0095         Sense cur_sense;
0096         if (cur_face != face.id())
0097         {
0098             // Calculate sense
0099             SignedSense ss = visit_(CalcSense{pos_}, vol.get_surface(cur_face));
0100             cur_sense = to_sense(ss);
0101             if (!result.face && ss == SignedSense::on)
0102             {
0103                 // This is the first face that we're exactly on: save it
0104                 result.face = {cur_face, cur_sense};
0105             }
0106         }
0107         else
0108         {
0109             // Sense is known a priori
0110             cur_sense = face.sense();
0111         }
0112         // Save sense to result scratch space
0113         result.senses[cur_face.unchecked_get()] = cur_sense;
0114     }
0115 
0116     CELER_ENSURE(!result.face || result.face.id() < result.senses.size());
0117     return result;
0118 }
0119 
0120 //---------------------------------------------------------------------------//
0121 }  // namespace detail
0122 }  // namespace celeritas