1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
#ifndef VECGEOM_VOLUMES_SPHEREUTILITIES_H_
#define VECGEOM_VOLUMES_SPHEREUTILITIES_H_
#include "VecGeom/base/Global.h"
#ifndef VECCORE_CUDA
#include "VecGeom/base/RNG.h"
#endif
#include "VecGeom/base/Global.h"
#include "VecGeom/volumes/Wedge_Evolution.h"
#include "VecGeom/base/Vector3D.h"
#include "VecGeom/volumes/SphereStruct.h"
#include "VecGeom/volumes/kernel/GenericKernels.h"
#include <cstdio>
namespace vecgeom {
inline namespace VECGEOM_IMPL_NAMESPACE {
class UnplacedSphere;
template <typename T>
struct SphereStruct;
template <typename T>
VECGEOM_FORCE_INLINE
VECCORE_ATT_HOST_DEVICE
T sqr(T x)
{
return x * x;
}
#ifndef VECCORE_CUDA
// Generate radius in annular ring according to uniform area
template <typename T>
VECGEOM_FORCE_INLINE
T GetRadiusInRing(T rmin, T rmax)
{
if (rmin == rmax) return rmin;
T rng(RNG::Instance().uniform(0.0, 1.0));
if (rmin <= T(0.0)) return rmax * Sqrt(rng);
T rmin2 = rmin * rmin;
T rmax2 = rmax * rmax;
return Sqrt(rng * (rmax2 - rmin2) + rmin2);
}
#endif
namespace SphereUtilities {
using UnplacedStruct_t = SphereStruct<Precision>;
template <class Real_v>
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsPointOnInnerRadius(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point)
{
auto mag2 = point.Mag2();
return mag2 <= MakePlusTolerantSquare<true>(unplaced.fRmin) &&
mag2 >= MakeMinusTolerantSquare<true>(unplaced.fRmin);
}
template <class Real_v>
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsPointOnOuterRadius(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point)
{
auto mag2 = point.Mag2();
return mag2 <= MakePlusTolerantSquare<true>(unplaced.fRmax) &&
mag2 >= MakeMinusTolerantSquare<true>(unplaced.fRmax);
}
template <class Real_v>
VECGEOM_FORCE_INLINE
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsPointOnStartPhi(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point)
{
return unplaced.fPhiWedge.IsOnSurfaceGeneric<Real_v>(unplaced.fPhiWedge.GetAlong1(), unplaced.fPhiWedge.GetNormal1(),
point);
}
template <class Real_v>
VECGEOM_FORCE_INLINE
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsPointOnEndPhi(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point)
{
return unplaced.fPhiWedge.IsOnSurfaceGeneric<Real_v>(unplaced.fPhiWedge.GetAlong2(), unplaced.fPhiWedge.GetNormal2(),
point);
}
template <class Real_v>
VECGEOM_FORCE_INLINE
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsPointOnStartTheta(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point)
{
return unplaced.fThetaCone.IsOnSurfaceGeneric<Real_v, true>(point);
}
template <class Real_v>
VECGEOM_FORCE_INLINE
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsPointOnEndTheta(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point)
{
return unplaced.fThetaCone.IsOnSurfaceGeneric<Real_v, false>(point);
}
template <class Real_v>
VECGEOM_FORCE_INLINE
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsCompletelyOutside(UnplacedStruct_t const &unplaced,
Vector3D<Real_v> const &localPoint)
{
using Bool_v = vecCore::Mask_v<Real_v>;
Real_v rad = localPoint.Mag();
Bool_v outsideRadiusRange = (rad > (unplaced.fRmax + kTolerance)) || (rad < (unplaced.fRmin - kTolerance));
Bool_v outsidePhiRange(false), insidePhiRange(false);
unplaced.fPhiWedge.GenericKernelForContainsAndInside<Real_v, true>(localPoint, insidePhiRange, outsidePhiRange);
Bool_v outsideThetaRange = unplaced.fThetaCone.IsCompletelyOutside<Real_v>(localPoint);
Bool_v completelyoutside = outsideRadiusRange || outsidePhiRange || outsideThetaRange;
return completelyoutside;
}
template <class Real_v>
VECGEOM_FORCE_INLINE
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsCompletelyInside(UnplacedStruct_t const &unplaced,
Vector3D<Real_v> const &localPoint)
{
using Bool_v = vecCore::Mask_v<Real_v>;
Real_v rad = localPoint.Mag();
Bool_v insideRadiusRange = (rad < (unplaced.fRmax - kTolerance)) && (rad > (unplaced.fRmin + kTolerance));
Bool_v outsidePhiRange(false), insidePhiRange(false);
unplaced.fPhiWedge.GenericKernelForContainsAndInside<Real_v, true>(localPoint, insidePhiRange, outsidePhiRange);
Bool_v insideThetaRange = unplaced.fThetaCone.IsCompletelyInside<Real_v>(localPoint);
Bool_v completelyinside = insideRadiusRange && insidePhiRange && insideThetaRange;
return completelyinside;
}
template <class Real_v, bool ForInnerRadius, bool MovingOut>
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsPointOnRadialSurfaceAndMovingOut(UnplacedStruct_t const &unplaced,
Vector3D<Real_v> const &point,
Vector3D<Real_v> const &dir)
{
// Rays from rmax+tolerance or rmin-tolerance can be moving out even if not going fully "backward"
if (MovingOut) {
if (ForInnerRadius) {
return IsPointOnInnerRadius<Real_v>(unplaced, point) && (dir.Dot(-point) > Real_v(kSqrtTolerance));
} else {
return IsPointOnOuterRadius<Real_v>(unplaced, point) && (dir.Dot(point) > Real_v(kSqrtTolerance));
}
} else {
if (ForInnerRadius) {
return IsPointOnInnerRadius<Real_v>(unplaced, point) && (dir.Dot(-point) < Real_v(-kSqrtTolerance));
} else
return IsPointOnOuterRadius<Real_v>(unplaced, point) && (dir.Dot(point) < Real_v(-kSqrtTolerance));
}
}
template <class Real_v, bool MovingOut>
VECGEOM_FORCE_INLINE
VECCORE_ATT_HOST_DEVICE
typename vecCore::Mask_v<Real_v> IsPointOnSurfaceAndMovingOut(UnplacedStruct_t const &unplaced,
Vector3D<Real_v> const &point,
Vector3D<Real_v> const &dir)
{
using Bool_v = vecCore::Mask_v<Real_v>;
Bool_v tempOuterRad = IsPointOnRadialSurfaceAndMovingOut<Real_v, false, MovingOut>(unplaced, point, dir);
Bool_v tempInnerRad(false), tempStartPhi(false), tempEndPhi(false), tempStartTheta(false), tempEndTheta(false);
if (unplaced.fRmin) tempInnerRad = IsPointOnRadialSurfaceAndMovingOut<Real_v, true, MovingOut>(unplaced, point, dir);
if (unplaced.fDPhi < (kTwoPi - kHalfTolerance)) {
tempStartPhi = unplaced.fPhiWedge.IsPointOnSurfaceAndMovingOut<Real_v, true, MovingOut>(point, dir);
tempEndPhi = unplaced.fPhiWedge.IsPointOnSurfaceAndMovingOut<Real_v, false, MovingOut>(point, dir);
}
if (unplaced.fDTheta < (kPi - kHalfTolerance)) {
tempStartTheta = unplaced.fThetaCone.IsPointOnSurfaceAndMovingOut<Real_v, true, MovingOut>(point, dir);
tempEndTheta = unplaced.fThetaCone.IsPointOnSurfaceAndMovingOut<Real_v, false, MovingOut>(point, dir);
}
Bool_v isPointOnSurfaceAndMovingOut =
((tempOuterRad || tempInnerRad) && unplaced.fPhiWedge.Contains<Real_v>(point) &&
unplaced.fThetaCone.Contains<Real_v>(point)) ||
((tempStartPhi || tempEndPhi) && (point.Mag2() >= unplaced.fRmin * unplaced.fRmin) &&
(point.Mag2() <= unplaced.fRmax * unplaced.fRmax) && unplaced.fThetaCone.Contains<Real_v>(point)) ||
((tempStartTheta || tempEndTheta) && (point.Mag2() >= unplaced.fRmin * unplaced.fRmin) &&
(point.Mag2() <= unplaced.fRmax * unplaced.fRmax) && unplaced.fPhiWedge.Contains<Real_v>(point));
return isPointOnSurfaceAndMovingOut;
}
} // namespace SphereUtilities
} // namespace VECGEOM_IMPL_NAMESPACE
} // namespace vecgeom
#endif // VECGEOM_VOLUMES_SPHEREUTILITIES_H_
|