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