File indexing completed on 2026-09-29 09:33:47
0001
0002
0003
0004
0005
0006 #ifndef VECGEOM_VOLUMES_KERNEL_TESSELLATEDIMPLEMENTATION_H_
0007 #define VECGEOM_VOLUMES_KERNEL_TESSELLATEDIMPLEMENTATION_H_
0008
0009 #include "VecGeom/base/Config.h"
0010 #include "VecGeom/base/Vector3D.h"
0011 #include "VecGeom/volumes/TessellatedStruct.h"
0012 #include "VecGeom/volumes/kernel/GenericKernels.h"
0013 #include <VecCore/VecCore>
0014
0015 #include <cstdio>
0016
0017 namespace vecgeom {
0018
0019 VECGEOM_DEVICE_FORWARD_DECLARE(struct TessellatedImplementation;);
0020 VECGEOM_DEVICE_DECLARE_CONV(struct, TessellatedImplementation);
0021
0022 inline namespace VECGEOM_IMPL_NAMESPACE {
0023
0024 class PlacedTessellated;
0025 template <size_t NVERT, typename T>
0026 class TessellatedStruct;
0027 class UnplacedTessellated;
0028
0029 struct TessellatedImplementation {
0030
0031 using PlacedShape_t = PlacedTessellated;
0032 using UnplacedStruct_t = TessellatedStruct<3, Precision>;
0033 using UnplacedVolume_t = UnplacedTessellated;
0034
0035 template <typename Real_v, typename Bool_v>
0036 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Contains(UnplacedStruct_t const &tessellated,
0037 Vector3D<Real_v> const &point, Bool_v &inside)
0038 {
0039 inside = Bool_v(false);
0040 int isurfOut, isurfIn;
0041 Real_v distOut, distIn;
0042 DistanceToSolid<Real_v, false>(tessellated, point, tessellated.fTestDir, InfinityLength<Real_v>(), distOut,
0043 isurfOut, distIn, isurfIn);
0044 if (isurfOut >= 0) inside = Bool_v(true);
0045
0046
0047
0048
0049
0050 }
0051
0052 template <typename Real_v, typename Inside_v>
0053 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Inside(UnplacedStruct_t const &tessellated,
0054 Vector3D<Real_v> const &point, Inside_v &inside)
0055 {
0056 inside = Inside_v(kOutside);
0057 int isurfOut, isurfIn;
0058 Real_v distOut, distIn;
0059 DistanceToSolid<Real_v, false>(tessellated, point, tessellated.fTestDir, InfinityLength<Real_v>(), distOut,
0060 isurfOut, distIn, isurfIn);
0061
0062 if (isurfOut < 0) return;
0063 if (distOut < 0 || distOut * tessellated.fTestDir.Dot(tessellated.fFacets[isurfOut]->fNormal) < kTolerance) {
0064 inside = Inside_v(kSurface);
0065 return;
0066 }
0067
0068
0069
0070 if (isurfIn < 0 || distOut < distIn) {
0071 inside = Inside_v(kInside);
0072 return;
0073 }
0074 if (distIn < 0 || distIn * tessellated.fTestDir.Dot(tessellated.fFacets[isurfIn]->fNormal) > -kTolerance)
0075 inside = Inside_v(kSurface);
0076 }
0077
0078 template <typename Real_v>
0079 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToIn(UnplacedStruct_t const &tessellated,
0080 Vector3D<Real_v> const &point,
0081 Vector3D<Real_v> const &direction,
0082 Real_v const &stepMax, Real_v &distance)
0083 {
0084 int isurf, isurfOut;
0085 Real_v distOut;
0086 DistanceToSolid<Real_v, true>(tessellated, point, direction, stepMax, distance, isurf, distOut, isurfOut);
0087 }
0088
0089 template <typename Real_v>
0090 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToOut(UnplacedStruct_t const &tessellated,
0091 Vector3D<Real_v> const &point,
0092 Vector3D<Real_v> const &direction,
0093 Real_v const &stepMax, Real_v &distance)
0094 {
0095 int isurf, isurfIn;
0096 Real_v distIn;
0097 DistanceToSolid<Real_v, false>(tessellated, point, direction, stepMax, distance, isurf, distIn, isurfIn);
0098 }
0099
0100 template <typename Real_v>
0101 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToIn(UnplacedStruct_t const &tessellated,
0102 Vector3D<Real_v> const &point, Real_v &safety)
0103 {
0104 using Bool_v = vecCore::Mask_v<Real_v>;
0105 Bool_v inside;
0106 TessellatedImplementation::Contains<Real_v, Bool_v>(tessellated, point, inside);
0107 if (inside) {
0108 safety = -1.;
0109 return;
0110 }
0111 int isurf;
0112 Real_v safetysq = SafetySq<Real_v, true>(tessellated, point, isurf);
0113 safety = vecCore::math::Sqrt(safetysq);
0114 }
0115
0116 template <typename Real_v>
0117 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToOut(UnplacedStruct_t const &tessellated,
0118 Vector3D<Real_v> const &point, Real_v &safety)
0119 {
0120 using Bool_v = vecCore::Mask_v<Real_v>;
0121 Bool_v inside;
0122 TessellatedImplementation::Contains<Real_v, Bool_v>(tessellated, point, inside);
0123 if (!inside) {
0124 safety = -1.;
0125 return;
0126 }
0127 int isurf;
0128 Real_v safetysq = SafetySq<Real_v, false>(tessellated, point, isurf);
0129 safety = vecCore::math::Sqrt(safetysq);
0130 }
0131
0132 template <typename Real_v>
0133 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Vector3D<Real_v> NormalKernel(
0134 UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point, typename vecCore::Mask_v<Real_v> &valid)
0135 {
0136
0137 valid = true;
0138 int isurf;
0139
0140 SafetySq<Real_v, false>(tessellated, point, isurf);
0141 return tessellated.fFacets[isurf]->fNormal;
0142 }
0143
0144 template <typename Real_v, bool ToIn>
0145 VECCORE_ATT_HOST_DEVICE static void DistanceToSolid(UnplacedStruct_t const &tessellated,
0146 Vector3D<Real_v> const &point, Vector3D<Real_v> const &direction,
0147 Real_v const &stepMax, Real_v &distance, int &isurf,
0148 Real_v &distother, int &isurfother)
0149 {
0150
0151
0152 #ifndef VECGEOM_ENABLE_CUDA
0153 using Float_v = vecgeom::VectorBackend::Real_v;
0154 #else
0155 using Float_v = vecgeom::ScalarBackend::Real_v;
0156 #endif
0157 isurf = -1;
0158 isurfother = -1;
0159 if (ToIn) {
0160
0161 const Vector3D<Real_v> invdir(Real_v(1.0) / NonZero(direction.x()), Real_v(1.0) / NonZero(direction.y()),
0162 Real_v(1.0) / NonZero(direction.z()));
0163 Vector3D<int> sign;
0164 sign[0] = invdir.x() < 0;
0165 sign[1] = invdir.y() < 0;
0166 sign[2] = invdir.z() < 0;
0167 distance = BoxImplementation::IntersectCachedKernel2<Real_v, Real_v>(
0168 &tessellated.fMinExtent, point, invdir, sign.x(), sign.y(), sign.z(), -kTolerance, InfinityLength<Real_v>());
0169 if (distance >= stepMax) return;
0170 }
0171
0172
0173
0174 Vector3D<Float_v> pointv(point);
0175 Vector3D<Float_v> dirv(direction);
0176 distance = InfinityLength<Real_v>();
0177 distother = InfinityLength<Real_v>();
0178 Real_v distanceToIn = InfinityLength<Real_v>();
0179 Real_v distanceToOut = InfinityLength<Real_v>();
0180 int isurfToIn = -1;
0181 int isurfToOut = -1;
0182 auto userhook = [&](HybridManager2::BoxIdDistancePair_t hitbox) {
0183
0184
0185 if (hitbox.second > vecCore::math::Min(stepMax, distance)) return true;
0186
0187 Real_v clusterToIn, clusterToOut;
0188 int icrtToIn, icrtToOut;
0189 tessellated.fClusters[hitbox.first]->DistanceToCluster(pointv, dirv, clusterToIn, clusterToOut, icrtToIn,
0190 icrtToOut);
0191
0192
0193 if (icrtToIn >= 0 && clusterToIn < distanceToIn) {
0194 distanceToIn = clusterToIn;
0195 isurfToIn = icrtToIn;
0196 if (ToIn) {
0197 isurf = isurfToIn;
0198 distance = distanceToIn;
0199 } else {
0200 isurfother = isurfToIn;
0201 distother = distanceToIn;
0202 }
0203 }
0204
0205 if (icrtToOut >= 0 && clusterToOut < distanceToOut) {
0206 distanceToOut = clusterToOut;
0207 isurfToOut = icrtToOut;
0208 if (!ToIn) {
0209 isurf = isurfToOut;
0210 distance = distanceToOut;
0211 } else {
0212 isurfother = isurfToOut;
0213 distother = distanceToOut;
0214 }
0215 }
0216 return false;
0217 };
0218
0219 #ifdef USEEMBREE
0220 EmbreeNavigator<> *boxNav = (EmbreeNavigator<> *)EmbreeNavigator<>::Instance();
0221
0222 boxNav->BVHSortedIntersectionsLooper(*tessellated.fNavHelper2, point, direction, 1E20, userhook);
0223 #else
0224 HybridNavigator<> *boxNav = (HybridNavigator<> *)HybridNavigator<>::Instance();
0225 boxNav->BVHSortedIntersectionsLooper(*tessellated.fNavHelper2, point, direction, stepMax, userhook);
0226 #endif
0227
0228
0229 if (ToIn) {
0230 if (isurfToIn < 0) {
0231 if (isurfToOut >= 0 && distanceToOut * direction.Dot(tessellated.fFacets[isurfToOut]->fNormal) > kTolerance)
0232 distance = -1.;
0233
0234 } else {
0235 if (isurfToOut >= 0 && distanceToOut > kTolerance && distanceToOut < distanceToIn)
0236 distance = -1.;
0237
0238 }
0239 } else {
0240 if (isurfToOut < 0)
0241 distance = -1.;
0242 else {
0243 if (isurfToIn >= 0 && distanceToIn < distanceToOut &&
0244 distanceToIn * direction.Dot(tessellated.fFacets[isurfToIn]->fNormal) < -kTolerance) {
0245 distance = -1.;
0246 isurf = -1;
0247 }
0248 }
0249 }
0250 }
0251
0252 template <typename Real_v, bool ToIn>
0253 VECCORE_ATT_HOST_DEVICE static Real_v SafetySq(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point,
0254 int &isurf)
0255 {
0256 #ifndef VECGEOM_ENABLE_CUDA
0257 using Float_v = vecgeom::VectorBackend::Real_v;
0258 #else
0259 using Float_v = vecgeom::ScalarBackend::Real_v;
0260 #endif
0261 Real_v safetysq = InfinityLength<Real_v>();
0262 isurf = -1;
0263 Vector3D<Float_v> pointv(point);
0264
0265 auto userhook = [&](HybridManager2::BoxIdDistancePair_t hitbox) {
0266
0267
0268 if (hitbox.second > safetysq) return true;
0269
0270 int isurfcrt;
0271 Real_v safetycrt = tessellated.fClusters[hitbox.first]->template SafetySq<ToIn>(pointv, isurfcrt);
0272 if (safetycrt < safetysq) {
0273 safetysq = safetycrt;
0274 isurf = isurfcrt;
0275 }
0276 return false;
0277 };
0278
0279 HybridSafetyEstimator *safEstimator = (HybridSafetyEstimator *)HybridSafetyEstimator::Instance();
0280
0281 safEstimator->BVHSortedSafetyLooper(*tessellated.fNavHelper, point, userhook, safetysq);
0282 return safetysq;
0283 }
0284
0285 };
0286 }
0287 }
0288
0289 #endif