File indexing completed on 2025-01-18 10:05:57
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include "corecel/Types.hh"
0011 #include "corecel/cont/Array.hh"
0012 #include "corecel/cont/Span.hh"
0013 #include "corecel/math/Algorithms.hh"
0014 #include "corecel/math/ArrayUtils.hh"
0015
0016 #include "detail/QuadraticSolver.hh"
0017
0018 namespace celeritas
0019 {
0020
0021
0022
0023
0024 class SphereCentered
0025 {
0026 public:
0027
0028
0029 using Intersections = Array<real_type, 2>;
0030 using StorageSpan = Span<real_type const, 1>;
0031
0032
0033
0034
0035
0036 static CELER_CONSTEXPR_FUNCTION SurfaceType surface_type()
0037 {
0038 return SurfaceType::sc;
0039 }
0040
0041
0042 static CELER_CONSTEXPR_FUNCTION bool simple_safety() { return true; }
0043
0044 public:
0045
0046
0047
0048 static inline SphereCentered from_radius_sq(real_type rsq);
0049
0050
0051 explicit inline CELER_FUNCTION SphereCentered(real_type radius);
0052
0053
0054 template<class R>
0055 explicit inline CELER_FUNCTION SphereCentered(Span<R, StorageSpan::extent>);
0056
0057
0058
0059
0060 CELER_FUNCTION real_type radius_sq() const { return radius_sq_; }
0061
0062
0063 CELER_FUNCTION StorageSpan data() const { return {&radius_sq_, 1}; }
0064
0065
0066
0067
0068 inline CELER_FUNCTION SignedSense calc_sense(Real3 const& pos) const;
0069
0070
0071 inline CELER_FUNCTION Intersections calc_intersections(
0072 Real3 const& pos, Real3 const& dir, SurfaceState on_surface) const;
0073
0074
0075 inline CELER_FUNCTION Real3 calc_normal(Real3 const& pos) const;
0076
0077 private:
0078
0079 real_type radius_sq_;
0080
0081
0082 SphereCentered() = default;
0083 };
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 SphereCentered SphereCentered::from_radius_sq(real_type rsq)
0094 {
0095 CELER_EXPECT(rsq > 0);
0096 SphereCentered result;
0097 result.radius_sq_ = rsq;
0098 return result;
0099 }
0100
0101
0102
0103
0104
0105 CELER_FUNCTION SphereCentered::SphereCentered(real_type radius)
0106 : radius_sq_(ipow<2>(radius))
0107 {
0108 CELER_EXPECT(radius > 0);
0109 }
0110
0111
0112
0113
0114
0115 template<class R>
0116 CELER_FUNCTION SphereCentered::SphereCentered(Span<R, StorageSpan::extent> data)
0117 : radius_sq_{data[0]}
0118 {
0119 }
0120
0121
0122
0123
0124
0125 CELER_FUNCTION SignedSense SphereCentered::calc_sense(Real3 const& pos) const
0126 {
0127 return real_to_sense(dot_product(pos, pos) - radius_sq_);
0128 }
0129
0130
0131
0132
0133
0134 CELER_FUNCTION auto
0135 SphereCentered::calc_intersections(Real3 const& pos,
0136 Real3 const& dir,
0137 SurfaceState on_surface) const -> Intersections
0138 {
0139 detail::QuadraticSolver solve_quadric(real_type(1), dot_product(pos, dir));
0140 if (on_surface == SurfaceState::off)
0141 {
0142 return solve_quadric(dot_product(pos, pos) - radius_sq_);
0143 }
0144 else
0145 {
0146 return solve_quadric();
0147 }
0148 }
0149
0150
0151
0152
0153
0154 CELER_FUNCTION Real3 SphereCentered::calc_normal(Real3 const& pos) const
0155 {
0156 return make_unit_vector(pos);
0157 }
0158
0159
0160 }