Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 10:11:39

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 celeritas/optical/surface/model/GridReflectivityExecutor.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/random/distribution/BernoulliDistribution.hh"
0010 #include "corecel/random/distribution/Selector.hh"
0011 #include "celeritas/Quantities.hh"
0012 #include "celeritas/grid/NonuniformGridCalculator.hh"
0013 #include "celeritas/optical/CoreTrackView.hh"
0014 
0015 #include "GridReflectivityData.hh"
0016 
0017 namespace celeritas
0018 {
0019 namespace optical
0020 {
0021 //---------------------------------------------------------------------------//
0022 /*!
0023  * Calculate the probability of a photon undergoing the specified reflectivity
0024  * action for a given grid.
0025  */
0026 class GridReflectivityCalculator
0027 {
0028   public:
0029     //!@{
0030     //! \name Type aliases
0031     using DataRef = NativeCRef<GridReflectivityData>;
0032     using Energy = units::MevEnergy;
0033     //!@}
0034 
0035   public:
0036     // Construct from data, surface, and energy
0037     explicit inline CELER_FUNCTION GridReflectivityCalculator(
0038         DataRef const&, SubModelId, Energy);
0039 
0040     // Calculate the probability for the specified reflectivity action
0041     inline CELER_FUNCTION real_type operator()(ReflectivityAction) const;
0042 
0043   private:
0044     DataRef const& data_;
0045     SubModelId surface_;
0046     Energy energy_;
0047 };
0048 
0049 //---------------------------------------------------------------------------//
0050 /*!
0051  * Sample user-defined reflectivity and transmittance grids to determine if the
0052  * track is transmitted, absorbed, or undergoes usual physics interactions.
0053  *
0054  * If the track is absorbed and a non-zero efficiency grid is present, then it
0055  * is also sampled. If it passes the efficiency threshold then it is instead
0056  * set to transmit to the next sub-surface.
0057  */
0058 struct GridReflectivityExecutor
0059 {
0060     //!@{
0061     //! \name Type aliases
0062     using Energy = units::MevEnergy;
0063     //!@}
0064 
0065     NativeCRef<GridReflectivityData> data;
0066 
0067     //! Apply grid reflectivity executor
0068     inline CELER_FUNCTION ReflectivityAction operator()(
0069         CoreTrackView const& track) const;
0070 };
0071 
0072 //---------------------------------------------------------------------------//
0073 // INLINE DEFINITIONS
0074 //---------------------------------------------------------------------------//
0075 /*!
0076  * Construct from data, surface, and energy.
0077  */
0078 CELER_FUNCTION GridReflectivityCalculator::GridReflectivityCalculator(
0079     DataRef const& data, SubModelId surface, Energy energy)
0080     : data_(data), surface_(surface), energy_(energy)
0081 {
0082 }
0083 
0084 //---------------------------------------------------------------------------//
0085 /*!
0086  * Calculate the probability for the specified reflectivity action.
0087  */
0088 CELER_FUNCTION real_type GridReflectivityCalculator::operator()(
0089     ReflectivityAction action) const
0090 {
0091     CELER_EXPECT(surface_ < data_.reflectivity[action].size());
0092     auto grid = data_.reflectivity[action][surface_];
0093 
0094     CELER_ASSERT(grid);
0095 
0096     NonuniformGridCalculator calc_grid{grid, data_.reals};
0097     real_type result = calc_grid(value_as<Energy>(energy_));
0098 
0099     // Values are probabilities and should be in [0,1]
0100     CELER_ENSURE(0 <= result && result <= 1);
0101 
0102     return result;
0103 }
0104 
0105 //---------------------------------------------------------------------------//
0106 /*!
0107  * Apply the executor to a track.
0108  */
0109 CELER_FUNCTION ReflectivityAction GridReflectivityExecutor::operator()(
0110     CoreTrackView const& track) const
0111 {
0112     using namespace celeritas::literals;
0113 
0114     auto s_phys = track.surface_physics();
0115     auto sub_model_id
0116         = s_phys.interface(SurfacePhysicsOrder::reflectivity).internal_surface_id();
0117 
0118     auto rng = track.rng();
0119 
0120     // Sample action based on reflectivity and transmittance grids
0121     auto action = celeritas::make_unnormalized_selector(
0122         GridReflectivityCalculator{
0123             data, sub_model_id, track.particle().energy()},
0124         ReflectivityAction::size_,
0125         1.0_r)(rng);
0126 
0127     if (action == ReflectivityAction::absorb)
0128     {
0129         if (auto e_grid_id = data.efficiency_ids[sub_model_id].get())
0130         {
0131             // If absorbed and has efficiency grid, sample efficiency
0132             auto const& e_grid = data.efficiency[e_grid_id];
0133 
0134             CELER_ASSERT(e_grid);
0135 
0136             real_type efficiency = NonuniformGridCalculator{e_grid, data.reals}(
0137                 value_as<Energy>(track.particle().energy()));
0138 
0139             if (BernoulliDistribution{efficiency}(rng))
0140             {
0141                 // Pass efficiency selection; transmit instead of absorb
0142                 action = ReflectivityAction::transmit;
0143             }
0144         }
0145     }
0146 
0147     return action;
0148 }
0149 
0150 //---------------------------------------------------------------------------//
0151 }  // namespace optical
0152 }  // namespace celeritas