File indexing completed on 2025-01-18 10:14:04
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 VECCORE_ATT_HOST_DEVICE
0036 static void PrintType()
0037 {
0038
0039 }
0040
0041 template <typename Stream>
0042 static void PrintType(Stream &st, int transCodeT = translation::kGeneric, int rotCodeT = rotation::kGeneric)
0043 {
0044 st << "SpecializedTessellated<" << transCodeT << "," << rotCodeT << ">";
0045 }
0046
0047 template <typename Stream>
0048 static void PrintImplementationType(Stream &st)
0049 {
0050 (void)st;
0051 }
0052
0053 template <typename Stream>
0054 static void PrintUnplacedType(Stream &st)
0055 {
0056 (void)st;
0057 }
0058
0059 template <typename Real_v, typename Bool_v>
0060 VECGEOM_FORCE_INLINE
0061 VECCORE_ATT_HOST_DEVICE
0062 static void Contains(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point, Bool_v &inside)
0063 {
0064 inside = Bool_v(false);
0065 int isurfOut, isurfIn;
0066 Real_v distOut, distIn;
0067 DistanceToSolid<Real_v, false>(tessellated, point, tessellated.fTestDir, InfinityLength<Real_v>(), distOut,
0068 isurfOut, distIn, isurfIn);
0069 if (isurfOut >= 0) inside = Bool_v(true);
0070
0071
0072
0073
0074
0075 }
0076
0077 template <typename Real_v, typename Inside_v>
0078 VECGEOM_FORCE_INLINE
0079 VECCORE_ATT_HOST_DEVICE
0080 static void Inside(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point, Inside_v &inside)
0081 {
0082 inside = Inside_v(kOutside);
0083 int isurfOut, isurfIn;
0084 Real_v distOut, distIn;
0085 DistanceToSolid<Real_v, false>(tessellated, point, tessellated.fTestDir, InfinityLength<Real_v>(), distOut,
0086 isurfOut, distIn, isurfIn);
0087
0088 if (isurfOut < 0) return;
0089 if (distOut < 0 || distOut * tessellated.fTestDir.Dot(tessellated.fFacets[isurfOut]->fNormal) < kTolerance) {
0090 inside = Inside_v(kSurface);
0091 return;
0092 }
0093
0094
0095
0096 if (isurfIn < 0 || distOut < distIn) {
0097 inside = Inside_v(kInside);
0098 return;
0099 }
0100 if (distIn < 0 || distIn * tessellated.fTestDir.Dot(tessellated.fFacets[isurfIn]->fNormal) > -kTolerance)
0101 inside = Inside_v(kSurface);
0102 }
0103
0104 template <typename Real_v>
0105 VECGEOM_FORCE_INLINE
0106 VECCORE_ATT_HOST_DEVICE
0107 static void DistanceToIn(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point,
0108 Vector3D<Real_v> const &direction, Real_v const &stepMax, Real_v &distance)
0109 {
0110 int isurf, isurfOut;
0111 Real_v distOut;
0112 DistanceToSolid<Real_v, true>(tessellated, point, direction, stepMax, distance, isurf, distOut, isurfOut);
0113 }
0114
0115 template <typename Real_v>
0116 VECGEOM_FORCE_INLINE
0117 VECCORE_ATT_HOST_DEVICE
0118 static void DistanceToOut(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point,
0119 Vector3D<Real_v> const &direction, Real_v const &stepMax, Real_v &distance)
0120 {
0121 int isurf, isurfIn;
0122 Real_v distIn;
0123 DistanceToSolid<Real_v, false>(tessellated, point, direction, stepMax, distance, isurf, distIn, isurfIn);
0124 }
0125
0126 template <typename Real_v>
0127 VECGEOM_FORCE_INLINE
0128 VECCORE_ATT_HOST_DEVICE
0129 static void SafetyToIn(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point, Real_v &safety)
0130 {
0131 using Bool_v = vecCore::Mask_v<Real_v>;
0132 Bool_v inside;
0133 TessellatedImplementation::Contains<Real_v, Bool_v>(tessellated, point, inside);
0134 if (inside) {
0135 safety = -1.;
0136 return;
0137 }
0138 int isurf;
0139 Real_v safetysq = SafetySq<Real_v, true>(tessellated, point, isurf);
0140 safety = vecCore::math::Sqrt(safetysq);
0141 }
0142
0143 template <typename Real_v>
0144 VECGEOM_FORCE_INLINE
0145 VECCORE_ATT_HOST_DEVICE
0146 static void SafetyToOut(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point, Real_v &safety)
0147 {
0148 using Bool_v = vecCore::Mask_v<Real_v>;
0149 Bool_v inside;
0150 TessellatedImplementation::Contains<Real_v, Bool_v>(tessellated, point, inside);
0151 if (!inside) {
0152 safety = -1.;
0153 return;
0154 }
0155 int isurf;
0156 Real_v safetysq = SafetySq<Real_v, false>(tessellated, point, isurf);
0157 safety = vecCore::math::Sqrt(safetysq);
0158 }
0159
0160 template <typename Real_v>
0161 VECGEOM_FORCE_INLINE
0162 VECCORE_ATT_HOST_DEVICE
0163 static Vector3D<Real_v> NormalKernel(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point,
0164 typename vecCore::Mask_v<Real_v> &valid)
0165 {
0166
0167 valid = true;
0168 int isurf;
0169
0170 SafetySq<Real_v, false>(tessellated, point, isurf);
0171 return tessellated.fFacets[isurf]->fNormal;
0172 }
0173
0174 template <typename Real_v, bool ToIn>
0175 VECCORE_ATT_HOST_DEVICE
0176 static void DistanceToSolid(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point,
0177 Vector3D<Real_v> const &direction, Real_v const &stepMax, Real_v &distance, int &isurf,
0178 Real_v &distother, int &isurfother)
0179 {
0180
0181
0182 #ifndef VECGEOM_ENABLE_CUDA
0183 using Float_v = vecgeom::VectorBackend::Real_v;
0184 #else
0185 using Float_v = vecgeom::ScalarBackend::Real_v;
0186 #endif
0187 isurf = -1;
0188 isurfother = -1;
0189 if (ToIn) {
0190
0191 const Vector3D<Real_v> invdir(Real_v(1.0) / NonZero(direction.x()), Real_v(1.0) / NonZero(direction.y()),
0192 Real_v(1.0) / NonZero(direction.z()));
0193 Vector3D<int> sign;
0194 sign[0] = invdir.x() < 0;
0195 sign[1] = invdir.y() < 0;
0196 sign[2] = invdir.z() < 0;
0197 distance = BoxImplementation::IntersectCachedKernel2<Real_v, Real_v>(
0198 &tessellated.fMinExtent, point, invdir, sign.x(), sign.y(), sign.z(), -kTolerance, InfinityLength<Real_v>());
0199 if (distance >= stepMax) return;
0200 }
0201
0202
0203
0204 Vector3D<Float_v> pointv(point);
0205 Vector3D<Float_v> dirv(direction);
0206 distance = InfinityLength<Real_v>();
0207 distother = InfinityLength<Real_v>();
0208 Real_v distanceToIn = InfinityLength<Real_v>();
0209 Real_v distanceToOut = InfinityLength<Real_v>();
0210 int isurfToIn = -1;
0211 int isurfToOut = -1;
0212 auto userhook = [&](HybridManager2::BoxIdDistancePair_t hitbox) {
0213
0214
0215 if (hitbox.second > vecCore::math::Min(stepMax, distance)) return true;
0216
0217 Real_v clusterToIn, clusterToOut;
0218 int icrtToIn, icrtToOut;
0219 tessellated.fClusters[hitbox.first]->DistanceToCluster(pointv, dirv, clusterToIn, clusterToOut, icrtToIn,
0220 icrtToOut);
0221
0222
0223 if (icrtToIn >= 0 && clusterToIn < distanceToIn) {
0224 distanceToIn = clusterToIn;
0225 isurfToIn = icrtToIn;
0226 if (ToIn) {
0227 isurf = isurfToIn;
0228 distance = distanceToIn;
0229 } else {
0230 isurfother = isurfToIn;
0231 distother = distanceToIn;
0232 }
0233 }
0234
0235 if (icrtToOut >= 0 && clusterToOut < distanceToOut) {
0236 distanceToOut = clusterToOut;
0237 isurfToOut = icrtToOut;
0238 if (!ToIn) {
0239 isurf = isurfToOut;
0240 distance = distanceToOut;
0241 } else {
0242 isurfother = isurfToOut;
0243 distother = distanceToOut;
0244 }
0245 }
0246 return false;
0247 };
0248
0249 #ifdef USEEMBREE
0250 EmbreeNavigator<> *boxNav = (EmbreeNavigator<> *)EmbreeNavigator<>::Instance();
0251
0252 boxNav->BVHSortedIntersectionsLooper(*tessellated.fNavHelper2, point, direction, 1E20, userhook);
0253 #else
0254 HybridNavigator<> *boxNav = (HybridNavigator<> *)HybridNavigator<>::Instance();
0255 boxNav->BVHSortedIntersectionsLooper(*tessellated.fNavHelper2, point, direction, stepMax, userhook);
0256 #endif
0257
0258
0259 if (ToIn) {
0260 if (isurfToIn < 0) {
0261 if (isurfToOut >= 0 && distanceToOut * direction.Dot(tessellated.fFacets[isurfToOut]->fNormal) > kTolerance)
0262 distance = -1.;
0263
0264 } else {
0265 if (isurfToOut >= 0 && distanceToOut > kTolerance && distanceToOut < distanceToIn)
0266 distance = -1.;
0267
0268 }
0269 } else {
0270 if (isurfToOut < 0)
0271 distance = -1.;
0272 else {
0273 if (isurfToIn >= 0 && distanceToIn < distanceToOut &&
0274 distanceToIn * direction.Dot(tessellated.fFacets[isurfToIn]->fNormal) < -kTolerance) {
0275 distance = -1.;
0276 isurf = -1;
0277 }
0278 }
0279 }
0280 }
0281
0282 template <typename Real_v, bool ToIn>
0283 VECCORE_ATT_HOST_DEVICE
0284 static Real_v SafetySq(UnplacedStruct_t const &tessellated, Vector3D<Real_v> const &point, int &isurf)
0285 {
0286 #ifndef VECGEOM_ENABLE_CUDA
0287 using Float_v = vecgeom::VectorBackend::Real_v;
0288 #else
0289 using Float_v = vecgeom::ScalarBackend::Real_v;
0290 #endif
0291 Real_v safetysq = InfinityLength<Real_v>();
0292 isurf = -1;
0293 Vector3D<Float_v> pointv(point);
0294
0295 auto userhook = [&](HybridManager2::BoxIdDistancePair_t hitbox) {
0296
0297
0298 if (hitbox.second > safetysq) return true;
0299
0300 int isurfcrt;
0301 Real_v safetycrt = tessellated.fClusters[hitbox.first]->template SafetySq<ToIn>(pointv, isurfcrt);
0302 if (safetycrt < safetysq) {
0303 safetysq = safetycrt;
0304 isurf = isurfcrt;
0305 }
0306 return false;
0307 };
0308
0309 HybridSafetyEstimator *safEstimator = (HybridSafetyEstimator *)HybridSafetyEstimator::Instance();
0310
0311 safEstimator->BVHSortedSafetyLooper(*tessellated.fNavHelper, point, userhook, safetysq);
0312 return safetysq;
0313 }
0314
0315 };
0316 }
0317 }
0318
0319 #endif