File indexing completed on 2025-01-18 10:14:05
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef VECGEOM_VOLUMES_KERNEL_TRDIMPLEMENTATION_H_
0010 #define VECGEOM_VOLUMES_KERNEL_TRDIMPLEMENTATION_H_
0011
0012 #include "VecGeom/base/Global.h"
0013 #include "VecGeom/volumes/kernel/GenericKernels.h"
0014 #include "VecGeom/volumes/TrdStruct.h"
0015 #include "VecGeom/volumes/kernel/shapetypes/TrdTypes.h"
0016 #include <stdlib.h>
0017 #include <cstdio>
0018
0019 namespace vecgeom {
0020
0021 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE(struct, TrdImplementation, typename);
0022
0023 inline namespace VECGEOM_IMPL_NAMESPACE {
0024
0025 namespace TrdUtilities {
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 template <typename Real_v>
0042 VECGEOM_FORCE_INLINE
0043 VECCORE_ATT_HOST_DEVICE
0044 void PointLineOrientation(Real_v const &px, Real_v const &py, Precision const &vx, Precision const &vy,
0045 Real_v &crossProduct)
0046 {
0047 crossProduct = vx * py - vy * px;
0048 }
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 template <typename Real_v>
0068 VECGEOM_FORCE_INLINE
0069 VECCORE_ATT_HOST_DEVICE
0070 void PlaneTrajectoryIntersection(Real_v const &alongX, Real_v const &alongY, Real_v const &ylimit, Real_v const &posx,
0071 Real_v const &posy, Real_v const &dirx, Real_v const &diry, Real_v &dist,
0072 vecCore::Mask_v<Real_v> &ok)
0073 {
0074 dist = (alongY * posx - alongX * posy) / (diry * alongX - dirx * alongY);
0075
0076 Real_v hity = posy + dist * diry;
0077 ok = vecCore::math::Abs(hity) <= ylimit && dist > 0;
0078 }
0079
0080 template <typename Real_v, bool forY, bool mirroredPoint, bool toInside>
0081 VECGEOM_FORCE_INLINE
0082 VECCORE_ATT_HOST_DEVICE
0083 void FaceTrajectoryIntersection(TrdStruct<Precision> const &trd, Vector3D<Real_v> const &pos,
0084 Vector3D<Real_v> const &dir, Real_v &dist, vecCore::Mask_v<Real_v> &ok)
0085 {
0086 Real_v alongV, posV, dirV, posK, dirK, fV, fK, halfKplus, v1, ndotv;
0087
0088
0089
0090
0091 if (forY) {
0092 alongV = trd.fY2minusY1;
0093 v1 = trd.fDY1;
0094 posV = pos.y();
0095 posK = pos.x();
0096 dirV = dir.y();
0097 dirK = dir.x();
0098 fK = trd.fFx;
0099 fV = trd.fFy;
0100 halfKplus = trd.fHalfX1plusX2;
0101 } else {
0102 alongV = trd.fX2minusX1;
0103 v1 = trd.fDX1;
0104 posV = pos.x();
0105 posK = pos.y();
0106 dirV = dir.x();
0107 dirK = dir.y();
0108 fK = trd.fFy;
0109 fV = trd.fFx;
0110 halfKplus = trd.fHalfY1plusY2;
0111 }
0112 if (mirroredPoint) {
0113 posV *= Real_v(-1.);
0114 dirV *= Real_v(-1.);
0115 }
0116
0117 ndotv = dirV + fV * dir.z();
0118 if (toInside)
0119 ok = ndotv < Real_v(0.);
0120 else
0121 ok = ndotv > Real_v(0.);
0122 if (vecCore::MaskEmpty(ok)) return;
0123 Real_v alongZ = Real_v(2.0) * trd.fDZ;
0124
0125
0126 dist = (alongZ * (posV - v1) - alongV * (pos.z() + trd.fDZ)) / (dir.z() * alongV - dirV * alongZ + kTiny);
0127 ok &= dist > Real_v(MakeMinusTolerant<true>(0.));
0128 if (!vecCore::MaskEmpty(ok)) {
0129
0130 Real_v hitz = pos.z() + dist * dir.z();
0131 ok &= vecCore::math::Abs(hitz) <= trd.fDZ;
0132
0133 Real_v hitk = posK + dist * dirK;
0134 Real_v dK = halfKplus - fK * hitz;
0135 ok &= vecCore::math::Abs(hitk) <= dK;
0136 vecCore::MaskedAssign(dist, ok & (vecCore::math::Abs(dist) < kHalfTolerance), Real_v(0.0));
0137 }
0138 }
0139
0140 template <typename Real_v, typename trdTypeT, bool inside>
0141 VECGEOM_FORCE_INLINE
0142 VECCORE_ATT_HOST_DEVICE
0143 void Safety(TrdStruct<Precision> const &trd, Vector3D<Real_v> const &pos, Real_v &dist)
0144 {
0145 using namespace TrdTypes;
0146 using Bool_v = vecCore::Mask_v<Real_v>;
0147
0148 Real_v safz = trd.fDZ - vecCore::math::Abs(pos.z());
0149
0150 dist = safz;
0151
0152 Real_v distx = trd.fHalfX1plusX2 - trd.fFx * pos.z();
0153 Bool_v okx = distx >= 0;
0154 Real_v safx = (distx - vecCore::math::Abs(pos.x())) * trd.fCalfX;
0155 vecCore::MaskedAssign(dist, okx && safx < dist, safx);
0156
0157
0158 if (checkVaryingY<trdTypeT>(trd)) {
0159 Real_v disty = trd.fHalfY1plusY2 - trd.fFy * pos.z();
0160 Bool_v oky = disty >= 0;
0161 Real_v safy = (disty - vecCore::math::Abs(pos.y())) * trd.fCalfY;
0162 vecCore::MaskedAssign(dist, oky && safy < dist, safy);
0163 } else {
0164 Real_v safy = trd.fDY1 - vecCore::math::Abs(pos.y());
0165 vecCore::MaskedAssign(dist, safy < dist, safy);
0166 }
0167 if (!inside) dist = -dist;
0168 }
0169
0170 template <typename Real_v, typename trdTypeT, bool surfaceT>
0171 VECGEOM_FORCE_INLINE
0172 VECCORE_ATT_HOST_DEVICE
0173 static void UnplacedInside(TrdStruct<Precision> const &trd, Vector3D<Real_v> const &point,
0174 vecCore::Mask_v<Real_v> &completelyinside, vecCore::Mask_v<Real_v> &completelyoutside)
0175 {
0176
0177 using namespace TrdUtilities;
0178 using namespace TrdTypes;
0179
0180 Real_v pzPlusDz = point.z() + trd.fDZ;
0181
0182
0183 completelyoutside = vecCore::math::Abs(point.z()) > MakePlusTolerant<surfaceT>(trd.fDZ);
0184 if (surfaceT) completelyinside = vecCore::math::Abs(point.z()) < MakeMinusTolerant<surfaceT>(trd.fDZ);
0185
0186
0187 Real_v cross;
0188
0189
0190 PointLineOrientation<Real_v>(vecCore::math::Abs(point.x()) - trd.fDX1, pzPlusDz, trd.fX2minusX1, 2.0 * trd.fDZ,
0191 cross);
0192 if (surfaceT) {
0193 completelyoutside |= cross < -trd.fToleranceX;
0194 completelyinside &= cross > trd.fToleranceX;
0195 } else {
0196 completelyoutside |= cross < 0;
0197 }
0198
0199
0200 if (HasVaryingY<trdTypeT>::value != TrdTypes::kNo) {
0201
0202 PointLineOrientation<Real_v>(vecCore::math::Abs(point.y()) - trd.fDY1, pzPlusDz, trd.fY2minusY1, 2.0 * trd.fDZ,
0203 cross);
0204 if (surfaceT) {
0205 completelyoutside |= cross < -trd.fToleranceY;
0206 completelyinside &= cross > trd.fToleranceY;
0207 } else {
0208 completelyoutside |= cross < 0;
0209 }
0210 } else {
0211 completelyoutside |= vecCore::math::Abs(point.y()) > MakePlusTolerant<surfaceT>(trd.fDY1);
0212 if (surfaceT) completelyinside &= vecCore::math::Abs(point.y()) < MakeMinusTolerant<surfaceT>(trd.fDY1);
0213 }
0214 }
0215
0216 }
0217
0218 template <typename T>
0219 class SPlacedTrd;
0220 template <typename T>
0221 class SUnplacedTrd;
0222
0223 template <typename T>
0224 struct TrdStruct;
0225
0226 template <typename trdTypeT>
0227 struct TrdImplementation {
0228
0229 using UnplacedStruct_t = TrdStruct<Precision>;
0230 using UnplacedVolume_t = SUnplacedTrd<trdTypeT>;
0231 using PlacedShape_t = SPlacedTrd<UnplacedVolume_t>;
0232
0233 VECCORE_ATT_HOST_DEVICE
0234 static void PrintType() {}
0235
0236 template <typename Stream>
0237 static void PrintType(Stream &s, int transCodeT = translation::kGeneric, int rotCodeT = rotation::kGeneric)
0238 {
0239 s << "SpecializedTrd<" << transCodeT << "," << rotCodeT << ">";
0240 }
0241
0242 template <typename Stream>
0243 static void PrintImplementationType(Stream & )
0244 {
0245 }
0246
0247 template <typename Stream>
0248 static void PrintUnplacedType(Stream & )
0249 {
0250 }
0251
0252 template <typename Real_v, typename Bool_v>
0253 VECGEOM_FORCE_INLINE
0254 VECCORE_ATT_HOST_DEVICE
0255 static void UnplacedContains(UnplacedStruct_t const &trd, Vector3D<Real_v> const &point, Bool_v &inside)
0256 {
0257
0258 Bool_v unused;
0259 TrdUtilities::UnplacedInside<Real_v, trdTypeT, false>(trd, point, unused, inside);
0260 inside = !inside;
0261 }
0262
0263 template <typename Real_v, typename Bool_v>
0264 VECGEOM_FORCE_INLINE
0265 VECCORE_ATT_HOST_DEVICE
0266 static void Contains(UnplacedStruct_t const &trd, Vector3D<Real_v> const &point, Bool_v &inside)
0267 {
0268
0269 Bool_v unused;
0270 TrdUtilities::UnplacedInside<Real_v, trdTypeT, false>(trd, point, unused, inside);
0271 inside = !inside;
0272 }
0273
0274 template <typename Real_v, typename Inside_v>
0275 VECGEOM_FORCE_INLINE
0276 VECCORE_ATT_HOST_DEVICE
0277 static void Inside(UnplacedStruct_t const &trd, Vector3D<Real_v> const &point, Inside_v &inside)
0278 {
0279
0280 using Bool_v = vecCore::Mask_v<Real_v>;
0281 const Real_v in(EInside::kInside);
0282 const Real_v out(EInside::kOutside);
0283 Bool_v inmask = Bool_v(false);
0284 Bool_v outmask = Bool_v(false);
0285 Real_v result(EInside::kSurface);
0286
0287 TrdUtilities::UnplacedInside<Real_v, trdTypeT, true>(trd, point, inmask, outmask);
0288
0289 vecCore::MaskedAssign(result, inmask, in);
0290 vecCore::MaskedAssign(result, outmask, out);
0291
0292
0293
0294
0295
0296 for (size_t i = 0; i < vecCore::VectorSize(result); i++)
0297 vecCore::Set(inside, i, vecCore::Get(result, i));
0298 }
0299
0300 template <typename Real_v>
0301 VECGEOM_FORCE_INLINE
0302 VECCORE_ATT_HOST_DEVICE
0303 static void DistanceToIn(UnplacedStruct_t const &trd, Vector3D<Real_v> const &point,
0304 Vector3D<Real_v> const &direction, Real_v const & , Real_v &distance)
0305 {
0306
0307 using namespace TrdUtilities;
0308 using namespace TrdTypes;
0309 using Bool_v = vecCore::Mask_v<Real_v>;
0310
0311 Real_v hitx, hity;
0312
0313
0314 Vector3D<Real_v> pos_local;
0315 Vector3D<Real_v> dir_local;
0316 distance = InfinityLength<Real_v>();
0317
0318
0319 Bool_v inz = vecCore::math::Abs(point.z()) < Real_v(MakeMinusTolerant<true>(trd.fDZ));
0320 Real_v distx = trd.fHalfX1plusX2 - trd.fFx * point.z();
0321 Bool_v inx = (distx - vecCore::math::Abs(point.x())) * trd.fCalfX > Real_v(MakePlusTolerant<true>(0.));
0322 Real_v disty;
0323 Bool_v iny;
0324 if (checkVaryingY<trdTypeT>(trd)) {
0325 disty = trd.fHalfY1plusY2 - trd.fFy * point.z();
0326 iny = (disty - vecCore::math::Abs(point.y())) * trd.fCalfY > Real_v(MakePlusTolerant<true>(0.));
0327 } else {
0328 disty = vecCore::math::Abs(point.y()) - trd.fDY1;
0329 iny = disty < Real_v(MakeMinusTolerant<true>(0.));
0330 }
0331 Bool_v inside = inx & iny & inz;
0332 vecCore__MaskedAssignFunc(distance, inside, Real_v(-1.));
0333 Bool_v done = inside;
0334 Bool_v okz = point.z() * direction.z() < Real_v(0.);
0335 okz &= !inz;
0336 if (!vecCore::MaskEmpty(okz)) {
0337 Real_v distz = (vecCore::math::Abs(point.z()) - trd.fDZ) / vecCore::math::Abs(direction.z());
0338
0339 hitx = vecCore::math::Abs(point.x() + distz * direction.x());
0340 hity = vecCore::math::Abs(point.y() + distz * direction.y());
0341
0342
0343 Bool_v okzt = point.z() > (trd.fDZ - kHalfTolerance) && hitx <= trd.fDX2 && hity <= trd.fDY2;
0344
0345 Bool_v okzb = point.z() < (-trd.fDZ + kHalfTolerance) && hitx <= trd.fDX1 && hity <= trd.fDY1;
0346
0347 okz &= (okzt | okzb);
0348 vecCore::MaskedAssign(distance, okz, distz);
0349 }
0350 done |= okz;
0351 if (vecCore::MaskFull(done)) {
0352 vecCore::MaskedAssign(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0353 return;
0354 }
0355
0356
0357 Bool_v okx = Bool_v(false);
0358 if (!vecCore::MaskFull(inx)) {
0359
0360 FaceTrajectoryIntersection<Real_v, false, false, true>(trd, point, direction, distx, okx);
0361 vecCore::MaskedAssign(distance, okx, distx);
0362
0363 FaceTrajectoryIntersection<Real_v, false, true, true>(trd, point, direction, distx, okx);
0364 vecCore::MaskedAssign(distance, okx, distx);
0365 }
0366 done |= okx;
0367 if (vecCore::MaskFull(done)) {
0368 vecCore::MaskedAssign(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0369 return;
0370 }
0371
0372
0373 Bool_v oky;
0374 if (checkVaryingY<trdTypeT>(trd)) {
0375 if (!vecCore::MaskFull(iny)) {
0376 FaceTrajectoryIntersection<Real_v, true, false, true>(trd, point, direction, disty, oky);
0377 vecCore::MaskedAssign(distance, oky, disty);
0378
0379 FaceTrajectoryIntersection<Real_v, true, true, true>(trd, point, direction, disty, oky);
0380 vecCore::MaskedAssign(distance, oky, disty);
0381 }
0382 } else {
0383 if (!vecCore::MaskFull(iny)) {
0384 disty /= vecCore::math::Abs(direction.y());
0385 Real_v zhit = point.z() + disty * direction.z();
0386 Real_v xhit = point.x() + disty * direction.x();
0387 Real_v dx = trd.fHalfX1plusX2 - trd.fFx * zhit;
0388 oky = point.y() * direction.y() < 0 && disty > -kHalfTolerance && vecCore::math::Abs(xhit) < dx &&
0389 vecCore::math::Abs(zhit) < trd.fDZ;
0390 vecCore::MaskedAssign(distance, oky, disty);
0391 }
0392 }
0393 vecCore::MaskedAssign(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0394 }
0395
0396 template <typename Real_v>
0397 VECGEOM_FORCE_INLINE
0398 VECCORE_ATT_HOST_DEVICE
0399 static void DistanceToOut(UnplacedStruct_t const &trd, Vector3D<Real_v> const &point, Vector3D<Real_v> const &dir,
0400 Real_v const & , Real_v &distance)
0401 {
0402
0403 using namespace TrdUtilities;
0404 using namespace TrdTypes;
0405 using Bool_v = vecCore::Mask_v<Real_v>;
0406
0407 Real_v hitx, hity;
0408
0409 distance = Real_v(0.0);
0410
0411
0412 Real_v invdir = Real_v(1.) / vecCore::math::Abs(dir.z() + kTiny);
0413 Real_v safz = trd.fDZ - vecCore::math::Abs(point.z());
0414 Bool_v out = safz < Real_v(MakeMinusTolerant<true>(0.));
0415 Real_v distx = trd.fHalfX1plusX2 - trd.fFx * point.z();
0416 out |= (distx - vecCore::math::Abs(point.x())) * trd.fCalfX < Real_v(MakeMinusTolerant<true>(0.));
0417 Real_v disty;
0418 if (checkVaryingY<trdTypeT>(trd)) {
0419 disty = trd.fHalfY1plusY2 - trd.fFy * point.z();
0420 out |= (disty - vecCore::math::Abs(point.y())) * trd.fCalfY < Real_v(MakeMinusTolerant<true>(0.));
0421 } else {
0422 disty = trd.fDY1 - vecCore::math::Abs(point.y());
0423 out |= disty < Real_v(MakeMinusTolerant<true>(0.));
0424 }
0425 if ( vecCore::MaskFull(out)) {
0426 distance = Real_v(-1.);
0427 return;
0428 }
0429 Bool_v okzt = dir.z() > Real_v(0.);
0430 if (!vecCore::MaskEmpty(okzt)) {
0431 Real_v distz = (trd.fDZ - point.z()) * invdir;
0432 hitx = vecCore::math::Abs(point.x() + distz * dir.x());
0433 hity = vecCore::math::Abs(point.y() + distz * dir.y());
0434 okzt &= hitx <= trd.fDX2 && hity <= trd.fDY2;
0435 vecCore::MaskedAssign(distance, okzt, distz);
0436 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(okzt)) {
0437 vecCore::MaskedAssign(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0438 return;
0439 }
0440 }
0441
0442
0443 Bool_v okzb = dir.z() < Real_v(0.);
0444 if (!vecCore::MaskEmpty(okzb)) {
0445 Real_v distz = (point.z() + trd.fDZ) * invdir;
0446 hitx = vecCore::math::Abs(point.x() + distz * dir.x());
0447 hity = vecCore::math::Abs(point.y() + distz * dir.y());
0448 okzb &= hitx <= trd.fDX1 && hity <= trd.fDY1;
0449 vecCore::MaskedAssign(distance, okzb, distz);
0450 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(okzb)) {
0451 vecCore::MaskedAssign(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0452 return;
0453 }
0454 }
0455
0456
0457 Bool_v okx;
0458
0459 FaceTrajectoryIntersection<Real_v, false, false, false>(trd, point, dir, distx, okx);
0460
0461 vecCore::MaskedAssign(distance, okx, distx);
0462 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(okx)) {
0463 vecCore::MaskedAssign(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0464 return;
0465 }
0466
0467 FaceTrajectoryIntersection<Real_v, false, true, false>(trd, point, dir, distx, okx);
0468 vecCore::MaskedAssign(distance, okx, distx);
0469 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(okx)) {
0470 vecCore::MaskedAssign(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0471 return;
0472 }
0473
0474
0475 Bool_v oky;
0476
0477 if (checkVaryingY<trdTypeT>(trd)) {
0478 FaceTrajectoryIntersection<Real_v, true, false, false>(trd, point, dir, disty, oky);
0479 vecCore::MaskedAssign(distance, oky, disty);
0480 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(oky)) {
0481 vecCore::MaskedAssign(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0482 return;
0483 }
0484
0485 FaceTrajectoryIntersection<Real_v, true, true, false>(trd, point, dir, disty, oky);
0486 vecCore::MaskedAssign(distance, oky, disty);
0487 } else {
0488 Real_v plane = trd.fDY1;
0489 vecCore__MaskedAssignFunc(plane, dir.y() < Real_v(0.), Real_v(-trd.fDY1));
0490 disty = (plane - point.y()) / dir.y();
0491 Real_v zhit = point.z() + disty * dir.z();
0492 Real_v xhit = point.x() + disty * dir.x();
0493 Real_v dx = trd.fHalfX1plusX2 - trd.fFx * zhit;
0494 oky = vecCore::math::Abs(xhit) < dx && vecCore::math::Abs(zhit) < trd.fDZ;
0495 vecCore::MaskedAssign(distance, oky, disty);
0496 }
0497 vecCore__MaskedAssignFunc(distance, vecCore::math::Abs(distance) < kHalfTolerance, Real_v(0.0));
0498 vecCore__MaskedAssignFunc(distance, out, Real_v(-1.0));
0499 }
0500
0501 template <typename Real_v>
0502 VECGEOM_FORCE_INLINE
0503 VECCORE_ATT_HOST_DEVICE
0504 static void SafetyToIn(UnplacedStruct_t const &trd, Vector3D<Real_v> const &point, Real_v &safety)
0505 {
0506 using namespace TrdUtilities;
0507 Safety<Real_v, trdTypeT, false>(trd, point, safety);
0508 }
0509
0510 template <typename Real_v>
0511 VECGEOM_FORCE_INLINE
0512 VECCORE_ATT_HOST_DEVICE
0513 static void SafetyToOut(UnplacedStruct_t const &trd, Vector3D<Real_v> const &point, Real_v &safety)
0514 {
0515 using namespace TrdUtilities;
0516 Safety<Real_v, trdTypeT, true>(trd, point, safety);
0517 }
0518 };
0519 }
0520 }
0521
0522 #endif