File indexing completed on 2025-01-30 10:17:11
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/ArrayUtils.hh"
0014 #include "orange/OrangeTypes.hh"
0015
0016 #include "detail/QuadraticSolver.hh"
0017
0018 namespace celeritas
0019 {
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 template<Axis T>
0033 class ConeAligned
0034 {
0035 public:
0036
0037
0038 using Intersections = Array<real_type, 2>;
0039 using StorageSpan = Span<real_type const, 4>;
0040
0041
0042 private:
0043 static constexpr Axis U{T == Axis::x ? Axis::y : Axis::x};
0044 static constexpr Axis V{T == Axis::z ? Axis::y : Axis::z};
0045
0046 public:
0047
0048
0049
0050 static CELER_CONSTEXPR_FUNCTION SurfaceType surface_type();
0051
0052
0053 static CELER_CONSTEXPR_FUNCTION bool simple_safety() { return false; }
0054
0055
0056
0057 static CELER_CONSTEXPR_FUNCTION Axis t_axis() { return T; }
0058 static CELER_CONSTEXPR_FUNCTION Axis u_axis() { return U; }
0059 static CELER_CONSTEXPR_FUNCTION Axis v_axis() { return V; }
0060
0061
0062 public:
0063
0064
0065
0066 static ConeAligned from_tangent_sq(Real3 const& origin, real_type tsq);
0067
0068
0069 inline CELER_FUNCTION ConeAligned(Real3 const& origin, real_type tangent);
0070
0071
0072 template<class R>
0073 explicit inline CELER_FUNCTION ConeAligned(Span<R, StorageSpan::extent>);
0074
0075
0076
0077
0078 CELER_FUNCTION Real3 const& origin() const { return origin_; }
0079
0080
0081 CELER_FUNCTION real_type tangent_sq() const { return tsq_; }
0082
0083
0084 CELER_FUNCTION StorageSpan data() const { return {&origin_[0], 4}; }
0085
0086
0087
0088
0089 inline CELER_FUNCTION SignedSense calc_sense(Real3 const& pos) const;
0090
0091
0092 inline CELER_FUNCTION Intersections calc_intersections(
0093 Real3 const& pos, Real3 const& dir, SurfaceState on_surface) const;
0094
0095
0096 inline CELER_FUNCTION Real3 calc_normal(Real3 const& pos) const;
0097
0098 private:
0099
0100 Real3 origin_;
0101
0102
0103 real_type tsq_;
0104
0105
0106 ConeAligned() = default;
0107 };
0108
0109
0110
0111
0112
0113 using ConeX = ConeAligned<Axis::x>;
0114 using ConeY = ConeAligned<Axis::y>;
0115 using ConeZ = ConeAligned<Axis::z>;
0116
0117
0118
0119
0120
0121
0122
0123 template<Axis T>
0124 CELER_CONSTEXPR_FUNCTION SurfaceType ConeAligned<T>::surface_type()
0125 {
0126 return T == Axis::x ? SurfaceType::kx
0127 : T == Axis::y ? SurfaceType::ky
0128 : T == Axis::z ? SurfaceType::kz
0129 : SurfaceType::size_;
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 template<Axis T>
0150 CELER_FUNCTION
0151 ConeAligned<T>::ConeAligned(Real3 const& origin, real_type tangent)
0152 : origin_{origin}, tsq_{ipow<2>(tangent)}
0153 {
0154 CELER_EXPECT(tangent > 0);
0155 }
0156
0157
0158
0159
0160
0161 template<Axis T>
0162 template<class R>
0163 CELER_FUNCTION ConeAligned<T>::ConeAligned(Span<R, StorageSpan::extent> data)
0164 : origin_{data[0], data[1], data[2]}, tsq_{data[3]}
0165 {
0166 }
0167
0168
0169
0170
0171
0172 template<Axis T>
0173 CELER_FUNCTION SignedSense ConeAligned<T>::calc_sense(Real3 const& pos) const
0174 {
0175 real_type const x = pos[to_int(T)] - origin_[to_int(T)];
0176 real_type const y = pos[to_int(U)] - origin_[to_int(U)];
0177 real_type const z = pos[to_int(V)] - origin_[to_int(V)];
0178
0179 return real_to_sense((-tsq_ * ipow<2>(x)) + ipow<2>(y) + ipow<2>(z));
0180 }
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 template<Axis T>
0191 CELER_FUNCTION auto
0192 ConeAligned<T>::calc_intersections(Real3 const& pos,
0193 Real3 const& dir,
0194 SurfaceState on_surface) const -> Intersections
0195 {
0196
0197 real_type const x = pos[to_int(T)] - origin_[to_int(T)];
0198 real_type const y = pos[to_int(U)] - origin_[to_int(U)];
0199 real_type const z = pos[to_int(V)] - origin_[to_int(V)];
0200
0201 real_type const u = dir[to_int(T)];
0202 real_type const v = dir[to_int(U)];
0203 real_type const w = dir[to_int(V)];
0204
0205
0206 real_type a = (-tsq_ * ipow<2>(u)) + ipow<2>(v) + ipow<2>(w);
0207 real_type half_b = (-tsq_ * x * u) + (y * v) + (z * w);
0208 real_type c = (-tsq_ * ipow<2>(x)) + ipow<2>(y) + ipow<2>(z);
0209
0210 return detail::QuadraticSolver::solve_general(a, half_b, c, on_surface);
0211 }
0212
0213
0214
0215
0216
0217 template<Axis T>
0218 CELER_FUNCTION Real3 ConeAligned<T>::calc_normal(Real3 const& pos) const
0219 {
0220 Real3 norm;
0221 for (auto i = to_int(Axis::x); i < to_int(Axis::size_); ++i)
0222 {
0223 norm[i] = pos[i] - origin_[i];
0224 }
0225 norm[to_int(T)] *= -tsq_;
0226
0227 return make_unit_vector(norm);
0228 }
0229
0230
0231 }