File indexing completed on 2026-05-25 08:25:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #ifndef VECGEOM_VOLUMES_KERNEL_GENTRAPIMPLEMENTATION_H_
0024 #define VECGEOM_VOLUMES_KERNEL_GENTRAPIMPLEMENTATION_H_
0025
0026 #include "VecGeom/base/Global.h"
0027 #include "VecGeom/base/Vector2D.h"
0028
0029 #include "VecGeom/volumes/kernel/GenericKernels.h"
0030 #include "VecGeom/volumes/kernel/BoxImplementation.h"
0031 #include "VecGeom/volumes/UnplacedGenTrap.h"
0032
0033 #include <iostream>
0034
0035 namespace vecgeom {
0036
0037 VECGEOM_DEVICE_FORWARD_DECLARE(struct GenTrapImplementation;);
0038 VECGEOM_DEVICE_DECLARE_CONV(struct, GenTrapImplementation);
0039
0040 inline namespace VECGEOM_IMPL_NAMESPACE {
0041
0042 class PlacedGenTrap;
0043 class UnplacedGenTrap;
0044
0045 template <typename T>
0046 struct GenTrapStruct;
0047
0048 struct GenTrapImplementation {
0049
0050 using Vertex_t = Vector3D<Precision>;
0051 using PlacedShape_t = PlacedGenTrap;
0052 using UnplacedStruct_t = GenTrapStruct<Precision>;
0053 using UnplacedVolume_t = UnplacedGenTrap;
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 template <typename Real_v, typename Bool_v>
0069 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Contains(UnplacedStruct_t const &unplaced,
0070 Vector3D<Real_v> const &point, Bool_v &inside);
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 template <typename Real_v, typename Inside_t>
0085 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Inside(UnplacedStruct_t const &unplaced,
0086 Vector3D<Real_v> const &point, Inside_t &inside);
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 template <typename Real_v, bool ForInside>
0104 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void GenericKernelForContainsAndInside(
0105 UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point, vecCore::Mask_v<Real_v> &completelyinside,
0106 vecCore::Mask_v<Real_v> &completelyoutside);
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 template <typename Real_v>
0122 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToIn(UnplacedStruct_t const &unplaced,
0123 Vector3D<Real_v> const &point,
0124 Vector3D<Real_v> const &direction,
0125 Real_v const &stepMax, Real_v &distance);
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 template <typename Real_v>
0140 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToOut(UnplacedStruct_t const &unplaced,
0141 Vector3D<Real_v> const &point,
0142 Vector3D<Real_v> const &direction,
0143 Real_v const &stepMax, Real_v &distance);
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 template <typename Real_v>
0157 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToIn(UnplacedStruct_t const &unplaced,
0158 Vector3D<Real_v> const &point, Real_v &safety);
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 template <typename Real_v>
0172 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToOut(UnplacedStruct_t const &unplaced,
0173 Vector3D<Real_v> const &point, Real_v &safety);
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189 template <typename Real_v, typename Bool_v>
0190 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void NormalKernel(UnplacedStruct_t const &unplaced,
0191 Vector3D<Real_v> const &point,
0192 Vector3D<Real_v> &normal, Bool_v &valid);
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 template <typename Real_v>
0214 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Real_v DistanceToSurf(UnplacedStruct_t const &unplaced,
0215 Vector3D<Real_v> const &point,
0216 Vector3D<Real_v> const &dir, int i, bool in,
0217 Real_v lmin = Real_v(0),
0218 Real_v lmax = InfinityLength<Real_v>());
0219
0220
0221
0222
0223
0224
0225
0226
0227 template <typename Real_v>
0228 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void FillVerticesAtZ(UnplacedStruct_t const &unplaced, Real_v z,
0229 Vector2D<Real_v> vertices[4]);
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239 template <class Real_v>
0240 VECCORE_ATT_HOST_DEVICE static void GetClosestEdge(Vector3D<Real_v> const &point, Vector2D<Real_v> const vertxy[4],
0241 int &iseg);
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 template <typename Real_v>
0254 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static bool InsideSection(Vector3D<Real_v> const &point,
0255 Vector3D<Real_v> const v[4]);
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268 template <typename Real_v>
0269 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static bool InSurfLimits(UnplacedStruct_t const &unplaced,
0270 Vector3D<Real_v> const &point, int isurf);
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 template <typename Real_v>
0286 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Real_v SafetyArb4(UnplacedStruct_t const &unplaced,
0287 Vector3D<Real_v> const &point, Real_v safmax,
0288 bool inside = true);
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 template <typename Real_v>
0309 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void UNormal(UnplacedStruct_t const &unplaced,
0310 Vector3D<Real_v> const &point, int i,
0311 Vector3D<Real_v> &unorm, Real_v &u, Real_v &v);
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324 template <typename Real_v>
0325 VECCORE_ATT_HOST_DEVICE static Vector2D<Real_v> XYZtoUV(UnplacedStruct_t const &unplaced,
0326 Vector3D<Real_v> const &point, int i);
0327 };
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353 template <typename Real_v>
0354 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE bool GenTrap_VInterval(Real_v ptZ, Real_v dirZ, Real_v Dz2, Real_v limit,
0355 Real_v &tmin, Real_v &tmax)
0356 {
0357
0358 const Real_v kv = dirZ * Dz2;
0359 const Real_v v0 = ptZ * Dz2 + Real_v(0.5);
0360 Real_v t0 = Real_v(0), t1 = limit;
0361 if (Abs(kv) < kToleranceDist<Real_v>) {
0362
0363 if (v0 < Real_v(0) - kToleranceDist<Real_v> || v0 > Real_v(1) + kToleranceDist<Real_v>) return false;
0364 tmin = t0;
0365 tmax = t1;
0366 return true;
0367 }
0368 const Real_v t_at_0 = (Real_v(0) - v0) / kv;
0369 const Real_v t_at_1 = (Real_v(1) - v0) / kv;
0370 Real_v a = Min(t_at_0, t_at_1), b = Max(t_at_0, t_at_1);
0371 t0 = Max(t0, a);
0372 t1 = Min(t1, b);
0373 if (t1 < t0) return false;
0374 tmin = t0;
0375 tmax = t1;
0376 return true;
0377 }
0378
0379
0380 template <typename Real_v>
0381 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Real_v
0382 GenTrapImplementation::DistanceToSurf(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point,
0383 Vector3D<Real_v> const &dir, int i, bool in, Real_v lmin, Real_v lmax)
0384 {
0385
0386 Real_v big = InfinityLength<Real_v>();
0387 VECGEOM_ASSERT(!unplaced.IsDegenerated(i) && "DistanceToSurf called with degenerated face");
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 if (!unplaced.IsTwisted(i)) {
0398
0399
0400
0401
0402
0403 const Real_v safety = unplaced.fSurf[i].EvaluatePlanar(point);
0404 const Real_v dn = unplaced.fSurf[i].DotPlaneNormal(dir);
0405
0406
0407
0408
0409 const bool facing_ok = in ^ (dn < -kToleranceDist<Real_v>);
0410 const bool side_ok = (in && safety < kToleranceDist<Real_v>) || (!in && safety > -kToleranceDist<Real_v>);
0411 if (!facing_ok || !side_ok) return big;
0412
0413
0414
0415
0416 Real_v snext = -safety / NonZero(dn);
0417
0418 if ((snext < lmin - kToleranceDist<Real_v>) || (snext >= lmax)) return big;
0419
0420
0421
0422 return InSurfLimits<Real_v>(unplaced, point + snext * dir, i) ? Max(snext, Real_v(0.)) : big;
0423 } else {
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433 #if GENTRAP_USE_HYBRID_COEFFS
0434 const auto pointXY = point.XY();
0435 const auto dirXY = dir.XY();
0436 const auto z = point[2];
0437 const auto dz = dir[2];
0438
0439
0440 const auto &dMid = unplaced.fDmid[i];
0441 const auto &dT = unplaced.fDT[i];
0442
0443
0444 const Real_v TT = unplaced.fTT[i];
0445 const Real_v MM = unplaced.fMM[i];
0446 const Real_v MT = unplaced.fMT[i];
0447
0448
0449 auto xz = [](auto const &a, auto const &b) -> Real_v { return a.x() * b.y() - a.y() * b.x(); };
0450
0451
0452 const Real_v dT_x_dir = xz(dT, dirXY);
0453 const Real_v dT_x_point = xz(dT, pointXY);
0454 const Real_v dMid_x_dir = xz(dMid, dirXY);
0455 const Real_v dMid_x_pt = xz(dMid, pointXY);
0456
0457 Real_v a = dT_x_dir * dz + TT * dz * dz;
0458 Real_v b = dMid_x_dir + z * dT_x_dir + (dT_x_point + (MT + Real_v(2) * z * TT)) * dz;
0459 Real_v c = dMid_x_pt + z * dT_x_point + MM + z * MT + z * z * TT;
0460 #else
0461 int j = (i + 1) % 4;
0462
0463
0464 auto const pointXY = point.XY();
0465 auto const dirXY = dir.XY();
0466 auto const t = unplaced.fT;
0467
0468 auto const s1 = unplaced.fMidXY[i] + t[i] * point[2];
0469 auto const s2 = unplaced.fMidXY[j] + t[j] * point[2];
0470 auto ds = s2 - s1;
0471
0472
0473 Real_v a = ((t[j] - t[i]).CrossZ(dirXY) + t[i].CrossZ(t[j]) * dir[2]) * dir[2];
0474 Real_v b = ds.CrossZ(dirXY) + ((t[j] - t[i]).CrossZ(pointXY) + s1.CrossZ(t[j]) - s2.CrossZ(t[i])) * dir[2];
0475 Real_v c = ds.CrossZ(pointXY) + s1.CrossZ(s2);
0476 #endif
0477
0478 constexpr Real_v tolerance = kToleranceArb4<Real_v>;
0479 Real_v dist[2];
0480 auto nroots = QuadraticSolver(a, b, c, dist);
0481
0482
0483 if (!in && nroots == 2 && Abs(dist[0]) < tolerance && Abs(dist[1]) < tolerance) return big;
0484
0485 for (auto k = 0; k < nroots; ++k) {
0486 const Real_v troot = dist[k];
0487
0488
0489 if ((troot < lmin - kToleranceDist<Real_v>) || (troot >= lmax)) continue;
0490
0491
0492 if (in && troot > tolerance) return troot;
0493
0494
0495 auto hit = point + troot * dir;
0496 auto uv = XYZtoUV(unplaced, hit, i);
0497 auto u = uv[0];
0498 auto v = uv[1];
0499 bool in_patch = (u >= Real_v(0.)) && (u <= Real_v(1.)) && (v >= Real_v(0.)) && (v <= Real_v(1.));
0500 if (!in_patch) continue;
0501
0502 auto grad = unplaced.fSurf[i].EvaluateGradient(hit);
0503 bool crosses_ok = in ^ (dir.Dot(grad) < Real_v(0.));
0504 if (crosses_ok) return troot;
0505 }
0506 }
0507 return big;
0508 }
0509
0510
0511 template <typename Real_v, bool ForInside>
0512 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::GenericKernelForContainsAndInside(
0513 UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point, vecCore::Mask_v<Real_v> &completelyinside,
0514 vecCore::Mask_v<Real_v> &completelyoutside)
0515 {
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525 static_assert(vecCore::VectorSize<Real_v>() == 1);
0526
0527
0528 Vector3D<Real_v> halfsize(unplaced.fBBdimensions[0], unplaced.fBBdimensions[1], unplaced.fBBdimensions[2]);
0529 BoxImplementation::GenericKernelForContainsAndInside<Real_v, true>(halfsize, point - unplaced.fBBorigin,
0530 completelyinside, completelyoutside);
0531
0532 constexpr Real_v tolerance = kToleranceArb4<Real_v>;
0533 if (completelyoutside) return;
0534
0535
0536 auto on_surfz = (unplaced.fDz - Abs(point.z())) < Real_v(kTolerance);
0537
0538
0539 VECGEOM_PRAGMA_UNROLL(4)
0540 for (int i = 0; i < 4; i++) {
0541 if (unplaced.IsDegenerated(i)) continue;
0542 auto eqeval = unplaced.IsTwisted(i) ? unplaced.fSurf[i].Evaluate(point) : unplaced.fSurf[i].EvaluatePlanar(point);
0543 completelyoutside = eqeval > tolerance;
0544 if (completelyoutside) {
0545 completelyinside = false;
0546 return;
0547 }
0548 if (ForInside && !on_surfz) completelyinside &= eqeval < -tolerance;
0549 }
0550 }
0551
0552
0553 template <typename Real_v, typename Bool_v>
0554 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::Contains(UnplacedStruct_t const &unplaced,
0555 Vector3D<Real_v> const &point,
0556 Bool_v &inside)
0557 {
0558 #ifndef VECCORE_CUDA
0559
0560
0561
0562
0563
0564 if (unplaced.fTslHelper) {
0565
0566 inside = false;
0567 if (vecCore::math::Abs(point.z()) > unplaced.fDz) return;
0568 inside = unplaced.fTslHelper->Contains(point);
0569 return;
0570 }
0571 #endif
0572
0573 Bool_v unused(false);
0574 Bool_v outside(false);
0575 GenericKernelForContainsAndInside<Real_v, false>(unplaced, point, unused, outside);
0576 inside = !outside;
0577 }
0578
0579
0580 template <typename Real_v, typename Inside_t>
0581 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::Inside(UnplacedStruct_t const &unplaced,
0582 Vector3D<Real_v> const &point,
0583 Inside_t &inside)
0584 {
0585 #ifndef VECCORE_CUDA
0586 if (unplaced.fTslHelper) {
0587
0588 inside = EInside::kOutside;
0589 Precision safZ = vecCore::math::Abs(point.z()) - unplaced.fDz;
0590 if (safZ > kTolerance) return;
0591 bool insideZ = safZ < -kTolerance;
0592 inside = unplaced.fTslHelper->Inside(point);
0593 if (insideZ || inside == EInside::kOutside) return;
0594 inside = EInside::kSurface;
0595 return;
0596 }
0597 #endif
0598 bool completelyinside;
0599 bool completelyoutside;
0600 GenericKernelForContainsAndInside<Real_v, true>(unplaced, point, completelyinside, completelyoutside);
0601
0602
0603 inside = EInside::kSurface;
0604 if (completelyoutside) inside = EInside::kOutside;
0605 if (completelyinside) inside = EInside::kInside;
0606 }
0607
0608
0609 template <typename Real_v>
0610 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::DistanceToIn(UnplacedStruct_t const &unplaced,
0611 Vector3D<Real_v> const &point,
0612 Vector3D<Real_v> const &direction,
0613 Real_v const &stepMax,
0614 Real_v &distance)
0615 {
0616 #ifndef VECCORE_CUDA
0617
0618 if (unplaced.fTslHelper) {
0619 Precision invdirz = 1. / NonZero(direction.z());
0620 distance = unplaced.fTslHelper->DistanceToIn<false>(point, direction, invdirz, stepMax);
0621 return;
0622 }
0623 #endif
0624
0625
0626
0627
0628
0629
0630 bool completelyinside, completelyoutside;
0631 GenericKernelForContainsAndInside<Real_v, true>(unplaced, point, completelyinside, completelyoutside);
0632
0633
0634 if (completelyinside) {
0635 distance = Real_v(-1.);
0636 return;
0637 }
0638
0639
0640 Real_v bbdistance = Real_v(kInfLength);
0641 BoxImplementation::DistanceToIn(BoxStruct<Precision>(unplaced.fBBdimensions), point - unplaced.fBBorigin, direction,
0642 stepMax, bbdistance);
0643
0644
0645 distance = InfinityLength<Real_v>();
0646
0647
0648 bool done = bbdistance >= InfinityLength<Real_v>();
0649 if (done) return;
0650
0651
0652 Real_v zsafety = Abs(point.z()) - unplaced.fDz;
0653 bool canhitz = (zsafety > -kToleranceDist<Real_v>) && (point.z() * direction.z() < 0);
0654
0655 if (canhitz) {
0656
0657 Real_v next = zsafety / Abs(direction.z());
0658
0659
0660 auto const vertices = (direction.z() > 0) ? &unplaced.fVertices[0] : &unplaced.fVertices[4];
0661 auto hitz = InsideSection(point + next * direction, vertices);
0662 if (hitz) {
0663 distance = next;
0664 return;
0665 }
0666 }
0667
0668
0669
0670 Real_v t_approach = Max(Real_v(0), bbdistance - kToleranceArb4<Real_v>);
0671 Vector3D<Real_v> p0 = point + t_approach * direction;
0672 Real_v step_budget = stepMax - t_approach;
0673 if (step_budget <= Real_v(0)) {
0674 distance = InfinityLength<Real_v>();
0675 return;
0676 }
0677
0678
0679
0680
0681
0682
0683 Real_v tmin_v, tmax_v;
0684 if (!GenTrap_VInterval(p0.z(), direction.z(), unplaced.fDz2, step_budget, tmin_v, tmax_v)) {
0685
0686 return;
0687 }
0688
0689
0690 Real_v lmin = Max(tmin_v, (t_approach > Real_v(0)) ? kToleranceArb4<Real_v> : Real_v(0));
0691 Real_v lmax = tmax_v;
0692 if (lmin > lmax) return;
0693
0694
0695 Real_v best_local = InfinityLength<Real_v>();
0696
0697
0698
0699 VECGEOM_PRAGMA_UNROLL(4)
0700 for (auto i = 0; i < 4; ++i) {
0701 if (!unplaced.IsDegenerated(i) && !unplaced.IsTwisted(i)) {
0702
0703 Real_v dn = unplaced.fSurf[i].DotPlaneNormal(direction);
0704 if (dn >= -kToleranceDist<Real_v>) continue;
0705
0706
0707
0708 Real_v face_limit = Min(best_local, lmax);
0709 best_local = Min(best_local, DistanceToSurf(unplaced, p0, direction, i, false, lmin, face_limit));
0710 }
0711 }
0712
0713 VECGEOM_PRAGMA_UNROLL(4)
0714 for (auto i = 0; i < 4; ++i) {
0715 if (!unplaced.IsDegenerated(i) && unplaced.IsTwisted(i)) {
0716
0717 if (!unplaced.fMesh[i].MayHit(p0, direction, false)) continue;
0718
0719
0720 Real_v face_limit = Min(best_local, lmax);
0721 best_local = Min(best_local, DistanceToSurf(unplaced, p0, direction, i, false, lmin, face_limit));
0722 }
0723 }
0724
0725
0726 distance = (best_local >= InfinityLength<Real_v>()) ? InfinityLength<Real_v>() : (t_approach + best_local);
0727 }
0728
0729
0730 template <typename Real_v>
0731 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::DistanceToOut(
0732 UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point, Vector3D<Real_v> const &direction,
0733 Real_v const & , Real_v &distance)
0734 {
0735 #ifndef VECCORE_CUDA
0736 if (unplaced.fTslHelper) {
0737 distance = unplaced.fTslHelper->DistanceToOut(point, direction);
0738 return;
0739 }
0740 #endif
0741
0742
0743
0744
0745 distance = Real_v(-1.);
0746 bool completelyinside, completelyoutside;
0747
0748 GenericKernelForContainsAndInside<Real_v, true>(unplaced, point, completelyinside, completelyoutside);
0749 if (completelyoutside) return;
0750
0751
0752 Real_v sign = (direction.z() < 0) ? Real_v(-1.) : Real_v(1.);
0753 Real_v limit = Real_v(1.);
0754 bool skipZ = Abs(direction.z()) * limit < kToleranceDist<Real_v>;
0755 distance = skipZ ? InfinityLength<Real_v>() : (sign * unplaced.fDz - point.z()) / NonZero(direction.z());
0756
0757
0758
0759 VECGEOM_PRAGMA_UNROLL(4)
0760 for (auto i = 0; i < 4; ++i) {
0761 if (!unplaced.IsDegenerated(i) && !unplaced.IsTwisted(i)) {
0762 distance = Min(distance, DistanceToSurf(unplaced, point, direction, i, true, Real_v(0), distance));
0763 }
0764 }
0765
0766 VECGEOM_PRAGMA_UNROLL(4)
0767 for (auto i = 0; i < 4; ++i) {
0768 if (!unplaced.IsDegenerated(i) && unplaced.IsTwisted(i)) {
0769 if (!unplaced.fMesh[i].MayHit(point, direction, true)) continue;
0770 distance = Min(distance, DistanceToSurf(unplaced, point, direction, i, true, Real_v(0), distance));
0771 }
0772 }
0773 }
0774
0775
0776 template <typename Real_v>
0777 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::SafetyToIn(UnplacedStruct_t const &unplaced,
0778 Vector3D<Real_v> const &point,
0779 Real_v &safety)
0780 {
0781 #ifndef VECCORE_CUDA
0782 if (unplaced.fTslHelper) {
0783 safety = unplaced.fTslHelper->SafetyToIn(point);
0784 return;
0785 }
0786 #endif
0787
0788 static_assert(vecCore::VectorSize<Real_v>() == 1);
0789
0790
0791 bool inside;
0792 BoxImplementation::Contains(BoxStruct<Precision>(unplaced.fBBdimensions), point - unplaced.fBBorigin, inside);
0793 if (!inside) {
0794
0795 BoxImplementation::SafetyToIn(BoxStruct<Precision>(unplaced.fBBdimensions), point - unplaced.fBBorigin, safety);
0796 return;
0797 }
0798
0799
0800 safety = Abs(point[2]) - unplaced.fDz;
0801 safety = SafetyArb4(unplaced, point, safety, false);
0802 }
0803
0804
0805 template <typename Real_v>
0806 VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::SafetyToOut(UnplacedStruct_t const &unplaced,
0807 Vector3D<Real_v> const &point, Real_v &safety)
0808 {
0809
0810 #ifndef VECCORE_CUDA
0811 if (unplaced.fTslHelper) {
0812 safety = unplaced.fTslHelper->SafetyToOut(point);
0813 return;
0814 }
0815 #endif
0816
0817
0818 static_assert(vecCore::VectorSize<Real_v>() == 1);
0819
0820
0821
0822
0823
0824
0825 safety = Abs(point[2]) - unplaced.fDz;
0826
0827
0828 if (safety > -kTolerance) {
0829 safety = Real_v(-1.);
0830 return;
0831 }
0832
0833
0834 safety = SafetyArb4(unplaced, point, safety, true);
0835 }
0836
0837
0838 template <typename Real_v, typename Bool_v>
0839 VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::NormalKernel(UnplacedStruct_t const &unplaced,
0840 Vector3D<Real_v> const &point,
0841 Vector3D<Real_v> &normal, Bool_v &valid)
0842 {
0843
0844
0845
0846
0847
0848
0849
0850 valid = Bool_v(true);
0851 normal.Set(0.);
0852
0853
0854 Real_v safz = Abs(unplaced.fDz - Abs(point.z()));
0855 if (safz < kTolerance) {
0856 normal[2] = Sign(point.z());
0857 return;
0858 }
0859
0860
0861 Vector2D<Real_v> vert[4];
0862 FillVerticesAtZ(unplaced, point.z(), vert);
0863 int iseg;
0864 GetClosestEdge<Real_v>(point, vert, iseg);
0865
0866 if (!unplaced.IsTwisted(iseg)) {
0867
0868 normal = unplaced.fSurf[iseg].GetPlaneNormal();
0869 return;
0870 }
0871
0872 Real_v u, v;
0873 UNormal(unplaced, point, iseg, normal, u, v);
0874 normal.Normalize();
0875
0876
0877 valid = (u > -kToleranceDist<Real_v>) && (u < 1. + kToleranceDist<Real_v>) && (v > -kToleranceDist<Real_v>) &&
0878 (v < 1. + kToleranceDist<Real_v>);
0879 }
0880
0881
0882 template <typename Real_v>
0883 VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::GetClosestEdge(Vector3D<Real_v> const &point,
0884 Vector2D<Real_v> const vertxy[4], int &iseg)
0885 {
0886
0887 iseg = 0;
0888 Real_v lsq, dx, dy, dpx, dpy, u;
0889 Real_v safe = InfinityLength<Real_v>();
0890 Real_v ssq = InfinityLength<Real_v>();
0891
0892 for (int i = 0; i < 4; ++i) {
0893 int j = (i + 1) % 4;
0894 dx = vertxy[j].x() - vertxy[i].x();
0895 dy = vertxy[j].y() - vertxy[i].y();
0896 dpx = point.x() - vertxy[i].x();
0897 dpy = point.y() - vertxy[i].y();
0898 lsq = dx * dx + dy * dy;
0899
0900
0901 if (lsq < kToleranceDistSquared<Real_v>) continue;
0902
0903
0904 u = (dpx * dx + dpy * dy);
0905 if (u > lsq) {
0906
0907 dpx = point.x() - vertxy[j].x();
0908 dpy = point.y() - vertxy[j].y();
0909 } else if (u >= 0) {
0910
0911 auto invlsq = Real_v(1.) / lsq;
0912 dpx -= u * dx * invlsq;
0913 dpy -= u * dy * invlsq;
0914 }
0915
0916 ssq = dpx * dpx + dpy * dpy;
0917 if (ssq < safe) {
0918 safe = ssq;
0919 iseg = i;
0920 }
0921 }
0922 }
0923
0924
0925 template <typename Real_v>
0926 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::UNormal(UnplacedStruct_t const &unplaced,
0927 Vector3D<Real_v> const &point, int i,
0928 Vector3D<Real_v> &unorm, Real_v &u,
0929 Real_v &v)
0930 {
0931
0932 auto uv = XYZtoUV(unplaced, point, i);
0933 u = uv[0];
0934 v = uv[1];
0935
0936
0937
0938 #if GENTRAP_USE_HYBRID_COEFFS
0939 const auto &E0 = unplaced.fE0[i];
0940 const auto &E1 = unplaced.fE1[i];
0941 const auto &G0 = unplaced.fG0[i];
0942 const auto &G1 = unplaced.fG1[i];
0943 auto dPdu = -(Real_v(1.) - v) * E0 - v * E1;
0944 auto dPdv = (Real_v(1.) - u) * G0 + u * G1;
0945 #else
0946 auto j = (i + 1) % 4;
0947
0948 auto const &A = unplaced.fVertices[i];
0949 auto const &C = unplaced.fVertices[j];
0950 auto const &B = unplaced.fVertices[i + 4];
0951 auto const &D = unplaced.fVertices[j + 4];
0952 auto dPdu = -(Real_v(1.) - v) * (C - A) - v * (D - B);
0953 auto dPdv = (Real_v(1.) - u) * (B - A) + u * (D - C);
0954 #endif
0955
0956
0957 unorm = dPdu.Cross(dPdv);
0958 }
0959
0960
0961 template <typename Real_v>
0962 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE bool GenTrapImplementation::InsideSection(Vector3D<Real_v> const &point,
0963 Vector3D<Real_v> const v[4])
0964 {
0965 bool inside = true;
0966 bool degen = true;
0967
0968
0969 for (int i = 0; i < 4; ++i) {
0970 const auto vij = v[(i + 1) % 4] - v[i];
0971 auto len2 = vij.Mag2();
0972 if (len2 < kToleranceDistSquared<Real_v>) continue;
0973 degen = false;
0974 auto cross = (point - v[i]).CrossZ(vij);
0975 inside = cross * cross >= kToleranceDistSquared<Real_v> * len2 ? (cross >= 0) : false;
0976 if (!inside) break;
0977 }
0978 if (degen) return false;
0979 return inside;
0980 }
0981
0982
0983 template <typename Real_v>
0984 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenTrapImplementation::FillVerticesAtZ(
0985 UnplacedStruct_t const &unplaced, Real_v z, Vector2D<Real_v> vertices[4])
0986 {
0987
0988 for (int i = 0; i < 4; i++)
0989 vertices[i] = unplaced.fMidXY[i] + unplaced.fT[i] * z;
0990 }
0991
0992
0993 template <typename Real_v>
0994 VECCORE_ATT_HOST_DEVICE Vector2D<Real_v> GenTrapImplementation::XYZtoUV(UnplacedStruct_t const &unplaced,
0995 Vector3D<Real_v> const &point, int i)
0996 {
0997
0998 Real_v v = unplaced.fDz2 * (point[2] + unplaced.fDz);
0999
1000
1001 #if GENTRAP_USE_HYBRID_COEFFS
1002 const auto &A = unplaced.fVertices[i];
1003 const auto &G0 = unplaced.fG0[i];
1004 const auto &E0 = unplaced.fE0[i];
1005 const auto &E1 = unplaced.fE1[i];
1006 auto E = A + v * G0;
1007 auto EF = (Real_v(1.) - v) * E0 + v * E1;
1008 #else
1009 auto j = (i + 1) % 4;
1010 auto E = (1. - v) * unplaced.fVertices[i] + v * unplaced.fVertices[i + 4];
1011 auto F = (1. - v) * unplaced.fVertices[j] + v * unplaced.fVertices[j + 4];
1012 auto EF = F - E;
1013 #endif
1014 auto EP = point - E;
1015
1016
1017 auto u = EP.Dot(EF) / NonZero(EF.Dot(EF));
1018 return Vector2D<Real_v>(u, v);
1019 }
1020
1021
1022 template <typename Real_v>
1023 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE bool GenTrapImplementation::InSurfLimits(UnplacedStruct_t const &unplaced,
1024 Vector3D<Real_v> const &point,
1025 int isurf)
1026 {
1027 auto uv = XYZtoUV(unplaced, point, isurf);
1028
1029
1030 bool inside = (uv[0] > -kToleranceDist<Real_v>) && (uv[0] < Real_v(1.) + kToleranceDist<Real_v>) &&
1031 (uv[1] > -kToleranceDist<Real_v>) && (uv[1] < Real_v(1.) + kToleranceDist<Real_v>);
1032 return inside;
1033 }
1034
1035
1036 template <typename Real_v>
1037 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Real_v GenTrapImplementation::SafetyArb4(UnplacedStruct_t const &unplaced,
1038 Vector3D<Real_v> const &point,
1039 Real_v safmax, bool inside)
1040 {
1041
1042 Real_v safety = safmax;
1043
1044
1045 VECGEOM_PRAGMA_UNROLL(4)
1046 for (int i = 0; i < 4; i++) {
1047 if (!unplaced.IsDegenerated(i) && !unplaced.IsTwisted(i)) {
1048
1049 Real_v sface = unplaced.fSurf[i].EvaluatePlanar(point);
1050 safety = Max(safety, sface);
1051 }
1052 }
1053
1054 VECGEOM_PRAGMA_UNROLL(4)
1055
1056
1057
1058 for (int i = 0; i < 4; i++) {
1059 if (!unplaced.IsDegenerated(i) && unplaced.IsTwisted(i)) {
1060
1061 if (!inside && unplaced.fSurf[i].Evaluate(point) <= Real_v(0)) continue;
1062 Real_v sface = unplaced.fSurf[i].SafetyLipschitz(point);
1063 safety = Max(safety, sface);
1064 }
1065 }
1066
1067
1068 return (inside) ? -safety : safety;
1069 }
1070
1071 }
1072 }
1073
1074 #endif