File indexing completed on 2025-01-18 10:14:05
0001
0002
0003
0004 #ifndef VECGEOM_VOLUMES_KERNEL_TUBEIMPLEMENTATION_H_
0005 #define VECGEOM_VOLUMES_KERNEL_TUBEIMPLEMENTATION_H_
0006
0007 #include "VecGeom/base/Vector3D.h"
0008 #include "VecGeom/volumes/kernel/GenericKernels.h"
0009 #include "VecGeom/volumes/kernel/shapetypes/TubeTypes.h"
0010 #include "VecGeom/volumes/TubeStruct.h"
0011 #include "VecGeom/volumes/Wedge.h"
0012 #include <cstdio>
0013
0014 #define TUBE_SAFETY_OLD
0015
0016
0017 namespace vecgeom {
0018
0019 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE(struct, TubeImplementation, typename);
0020
0021 inline namespace VECGEOM_IMPL_NAMESPACE {
0022
0023 namespace TubeUtilities {
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template <typename Real_v, typename ShapeType, typename UnplacedVolumeType, bool onSurfaceT,
0059 bool includeSurface = true>
0060 VECGEOM_FORCE_INLINE
0061 VECCORE_ATT_HOST_DEVICE
0062 void PointInCyclicalSector(UnplacedVolumeType const &volume, Real_v const &x, Real_v const &y,
0063 typename vecCore::Mask_v<Real_v> &ret)
0064 {
0065 using namespace ::vecgeom::TubeTypes;
0066
0067
0068
0069 Real_v startx(volume.fAlongPhi1x);
0070 Real_v starty(volume.fAlongPhi1y);
0071
0072 Real_v endx(volume.fAlongPhi2x);
0073 Real_v endy(volume.fAlongPhi2y);
0074
0075 bool smallerthanpi;
0076
0077 if (SectorType<ShapeType>::value == kUnknownAngle)
0078 smallerthanpi = volume.fDphi <= M_PI;
0079 else
0080 smallerthanpi = SectorType<ShapeType>::value == kOnePi || SectorType<ShapeType>::value == kSmallerThanPi;
0081
0082 Real_v startCheck = (-x * starty + y * startx);
0083 Real_v endCheck = (-endx * y + endy * x);
0084
0085 if (onSurfaceT) {
0086
0087 ret = (Abs(startCheck) <= kHalfTolerance) || (Abs(endCheck) <= kHalfTolerance);
0088 } else {
0089 if (smallerthanpi) {
0090 if (includeSurface)
0091 ret = (startCheck >= -kHalfTolerance) & (endCheck >= -kHalfTolerance);
0092 else
0093 ret = (startCheck >= kHalfTolerance) & (endCheck >= kHalfTolerance);
0094 } else {
0095 if (includeSurface)
0096 ret = (startCheck >= -kHalfTolerance) || (endCheck >= -kHalfTolerance);
0097 else
0098 ret = (startCheck >= kHalfTolerance) || (endCheck >= kHalfTolerance);
0099 }
0100 }
0101 }
0102
0103 template <typename Real_v, typename UnplacedStruct_t, typename TubeType, bool LargestSolution, bool insectorCheck>
0104 VECGEOM_FORCE_INLINE
0105 VECCORE_ATT_HOST_DEVICE
0106 void CircleTrajectoryIntersection(Real_v const &b, Real_v const &c, UnplacedStruct_t const &tube,
0107 Vector3D<Real_v> const &pos, Vector3D<Real_v> const &dir, Real_v &dist,
0108 typename vecCore::Mask_v<Real_v> &ok)
0109 {
0110 using namespace ::vecgeom::TubeTypes;
0111
0112 using Bool_v = vecCore::Mask_v<Real_v>;
0113
0114 Real_v delta = b * b - c;
0115 ok = delta > Real_v(0.);
0116 if (LargestSolution) ok |= delta == Real_v(0.);
0117
0118 vecCore::MaskedAssign(delta, !ok, Real_v(0.));
0119 delta = Sqrt(delta);
0120 if (!LargestSolution) delta = -delta;
0121
0122 dist = -b + delta;
0123
0124
0125
0126
0127 ok &= dist >= -2 * kTolerance;
0128 if (vecCore::EarlyReturnAllowed() && vecCore::MaskEmpty(ok)) return;
0129
0130 if (insectorCheck) {
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 Real_v hitz = pos.z() + dist * dir.z();
0149 ok &= (Abs(hitz) <= tube.fZ);
0150 if (vecCore::EarlyReturnAllowed() && vecCore::MaskEmpty(ok)) return;
0151
0152 if (checkPhiTreatment<TubeType>(tube)) {
0153 Bool_v insector(false);
0154 Real_v hitx = pos.x() + dist * dir.x();
0155 Real_v hity = pos.y() + dist * dir.y();
0156 PointInCyclicalSector<Real_v, TubeType, UnplacedStruct_t, false, true>(tube, hitx, hity, insector);
0157
0158
0159 ok &= insector;
0160 }
0161 }
0162 }
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195 template <typename Real_v>
0196 VECGEOM_FORCE_INLINE
0197 VECCORE_ATT_HOST_DEVICE
0198 Real_v PerpDist2D(Real_v const &px, Real_v const &py, Real_v const &vx, Real_v const &vy)
0199 {
0200 return px * vy - py * vx;
0201 }
0202
0203
0204
0205
0206 template <typename Real_v, typename UnplacedStruct_t, typename TubeType, bool inside>
0207 VECGEOM_FORCE_INLINE
0208 VECCORE_ATT_HOST_DEVICE
0209 void PhiPlaneSafety(UnplacedStruct_t const &tube, Vector3D<Real_v> const &pos, Real_v &safety)
0210 {
0211 using namespace ::vecgeom::TubeTypes;
0212
0213 if ((SectorType<TubeType>::value == kUnknownAngle && tube.fDphi > M_PI) ||
0214 (SectorType<TubeType>::value == kBiggerThanPi)) {
0215 safety = Sqrt(pos.x() * pos.x() + pos.y() * pos.y());
0216 } else {
0217 safety = kInfLength;
0218 }
0219
0220 Real_v phi1 = PerpDist2D<Real_v>(pos.x(), pos.y(), Real_v(tube.fAlongPhi1x), Real_v(tube.fAlongPhi1y));
0221 if (inside) phi1 *= -1;
0222
0223 if (SectorType<TubeType>::value == kOnePi) {
0224 auto absphi1 = Abs(phi1);
0225 vecCore::MaskedAssign(safety, absphi1 > kHalfTolerance, absphi1);
0226 return;
0227 }
0228
0229
0230 vecCore::MaskedAssign(safety,
0231 phi1 > -kHalfTolerance &&
0232 phi1 < safety,
0233 phi1);
0234
0235 Real_v phi2 = PerpDist2D<Real_v>(pos.x(), pos.y(), Real_v(tube.fAlongPhi2x), Real_v(tube.fAlongPhi2y));
0236 if (!inside) phi2 *= -1;
0237
0238
0239 vecCore::MaskedAssign(safety,
0240 phi2 > -kHalfTolerance &&
0241 phi2 < safety,
0242 phi2);
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 template <typename Real_v, typename UnplacedStruct_t, typename TubeType, bool PositiveDirectionOfPhiVector,
0261 bool insectorCheck>
0262 VECGEOM_FORCE_INLINE
0263 VECCORE_ATT_HOST_DEVICE
0264 void PhiPlaneTrajectoryIntersection(Precision alongX, Precision alongY, Precision normalX, Precision normalY,
0265 UnplacedStruct_t const &tube, Vector3D<Real_v> const &pos,
0266 Vector3D<Real_v> const &dir, Real_v &dist, typename vecCore::Mask_v<Real_v> &ok)
0267 {
0268
0269 dist = kInfLength;
0270
0271
0272
0273
0274 Real_v dirDotNorm = dir.x() * normalX + dir.y() * normalY;
0275 if (insectorCheck)
0276 ok = (dirDotNorm > Real_v(0.));
0277 else
0278 ok = (dirDotNorm < Real_v(0.));
0279
0280
0281
0282 Real_v dirDotXY = (dir.y() * alongX - dir.x() * alongY);
0283 dist = (alongY * pos.x() - alongX * pos.y()) / NonZero(dirDotXY);
0284
0285 ok &= (dist * Abs(dirDotNorm)) > -kHalfTolerance;
0286
0287
0288 if (insectorCheck) {
0289 Real_v hitx = pos.x() + dist * dir.x();
0290 Real_v hity = pos.y() + dist * dir.y();
0291 Real_v hitz = pos.z() + dist * dir.z();
0292 Real_v r2 = hitx * hitx + hity * hity;
0293 ok &= Abs(hitz) <= tube.fTolOz && (r2 >= tube.fTolOrmin2) && (r2 <= tube.fTolOrmax2);
0294
0295
0296
0297
0298 if (PositiveDirectionOfPhiVector) {
0299 ok = ok && (hitx * alongX + hity * alongY) > Real_v(0.);
0300 }
0301 } else {
0302 if (PositiveDirectionOfPhiVector) {
0303 Real_v hitx = pos.x() + dist * dir.x();
0304 Real_v hity = pos.y() + dist * dir.y();
0305 ok = ok && (hitx * alongX + hity * alongY) >= Real_v(0.);
0306 }
0307 }
0308 }
0309
0310 template <typename Real_v, typename UnplacedStruct_t, bool ForInnerSurface>
0311 VECGEOM_FORCE_INLINE
0312 VECCORE_ATT_HOST_DEVICE
0313 typename vecCore::Mask_v<Real_v> IsOnTubeSurface(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point)
0314 {
0315 const Real_v rho = point.Perp2();
0316 if (ForInnerSurface) {
0317 return (rho >= tube.fTolOrmin2) && (rho <= tube.fTolIrmin2) && (Abs(point.z()) < (tube.fZ + kTolerance));
0318 } else {
0319 return (rho >= tube.fTolIrmax2) && (rho <= tube.fTolOrmax2) && (Abs(point.z()) < (tube.fZ + kTolerance));
0320 }
0321 }
0322
0323 template <typename Real_v, bool ForInnerSurface>
0324 VECCORE_ATT_HOST_DEVICE
0325 Vector3D<Real_v> GetNormal(Vector3D<Real_v> const &point)
0326 {
0327 Vector3D<Real_v> norm(0., 0., 0.);
0328 if (ForInnerSurface) {
0329 norm.Set(-point.x(), -point.y(), 0.);
0330 } else {
0331 norm.Set(point.x(), point.y(), 0.);
0332 }
0333 return norm;
0334 }
0335
0336 template <typename Real_v, typename UnplacedStruct_t, bool ForInnerSurface>
0337 VECGEOM_FORCE_INLINE
0338 VECCORE_ATT_HOST_DEVICE
0339 typename vecCore::Mask_v<Real_v> IsMovingInsideTubeSurface(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point,
0340 Vector3D<Real_v> const &direction)
0341 {
0342 return IsOnTubeSurface<Real_v, UnplacedStruct_t, ForInnerSurface>(tube, point) &&
0343 (direction.Dot(GetNormal<Real_v, ForInnerSurface>(point)) <= Real_v(0.));
0344 }
0345
0346 }
0347
0348 template <typename T>
0349 class SPlacedTube;
0350 template <typename T>
0351 class SUnplacedTube;
0352 template <typename tubeTypeT>
0353 struct TubeImplementation {
0354
0355 using UnplacedStruct_t = ::vecgeom::TubeStruct<Precision>;
0356 using UnplacedVolume_t = SUnplacedTube<tubeTypeT>;
0357 using PlacedShape_t = SPlacedTube<UnplacedVolume_t>;
0358
0359 VECCORE_ATT_HOST_DEVICE
0360 static void PrintType()
0361 {
0362
0363
0364
0365 }
0366
0367 template <typename Stream>
0368 static void PrintType(Stream &s, int transCodeT = translation::kGeneric, int rotCodeT = rotation::kGeneric)
0369 {
0370 s << "SpecializedTube<" << transCodeT << "," << rotCodeT << ",TubeTypes::" << tubeTypeT::toString() << ">";
0371 }
0372
0373 template <typename Stream>
0374 static void PrintImplementationType(Stream &s)
0375 {
0376 (void)s;
0377
0378
0379
0380 }
0381
0382 template <typename Stream>
0383 static void PrintUnplacedType(Stream &s)
0384 {
0385 s << "UnplacedTube";
0386 }
0387
0388
0389 template <typename Real_v, bool ForInside>
0390 VECGEOM_FORCE_INLINE
0391 VECCORE_ATT_HOST_DEVICE
0392 static void GenericKernelForContainsAndInside(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point,
0393 typename vecCore::Mask_v<Real_v> &completelyinside,
0394 typename vecCore::Mask_v<Real_v> &completelyoutside)
0395 {
0396 using namespace ::vecgeom::TubeTypes;
0397 using Bool_v = vecCore::Mask_v<Real_v>;
0398
0399
0400 Real_v absz = Abs(point[2]);
0401 completelyoutside = absz > MakePlusTolerant<ForInside>(tube.fZ);
0402 if (ForInside) {
0403 completelyinside = absz < MakeMinusTolerant<ForInside>(tube.fZ);
0404 }
0405 if (vecCore::EarlyReturnAllowed()) {
0406 if (vecCore::MaskFull(completelyoutside)) {
0407 return;
0408 }
0409 }
0410
0411
0412 Real_v r2 = point.x() * point.x() + point.y() * point.y();
0413
0414
0415 completelyoutside |= r2 > MakePlusTolerantSquare<ForInside>(tube.fRmax);
0416 if (ForInside) {
0417 completelyinside &= r2 < MakeMinusTolerantSquare<ForInside>(tube.fRmax);
0418 }
0419 if (vecCore::EarlyReturnAllowed()) {
0420 if (vecCore::MaskFull(completelyoutside)) {
0421 return;
0422 }
0423 }
0424
0425
0426 if (checkRminTreatment<tubeTypeT>(tube)) {
0427 completelyoutside |= r2 <= MakeMinusTolerantSquare<ForInside>(tube.fRmin);
0428 if (ForInside) {
0429 completelyinside &= r2 > MakePlusTolerantSquare<ForInside>(tube.fRmin);
0430 }
0431 if (vecCore::EarlyReturnAllowed()) {
0432 if (vecCore::MaskFull(completelyoutside)) {
0433 return;
0434 }
0435 }
0436 }
0437
0438 if (checkPhiTreatment<tubeTypeT>(tube)) {
0439 Bool_v completelyoutsidephi(false);
0440 Bool_v completelyinsidephi(false);
0441 tube.fPhiWedge.GenericKernelForContainsAndInside<Real_v, ForInside>(point, completelyinsidephi,
0442 completelyoutsidephi);
0443
0444 completelyoutside |= completelyoutsidephi;
0445 if (ForInside) completelyinside &= completelyinsidephi;
0446 }
0447 }
0448
0449 template <typename Real_v>
0450 VECGEOM_FORCE_INLINE
0451 VECCORE_ATT_HOST_DEVICE
0452 static void Contains(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point,
0453 typename vecCore::Mask_v<Real_v> &contains)
0454 {
0455 using Bool_v = vecCore::Mask_v<Real_v>;
0456 Bool_v unused, outside;
0457 GenericKernelForContainsAndInside<Real_v, false>(tube, point, unused, outside);
0458 contains = !outside;
0459 }
0460
0461 template <typename Real_v, typename Inside_t>
0462 VECGEOM_FORCE_INLINE
0463 VECCORE_ATT_HOST_DEVICE
0464 static void Inside(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point, Inside_t &inside)
0465 {
0466 using Bool_v = vecCore::Mask_v<Real_v>;
0467 using InsideBool_v = vecCore::Mask_v<Inside_t>;
0468 Bool_v completelyinside, completelyoutside;
0469 GenericKernelForContainsAndInside<Real_v, true>(tube, point, completelyinside, completelyoutside);
0470 inside = EInside::kSurface;
0471 vecCore::MaskedAssign(inside, (InsideBool_v)completelyoutside, Inside_t(EInside::kOutside));
0472 vecCore::MaskedAssign(inside, (InsideBool_v)completelyinside, Inside_t(EInside::kInside));
0473 }
0474
0475 template <typename Real_v>
0476 VECGEOM_FORCE_INLINE
0477 VECCORE_ATT_HOST_DEVICE
0478 static void DistanceToIn(UnplacedStruct_t const &tube, Vector3D<Real_v> const &pointt, Vector3D<Real_v> const &dir,
0479 Real_v const &stepMax, Real_v &distance)
0480 {
0481 Vector3D<Real_v> point = pointt;
0482 Real_v ptDist = point.Mag();
0483 Real_v distToMove(0.);
0484 using Bool_v = vecCore::Mask_v<Real_v>;
0485 Precision order = 100.;
0486 Bool_v cond = (ptDist > order * tube.fMaxVal);
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498 vecCore__MaskedAssignFunc(distToMove, cond, (ptDist - Real_v(order * tube.fMaxVal)));
0499 vecCore__MaskedAssignFunc(point, cond, point + distToMove * dir);
0500 DistanceToInKernel<Real_v>(tube, point, dir, stepMax, distance);
0501 distance += distToMove;
0502 }
0503
0504 template <typename Real_v>
0505 VECGEOM_FORCE_INLINE
0506 VECCORE_ATT_HOST_DEVICE
0507 static void DistanceToInKernel(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point,
0508 Vector3D<Real_v> const &dir, Real_v const &stepMax, Real_v &distance)
0509 {
0510 (void)stepMax;
0511 using namespace TubeUtilities;
0512 using namespace ::vecgeom::TubeTypes;
0513
0514 using Bool_v = vecCore::Mask_v<Real_v>;
0515
0516 Bool_v done(false);
0517
0518
0519 distance = kInfLength;
0520
0521
0522 Real_v distz = Abs(point.z()) - tube.fZ;
0523 done |= distz > kHalfTolerance && point.z() * dir.z() >= 0;
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533 Real_v rsq = point.x() * point.x() + point.y() * point.y();
0534 Real_v rdotn = point.x() * dir.x() + point.y() * dir.y();
0535 done |= rsq > tube.fTolIrmax2 && rdotn >= 0;
0536 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done)) return;
0537
0538
0539
0540 vecCore__MaskedAssignFunc(distance, !done, Real_v(-1.0));
0541
0542
0543 Bool_v inside = distz < -kHalfTolerance;
0544
0545 inside &= rsq < tube.fTolIrmax2;
0546 if (checkRminTreatment<tubeTypeT>(tube)) {
0547 inside &= rsq > tube.fTolIrmin2;
0548 }
0549 if (checkPhiTreatment<tubeTypeT>(tube) && !vecCore::MaskEmpty(inside)) {
0550 Bool_v insector;
0551 PointInCyclicalSector<Real_v, tubeTypeT, UnplacedStruct_t, false, false>(tube, point.x(), point.y(), insector);
0552 inside &= insector;
0553
0554
0555 }
0556 done |= inside;
0557 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done)) return;
0558
0559
0560
0561 vecCore::MaskedAssign(distance, !done, Real_v(kInfLength));
0562
0563 distz /= NonZeroAbs(dir.z());
0564
0565
0566 Real_v hitx = point.x() + distz * dir.x();
0567 Real_v hity = point.y() + distz * dir.y();
0568 Real_v r2 = hitx * hitx + hity * hity;
0569 Bool_v okz = distz > -kHalfTolerance && (point.z() * dir.z() < 0);
0570
0571 okz &= (r2 <= tube.fRmax2);
0572 if (checkRminTreatment<tubeTypeT>(tube)) {
0573 okz &= (tube.fRmin2 <= r2);
0574 }
0575 if (checkPhiTreatment<tubeTypeT>(tube) && !vecCore::MaskEmpty(okz)) {
0576 Bool_v insector;
0577 PointInCyclicalSector<Real_v, tubeTypeT, UnplacedStruct_t, false>(tube, hitx, hity, insector);
0578 okz &= insector;
0579
0580
0581 }
0582 vecCore::MaskedAssign(distance, !done && okz, distz);
0583 done |= okz;
0584
0585 Bool_v isOnSurfaceAndMovingInside = IsMovingInsideTubeSurface<Real_v, UnplacedStruct_t, false>(tube, point, dir);
0586 if (checkRminTreatment<tubeTypeT>(tube)) {
0587 isOnSurfaceAndMovingInside |= IsMovingInsideTubeSurface<Real_v, UnplacedStruct_t, true>(tube, point, dir);
0588 }
0589
0590 if (!checkPhiTreatment<tubeTypeT>(tube)) {
0591 vecCore__MaskedAssignFunc(distance, !done && isOnSurfaceAndMovingInside, Real_v(0.));
0592 done |= isOnSurfaceAndMovingInside;
0593 if (vecCore::MaskFull(done)) return;
0594 } else {
0595 Bool_v insector(false);
0596 PointInCyclicalSector<Real_v, tubeTypeT, UnplacedStruct_t, false>(tube, point.x(), point.y(), insector);
0597 vecCore__MaskedAssignFunc(distance, !done && insector && isOnSurfaceAndMovingInside, Real_v(0.));
0598 done |= (insector && isOnSurfaceAndMovingInside);
0599 if (vecCore::MaskFull(done)) return;
0600 }
0601
0602
0603
0604
0605
0606
0607
0608 Real_v invnsq = Real_v(1.) / NonZero(Real_v(1.) - dir.z() * dir.z());
0609 Real_v b = invnsq * rdotn;
0610
0611
0612
0613
0614
0615
0616
0617 Real_v crmax = invnsq * (rsq - tube.fRmax2);
0618 Real_v dist_rmax;
0619 Bool_v ok_rmax(false);
0620 CircleTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, false, true>(b, crmax, tube, point, dir,
0621 dist_rmax, ok_rmax);
0622 ok_rmax &= dist_rmax < distance;
0623 vecCore::MaskedAssign(distance, !done && ok_rmax, dist_rmax);
0624 done |= ok_rmax;
0625 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done)) return;
0626
0627
0628
0629
0630
0631
0632
0633 Real_v dist_rmin(-kInfLength);
0634 Bool_v ok_rmin(false);
0635 if (checkRminTreatment<tubeTypeT>(tube)) {
0636
0637
0638
0639
0640
0641
0642
0643 Real_v crmin = invnsq * (rsq - tube.fRmin2);
0644 CircleTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, true, true>(b, crmin, tube, point, dir,
0645 dist_rmin, ok_rmin);
0646 ok_rmin &= dist_rmin < distance;
0647 vecCore::MaskedAssign(distance, !done && ok_rmin, dist_rmin);
0648
0649
0650 }
0651
0652
0653
0654
0655 if (checkPhiTreatment<tubeTypeT>(tube)) {
0656
0657 Real_v dist_phi;
0658 Bool_v ok_phi;
0659 auto const &w = tube.fPhiWedge;
0660 PhiPlaneTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, SectorType<tubeTypeT>::value != kOnePi, true>(
0661 tube.fAlongPhi1x, tube.fAlongPhi1y, w.GetNormal1().x(), w.GetNormal1().y(), tube, point, dir, dist_phi,
0662 ok_phi);
0663 ok_phi &= dist_phi < distance;
0664 vecCore::MaskedAssign(distance, !done && ok_phi, dist_phi);
0665 done |= ok_phi;
0666
0667
0668
0669
0670
0671
0672
0673
0674 if (SectorType<tubeTypeT>::value != kOnePi) {
0675 PhiPlaneTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, true, true>(
0676 tube.fAlongPhi2x, tube.fAlongPhi2y, w.GetNormal2().x(), w.GetNormal2().y(), tube, point, dir, dist_phi,
0677 ok_phi);
0678 vecCore::MaskedAssign(distance, ok_phi && dist_phi < distance, dist_phi);
0679 }
0680 }
0681 }
0682
0683 template <typename Real_v>
0684 VECGEOM_FORCE_INLINE
0685 VECCORE_ATT_HOST_DEVICE
0686 static void DistanceToOut(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point, Vector3D<Real_v> const &dir,
0687 Real_v const &stepMax, Real_v &distance)
0688 {
0689 (void)stepMax;
0690 using namespace ::vecgeom::TubeTypes;
0691 using namespace TubeUtilities;
0692
0693 using Bool_v = vecCore::Mask_v<Real_v>;
0694
0695 distance = Real_v(-1.);
0696 Bool_v done(false);
0697
0698
0699
0700
0701
0702 Real_v distz = tube.fZ - Abs(point.z());
0703 done |= distz < -kHalfTolerance;
0704 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done)) return;
0705
0706 Real_v rsq = point.x() * point.x() + point.y() * point.y();
0707 Real_v rdotn = dir.x() * point.x() + dir.y() * point.y();
0708 Real_v crmax = rsq - tube.fRmax2;
0709 Real_v crmin = rsq;
0710
0711
0712 done |= crmax > Real_v(2.0 * kTolerance * tube.fRmax);
0713 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done)) return;
0714
0715 if (checkRminTreatment<tubeTypeT>(tube)) {
0716
0717
0718 crmin -= tube.fRmin2;
0719 done |= crmin < Real_v(-2.0 * kTolerance * tube.fRmin);
0720 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done)) return;
0721 }
0722
0723
0724 if (checkPhiTreatment<tubeTypeT>(tube)) {
0725 Bool_v completelyoutsidephi(false);
0726 Bool_v completelyinsidephi(false);
0727 tube.fPhiWedge.GenericKernelForContainsAndInside<Real_v, true>(point, completelyinsidephi, completelyoutsidephi);
0728
0729 done |= completelyoutsidephi;
0730 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done)) return;
0731 }
0732
0733
0734 vecCore::MaskedAssign(distance, !done, Real_v(kInfLength));
0735
0736 Real_v invdirz = Real_v(1.) / NonZero(dir.z());
0737 distz = (tube.fZ - point.z()) * invdirz;
0738 vecCore__MaskedAssignFunc(distz, dir.z() < 0, (-tube.fZ - point.z()) * invdirz);
0739 vecCore::MaskedAssign(distance, !done && dir.z() != Real_v(0.) && distz < distance, distz);
0740
0741
0742
0743
0744
0745
0746 Real_v invnsq = Real_v(1.) / NonZero(Real_v(1.) - dir.z() * dir.z());
0747 Real_v b = invnsq * rdotn;
0748
0749
0750
0751
0752
0753 if (checkRminTreatment<tubeTypeT>(tube)) {
0754 Real_v dist_rmin(kInfLength);
0755 Bool_v ok_rmin(false);
0756 crmin *= invnsq;
0757 CircleTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, false, false>(b, crmin, tube, point, dir,
0758 dist_rmin, ok_rmin);
0759 vecCore::MaskedAssign(distance, ok_rmin && dist_rmin < distance, dist_rmin);
0760 }
0761
0762
0763
0764
0765
0766 Real_v dist_rmax(kInfLength);
0767 Bool_v ok_rmax(false);
0768 crmax *= invnsq;
0769 CircleTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, true, false>(b, crmax, tube, point, dir,
0770 dist_rmax, ok_rmax);
0771 vecCore::MaskedAssign(distance, ok_rmax && dist_rmax < distance, dist_rmax);
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784 if (checkPhiTreatment<tubeTypeT>(tube)) {
0785 Real_v dist_phi(kInfLength);
0786 Bool_v ok_phi(false);
0787
0788 auto const &w = tube.fPhiWedge;
0789 if (SectorType<tubeTypeT>::value == kSmallerThanPi) {
0790
0791 Precision normal1X = w.GetNormal1().x();
0792 Precision normal1Y = w.GetNormal1().y();
0793 PhiPlaneTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, false, false>(
0794 tube.fAlongPhi1x, tube.fAlongPhi1y, normal1X, normal1Y, tube, point, dir, dist_phi, ok_phi);
0795 vecCore::MaskedAssign(distance, ok_phi && dist_phi < distance, dist_phi);
0796
0797 PhiPlaneTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, false, false>(
0798 tube.fAlongPhi2x, tube.fAlongPhi2y, w.GetNormal2().x(), w.GetNormal2().y(), tube, point, dir, dist_phi,
0799 ok_phi);
0800 vecCore::MaskedAssign(distance, ok_phi && dist_phi < distance, dist_phi);
0801 } else if (SectorType<tubeTypeT>::value == kOnePi) {
0802 PhiPlaneTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, false, false>(
0803 tube.fAlongPhi2x, tube.fAlongPhi2y, w.GetNormal2().x(), w.GetNormal2().x(), tube, point, dir, dist_phi,
0804 ok_phi);
0805 vecCore::MaskedAssign(distance, ok_phi && dist_phi < distance, dist_phi);
0806 } else {
0807
0808
0809 PhiPlaneTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, true, false>(
0810 tube.fAlongPhi1x, tube.fAlongPhi1y, w.GetNormal1().x(), w.GetNormal1().y(), tube, point, dir, dist_phi,
0811 ok_phi);
0812 vecCore::MaskedAssign(distance, ok_phi && dist_phi < distance, dist_phi);
0813
0814 PhiPlaneTrajectoryIntersection<Real_v, UnplacedStruct_t, tubeTypeT, true, false>(
0815 tube.fAlongPhi2x, tube.fAlongPhi2y, w.GetNormal2().x(), w.GetNormal2().y(), tube, point, dir, dist_phi,
0816 ok_phi);
0817 vecCore::MaskedAssign(distance, ok_phi && dist_phi < distance, dist_phi);
0818 }
0819 }
0820 return;
0821 }
0822
0823
0824
0825 template <typename Real_v>
0826 VECGEOM_FORCE_INLINE
0827 VECCORE_ATT_HOST_DEVICE
0828 static void SafetyAssign(Real_v safety, Real_v &positiveSafety, Real_v &negativeSafety)
0829 {
0830 vecCore::MaskedAssign(positiveSafety, safety >= Real_v(0.) && safety < positiveSafety, safety);
0831 vecCore::MaskedAssign(negativeSafety, safety <= Real_v(0.) && safety > negativeSafety, safety);
0832 }
0833
0834
0835
0836
0837
0838
0839 template <typename Real_v>
0840 VECGEOM_FORCE_INLINE
0841 VECCORE_ATT_HOST_DEVICE
0842 static void SafetyKernel(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point, Real_v &safePos,
0843 Real_v &safeNeg)
0844 {
0845
0846
0847 using namespace ::vecgeom::TubeTypes;
0848 using namespace TubeUtilities;
0849
0850 safePos = kInfLength;
0851 safeNeg = -safePos;
0852
0853 Real_v safez = Abs(point.z()) - tube.fZ;
0854 SafetyAssign(safez, safePos, safeNeg);
0855
0856 Real_v r = Sqrt(point.x() * point.x() + point.y() * point.y());
0857 Real_v safermax = r - tube.fRmax;
0858 SafetyAssign(safermax, safePos, safeNeg);
0859
0860 if (checkRminTreatment<tubeTypeT>(tube)) {
0861 Real_v safermin = tube.fRmin - r;
0862 SafetyAssign(safermin, safePos, safeNeg);
0863 }
0864
0865 if (checkPhiTreatment<tubeTypeT>(tube)) {
0866 Real_v safephi;
0867 PhiPlaneSafety<Real_v, UnplacedStruct_t, tubeTypeT, false>(tube, point, safephi);
0868 SafetyAssign(safephi, safePos, safeNeg);
0869 }
0870 }
0871
0872 template <typename Real_v>
0873 VECGEOM_FORCE_INLINE
0874 VECCORE_ATT_HOST_DEVICE
0875 static void SafetyToIn(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point, Real_v &safety)
0876 {
0877
0878 #ifdef TUBE_SAFETY_OLD
0879 SafetyToInOld(tube, point, safety);
0880 #else
0881 Real_v safetyInsidePoint, safetyOutsidePoint;
0882 SafetyKernel(tube, point, safetyOutsidePoint, safetyInsidePoint);
0883
0884
0885
0886
0887 safety = vecCore::Blend(safetyOutsidePoint == InfinityLength<Real_v>(), safetyInsidePoint, safetyOutsidePoint);
0888 #endif
0889 }
0890
0891 template <typename Real_v>
0892 VECGEOM_FORCE_INLINE
0893 VECCORE_ATT_HOST_DEVICE
0894 static void SafetyToOut(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point, Real_v &safety)
0895 {
0896 #ifdef TUBE_SAFETY_OLD
0897 SafetyToOutOld(tube, point, safety);
0898 #else
0899 Real_v safetyInsidePoint, safetyOutsidePoint;
0900 SafetyKernel<Real_v>(tube, point, safetyOutsidePoint, safetyInsidePoint);
0901
0902
0903
0904
0905 safety = -vecCore::Blend(safetyOutsidePoint == InfinityLength<Real_v>(), safetyInsidePoint, safetyOutsidePoint);
0906 #endif
0907 }
0908
0909 template <typename Real_v>
0910 VECGEOM_FORCE_INLINE
0911 VECCORE_ATT_HOST_DEVICE
0912 static void SafetyToInOld(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point, Real_v &safety)
0913 {
0914 using namespace ::vecgeom::TubeTypes;
0915 using namespace TubeUtilities;
0916
0917 using Bool_v = vecCore::Mask_v<Real_v>;
0918
0919 safety = Abs(point.z()) - tube.fZ;
0920
0921 Real_v r = Sqrt(point.x() * point.x() + point.y() * point.y());
0922 Real_v safermax = r - tube.fRmax;
0923 vecCore::MaskedAssign(safety, safermax > safety, safermax);
0924
0925 if (checkRminTreatment<tubeTypeT>(tube)) {
0926 Real_v safermin = tube.fRmin - r;
0927 vecCore::MaskedAssign(safety, safermin > safety, safermin);
0928 }
0929
0930 if (checkPhiTreatment<tubeTypeT>(tube)) {
0931 Bool_v insector;
0932 PointInCyclicalSector<Real_v, tubeTypeT, UnplacedStruct_t, false, false>(tube, point.x(), point.y(), insector);
0933 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(insector)) return;
0934
0935 Real_v safephi;
0936 PhiPlaneSafety<Real_v, UnplacedStruct_t, tubeTypeT, false>(tube, point, safephi);
0937 vecCore::MaskedAssign(safety, !insector && safephi < kInfLength && safephi > safety, safephi);
0938 }
0939 }
0940
0941 template <typename Real_v>
0942 VECGEOM_FORCE_INLINE
0943 VECCORE_ATT_HOST_DEVICE
0944 static void SafetyToOutOld(UnplacedStruct_t const &tube, Vector3D<Real_v> const &point, Real_v &safety)
0945 {
0946 using namespace ::vecgeom::TubeTypes;
0947 using namespace TubeUtilities;
0948
0949 safety = tube.fZ - Abs(point.z());
0950 Real_v r = Sqrt(point.x() * point.x() + point.y() * point.y());
0951 Real_v safermax = tube.fRmax - r;
0952 vecCore::MaskedAssign(safety, safermax < safety, safermax);
0953
0954 if (checkRminTreatment<tubeTypeT>(tube)) {
0955 Real_v safermin = r - tube.fRmin;
0956 vecCore::MaskedAssign(safety, safermin < safety, safermin);
0957 }
0958
0959 if (checkPhiTreatment<tubeTypeT>(tube)) {
0960
0961 Real_v safephi = tube.fPhiWedge.SafetyToOut<Real_v>(point);
0962 vecCore::MaskedAssign(safety, safephi < safety, safephi);
0963 }
0964 }
0965
0966 template <typename Real_v>
0967 VECGEOM_FORCE_INLINE
0968 VECCORE_ATT_HOST_DEVICE
0969 static Vector3D<Real_v> ApproxSurfaceNormalKernel(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point)
0970 {
0971
0972 Vector3D<Real_v> norm(0., 0., 0.);
0973 Real_v radius = point.Perp();
0974 Real_v distRMax = vecCore::math::Abs(radius - unplaced.fRmax);
0975 Real_v distRMin = kInfLength;
0976 vecCore__MaskedAssignFunc(distRMax, distRMax < Real_v(0.), InfinityLength<Real_v>());
0977 if (unplaced.fRmin) {
0978 distRMin = Abs(unplaced.fRmin - radius);
0979 vecCore__MaskedAssignFunc(distRMin, distRMin < Real_v(0.), InfinityLength<Real_v>());
0980 }
0981 Real_v distMin = Min(distRMin, distRMax);
0982
0983 Real_v distPhi1 = kInfLength, distPhi2 = kInfLength;
0984 if (unplaced.fDphi != vecgeom::kTwoPi) {
0985 distPhi1 = point.x() * unplaced.fPhiWedge.GetNormal1().x() + point.y() * unplaced.fPhiWedge.GetNormal1().y();
0986 distPhi2 = point.x() * unplaced.fPhiWedge.GetNormal2().x() + point.y() * unplaced.fPhiWedge.GetNormal2().y();
0987
0988 vecCore__MaskedAssignFunc(distPhi1, distPhi1 < Real_v(0.), InfinityLength<Real_v>());
0989 vecCore__MaskedAssignFunc(distPhi2, distPhi2 < Real_v(0.), InfinityLength<Real_v>());
0990 distMin = Min(distMin, Min(distPhi1, distPhi2));
0991 }
0992
0993 Real_v distZ = kInfLength;
0994 vecCore__MaskedAssignFunc(distZ, point.z() < Real_v(0.), vecCore::math::Abs(point.z() + unplaced.fZ));
0995 vecCore__MaskedAssignFunc(distZ, point.z() >= Real_v(0.), vecCore::math::Abs(point.z() - unplaced.fZ));
0996 distMin = Min(distMin, distZ);
0997
0998 if (unplaced.fDphi) {
0999 Vector3D<Real_v> normal1 = unplaced.fPhiWedge.GetNormal1();
1000 Vector3D<Real_v> normal2 = unplaced.fPhiWedge.GetNormal2();
1001 vecCore__MaskedAssignFunc(norm, distMin == distPhi1, -normal1);
1002 vecCore__MaskedAssignFunc(norm, distMin == distPhi2, -normal2);
1003 }
1004
1005 vecCore__MaskedAssignFunc(norm, (distMin == distZ) && (point.z() < Real_v(0.)), Vector3D<Real_v>(0., 0., -1.));
1006 vecCore__MaskedAssignFunc(norm, (distMin == distZ) && (point.z() >= Real_v(0.)), Vector3D<Real_v>(0., 0., 1.));
1007
1008 if (vecCore::math::Abs(point.z()) < (unplaced.fZ + kTolerance)) {
1009 Vector3D<Real_v> temp = point;
1010 temp.z() = Real_v(0.);
1011 vecCore__MaskedAssignFunc(norm, distMin == distRMax, temp.Unit());
1012 if (unplaced.fRmin) vecCore__MaskedAssignFunc(norm, distMin == distRMin, -temp.Unit());
1013 }
1014
1015 return norm;
1016 }
1017
1018 template <typename Real_v, typename Bool_v>
1019 VECGEOM_FORCE_INLINE
1020 VECCORE_ATT_HOST_DEVICE
1021 static void NormalKernel(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point, Vector3D<Real_v> &norm,
1022 Bool_v &valid)
1023 {
1024
1025 valid = Bool_v(false);
1026 Bool_v isPointInside(false), isPointOutside(false);
1027 GenericKernelForContainsAndInside<Real_v, true>(unplaced, point, isPointInside, isPointOutside);
1028 if (isPointInside || isPointOutside) {
1029 norm = ApproxSurfaceNormalKernel<Real_v>(unplaced, point);
1030 return;
1031 }
1032
1033 int nosurface = 0;
1034
1035 Precision x2y2 = Sqrt(point.x() * point.x() + point.y() * point.y());
1036 bool inZ = ((point.z() < unplaced.fZ + kTolerance) && (point.z() > -unplaced.fZ - kTolerance));
1037 bool inR = ((x2y2 >= unplaced.fRmin - kTolerance) && (x2y2 <= unplaced.fRmax + kTolerance));
1038
1039
1040 if (inR && (Abs(point.z() - unplaced.fZ) <= kTolerance)) {
1041 norm.Set(0., 0., 1.);
1042 nosurface++;
1043 }
1044 if (inR && (Abs(point.z() + unplaced.fZ) <= kTolerance)) {
1045 if (nosurface > 0) {
1046
1047 norm[2] += Real_v(-1.);
1048 } else {
1049 norm.Set(0., 0., -1.);
1050 }
1051 nosurface++;
1052 }
1053 if (unplaced.fRmin > 0.) {
1054 if (inZ && (Abs(x2y2 - unplaced.fRmin) <= kTolerance)) {
1055 Precision invx2y2 = 1. / x2y2;
1056 if (nosurface == 0) {
1057 norm[0] = -point[0] * invx2y2;
1058 norm[1] = -point[1] * invx2y2;
1059 norm[2] = Real_v(0.);
1060 } else {
1061 norm[0] += -point[0] * invx2y2;
1062 norm[1] += -point[1] * invx2y2;
1063 }
1064 nosurface++;
1065 }
1066 }
1067 if (inZ && (Abs(x2y2 - unplaced.fRmax) <= kTolerance)) {
1068 Precision invx2y2 = 1. / x2y2;
1069 if (nosurface > 0) {
1070 norm[0] += point[0] * invx2y2;
1071 norm[1] += point[1] * invx2y2;
1072 } else {
1073 norm[0] = point[0] * invx2y2;
1074 norm[1] = point[1] * invx2y2;
1075 norm[2] = Real_v(0.);
1076 }
1077 nosurface++;
1078 }
1079
1080
1081 if (unplaced.fDphi < vecgeom::kTwoPi) {
1082 if (inR && unplaced.fPhiWedge.IsOnSurface1(point)) {
1083 if (nosurface == 0)
1084 norm = -unplaced.fPhiWedge.GetNormal1();
1085 else
1086 norm += -unplaced.fPhiWedge.GetNormal1();
1087 nosurface++;
1088 }
1089 if (inR && unplaced.fPhiWedge.IsOnSurface2(point)) {
1090 if (nosurface == 0)
1091 norm = -unplaced.fPhiWedge.GetNormal2();
1092 else
1093 norm += -unplaced.fPhiWedge.GetNormal2();
1094 nosurface++;
1095 }
1096 }
1097 if (nosurface > 1) norm = norm / std::sqrt(1. * nosurface);
1098 valid = nosurface != 0;
1099 }
1100
1101 };
1102
1103 }
1104 }
1105
1106 #endif