File indexing completed on 2025-09-17 08:59:58
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/math/Algorithms.hh"
0010 #include "corecel/math/ArrayUtils.hh"
0011 #include "corecel/math/NumericLimits.hh"
0012
0013 #include "../ImageData.hh"
0014
0015 namespace celeritas
0016 {
0017 namespace detail
0018 {
0019
0020
0021
0022
0023
0024
0025
0026 template<class GTV>
0027 class SafetyCalculator
0028 {
0029 public:
0030
0031
0032 using ParamsRef = NativeCRef<ImageParamsData>;
0033 using StateRef = NativeRef<ImageStateData>;
0034
0035
0036 public:
0037
0038 inline CELER_FUNCTION
0039 SafetyCalculator(GTV&&, ParamsRef const&, real_type max_distance);
0040
0041
0042 inline CELER_FUNCTION real_type operator()(size_type x, size_type y);
0043
0044 private:
0045 GTV geo_;
0046 ImageParamsScalars const& scalars_;
0047 Real3 dir_;
0048 real_type max_distance_;
0049 };
0050
0051
0052
0053
0054
0055 template<class GTV>
0056 CELER_FUNCTION SafetyCalculator(GTV&&,
0057 NativeCRef<ImageParamsData> const&,
0058 real_type) -> SafetyCalculator<GTV>;
0059
0060
0061
0062
0063
0064
0065
0066 template<class GTV>
0067 CELER_FUNCTION SafetyCalculator<GTV>::SafetyCalculator(GTV&& geo,
0068 ParamsRef const& params,
0069 real_type max_distance)
0070 : geo_{celeritas::forward<GTV>(geo)}
0071 , scalars_{params.scalars}
0072 , dir_{make_unit_vector(cross_product(scalars_.down, scalars_.right))}
0073 , max_distance_{max_distance}
0074 {
0075 CELER_ENSURE(max_distance_ > 0);
0076 }
0077
0078
0079
0080
0081
0082 template<class GTV>
0083 CELER_FUNCTION real_type SafetyCalculator<GTV>::operator()(size_type x,
0084 size_type y)
0085 {
0086 geo_ = [&] {
0087 auto calc_offset = [pw = scalars_.pixel_width](size_type i) {
0088 return pw * (static_cast<real_type>(i) + real_type(0.5));
0089 };
0090
0091 GeoTrackInitializer init;
0092 init.pos = scalars_.origin;
0093 axpy(calc_offset(y), scalars_.down, &init.pos);
0094 axpy(calc_offset(x), scalars_.right, &init.pos);
0095 init.dir = dir_;
0096 return init;
0097 }();
0098
0099 if (geo_.is_outside())
0100 {
0101 return numeric_limits<real_type>::quiet_NaN();
0102 }
0103
0104 return geo_.find_safety(max_distance_);
0105 }
0106
0107
0108 }
0109 }