File indexing completed on 2025-01-18 10:14:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef VECGEOM_VOLUMES_KERNEL_POLYCONEIMPLEMENTATION_H_
0013 #define VECGEOM_VOLUMES_KERNEL_POLYCONEIMPLEMENTATION_H_
0014
0015 #include "VecGeom/base/Vector3D.h"
0016 #include "VecGeom/volumes/PolyconeStruct.h"
0017 #include "VecGeom/volumes/kernel/GenericKernels.h"
0018 #include <VecCore/VecCore>
0019 #include "VecGeom/volumes/kernel/ConeImplementation.h"
0020 #include "VecGeom/volumes/kernel/shapetypes/ConeTypes.h"
0021
0022 #include <cstdio>
0023
0024 namespace vecgeom {
0025
0026 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE(struct, PolyconeImplementation, typename);
0027
0028 inline namespace VECGEOM_IMPL_NAMESPACE {
0029
0030 template <typename T>
0031 class SPlacedPolycone;
0032 template <typename T>
0033 class SUnplacedPolycone;
0034
0035 template <typename polyconeTypeT>
0036 struct PolyconeImplementation {
0037
0038 using UnplacedStruct_t = PolyconeStruct<Precision>;
0039 using UnplacedVolume_t = SUnplacedPolycone<polyconeTypeT>;
0040 using PlacedShape_t = SPlacedPolycone<UnplacedVolume_t>;
0041
0042 VECCORE_ATT_HOST_DEVICE
0043 static void PrintType()
0044 {
0045
0046 }
0047
0048 template <typename Stream>
0049 static void PrintType(Stream &st, int transCodeT = translation::kGeneric, int rotCodeT = rotation::kGeneric)
0050 {
0051 st << "SpecializedPolycone<" << transCodeT << "," << rotCodeT << ">";
0052 }
0053
0054 template <typename Stream>
0055 static void PrintImplementationType(Stream &st)
0056 {
0057 (void)st;
0058
0059 }
0060
0061 template <typename Stream>
0062 static void PrintUnplacedType(Stream &st)
0063 {
0064 (void)st;
0065
0066
0067 }
0068
0069 template <typename Real_v, bool ForInside>
0070 VECGEOM_FORCE_INLINE
0071 VECCORE_ATT_HOST_DEVICE
0072 static void GenericKernelForASection(UnplacedStruct_t const &unplaced, int isect,
0073 Vector3D<Real_v> const &polyconePoint,
0074 typename vecCore::Mask_v<Real_v> &secFullyInside,
0075 typename vecCore::Mask_v<Real_v> &secFullyOutside)
0076 {
0077
0078
0079 using namespace ConeTypes;
0080
0081 if (isect < 0) {
0082 secFullyInside = false;
0083 secFullyOutside = true;
0084 return;
0085 }
0086
0087 PolyconeSection const &sec = unplaced.GetSection(isect);
0088 Vector3D<Precision> secLocalp = polyconePoint - Vector3D<Precision>(0, 0, sec.fShift);
0089 #ifdef POLYCONEDEBUG
0090 std::cout << " isect=" << isect << "/" << unplaced.GetNSections() << " secLocalP=" << secLocalp
0091 << ", secShift=" << sec.fShift << " sec.fSolid=" << sec.fSolid << std::endl;
0092 if (sec.fSolid) sec.fSolid->Print();
0093 #endif
0094
0095 ConeHelpers<Real_v, polyconeTypeT>::template GenericKernelForContainsAndInside<ForInside>(
0096 *sec.fSolid, secLocalp, secFullyInside, secFullyOutside);
0097 }
0098
0099 template <typename Real_v, typename Bool_v>
0100 VECGEOM_FORCE_INLINE
0101 VECCORE_ATT_HOST_DEVICE
0102 static void Contains(UnplacedStruct_t const &polycone, Vector3D<Real_v> const &point, Bool_v &inside)
0103 {
0104
0105 Bool_v unused(false), outside(false);
0106 GenericKernelForContainsAndInside<Real_v, Bool_v, false>(polycone, point, unused, outside);
0107 inside = !outside;
0108 }
0109
0110
0111
0112 template <typename Real_v, typename Inside_t>
0113 VECGEOM_FORCE_INLINE
0114 VECCORE_ATT_HOST_DEVICE
0115 static void Inside(UnplacedStruct_t const &polycone, Vector3D<Real_v> const &point, Inside_t &inside)
0116 {
0117
0118 using Bool_v = vecCore::Mask_v<Real_v>;
0119 using InsideBool_v = vecCore::Mask_v<Inside_t>;
0120 Bool_v completelyinside(false), completelyoutside(false);
0121 GenericKernelForContainsAndInside<Real_v, Bool_v, true>(polycone, point, completelyinside, completelyoutside);
0122 inside = EInside::kSurface;
0123 vecCore::MaskedAssign(inside, (InsideBool_v)completelyoutside, Inside_t(EInside::kOutside));
0124 vecCore::MaskedAssign(inside, (InsideBool_v)completelyinside, Inside_t(EInside::kInside));
0125 }
0126
0127 template <typename Real_v, typename Bool_v, bool ForInside>
0128 VECGEOM_FORCE_INLINE
0129 VECCORE_ATT_HOST_DEVICE
0130 static void GenericKernelForContainsAndInside(UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &localPoint,
0131 Bool_v &completelyInside, Bool_v &completelyOutside)
0132 {
0133
0134 typedef Bool_v Bool_t;
0135
0136 int indexLow = unplaced.GetSectionIndex(localPoint.z() - kTolerance);
0137 int indexHigh = unplaced.GetSectionIndex(localPoint.z() + kTolerance);
0138 if (indexLow < 0 && indexHigh < 0) {
0139 completelyOutside = true;
0140 return;
0141 }
0142 if (indexLow < 0 && indexHigh == 0) {
0143
0144 GenericKernelForASection<Real_v, ForInside>(unplaced, 0, localPoint, completelyInside, completelyOutside);
0145 return;
0146 }
0147 if (indexHigh < 0 && indexLow == (unplaced.GetNSections() - 1)) {
0148
0149 GenericKernelForASection<Real_v, ForInside>(unplaced, (unplaced.GetNSections() - 1), localPoint, completelyInside,
0150 completelyOutside);
0151
0152 return;
0153 }
0154 if (indexLow >= 0 && indexHigh >= 0) {
0155 if (indexLow == indexHigh) {
0156
0157 GenericKernelForASection<Real_v, ForInside>(unplaced, indexLow, localPoint, completelyInside,
0158 completelyOutside);
0159
0160 return;
0161 } else {
0162
0163 Bool_t secInLow = false, secOutLow = false;
0164 Bool_t secInHigh = false, secOutHigh = false;
0165 GenericKernelForASection<Real_v, ForInside>(unplaced, indexLow, localPoint, secInLow, secOutLow);
0166 GenericKernelForASection<Real_v, ForInside>(unplaced, indexHigh, localPoint, secInHigh, secOutHigh);
0167 Bool_t surfLow = !secInLow && !secOutLow;
0168 Bool_t surfHigh = !secInHigh && !secOutHigh;
0169
0170 if (surfLow && surfHigh) {
0171 completelyInside = true;
0172 return;
0173 } else {
0174
0175
0176
0177
0178
0179
0180 if (secOutLow && secOutHigh) {
0181 completelyOutside = true;
0182 return;
0183 }
0184 }
0185 }
0186 }
0187 }
0188
0189 template <typename Real_v>
0190 VECGEOM_FORCE_INLINE
0191 VECCORE_ATT_HOST_DEVICE
0192 static void DistanceToIn(UnplacedStruct_t const &polycone, Vector3D<Real_v> const &point,
0193 Vector3D<Real_v> const &direction, Real_v const &stepMax, Real_v &distance)
0194 {
0195
0196 Vector3D<Real_v> p = point;
0197 Vector3D<Real_v> v = direction;
0198
0199 #ifdef POLYCONEDEBUG
0200 std::cout << "Polycone::DistToIn() (spot 1): point=" << point << ", dir=" << direction << ", localPoint=" << p
0201 << ", localDir=" << v << "\n";
0202 #endif
0203
0204
0205
0206 distance = kInfLength;
0207 int increment = (v.z() > 0) ? 1 : -1;
0208 if (std::fabs(v.z()) < kTolerance) increment = 0;
0209 int index = polycone.GetSectionIndex(p.z());
0210 if (index == -1) index = 0;
0211 if (index == -2) index = polycone.GetNSections() - 1;
0212
0213 do {
0214
0215 PolyconeSection const &sec = polycone.GetSection(index);
0216
0217 #ifdef POLYCONEDEBUG
0218 std::cout << "Polycone::DistToIn() (spot 2):"
0219 << " index=" << index << " NSec=" << polycone.GetNSections() << " &sec=" << &sec << " - secPars:"
0220 << " secOffset=" << sec.fShift << " Dz=" << sec.fSolid->GetDz() << " Rmin1=" << sec.fSolid->GetRmin1()
0221 << " Rmin2=" << sec.fSolid->GetRmin2() << " Rmax1=" << sec.fSolid->GetRmax1()
0222 << " Rmax2=" << sec.fSolid->GetRmax2() << " -- calling Cone::DistToIn()...\n";
0223 #endif
0224
0225 ConeImplementation<polyconeTypeT>::template DistanceToIn<Real_v>(
0226 *sec.fSolid, p - Vector3D<Precision>(0, 0, sec.fShift), v, stepMax, distance);
0227
0228 #ifdef POLYCONEDEBUG
0229 std::cout << "Polycone::DistToIn() (spot 3):"
0230 << " distToIn() = " << distance << "\n";
0231 #endif
0232
0233 if (distance < kInfLength || !increment) break;
0234 index += increment;
0235 } while (index >= 0 && index < polycone.GetNSections());
0236 return;
0237 }
0238
0239 template <typename Real_v>
0240 VECGEOM_FORCE_INLINE
0241 VECCORE_ATT_HOST_DEVICE
0242 static void DistanceToOut(UnplacedStruct_t const &polycone, Vector3D<Real_v> const &point,
0243 Vector3D<Real_v> const &dir, Real_v const &stepMax, Real_v &distance)
0244 {
0245
0246 distance = kInfLength;
0247 Vector3D<Real_v> pn = point;
0248
0249
0250 if (polycone.GetNSections() == 1) {
0251 const PolyconeSection §ion = polycone.GetSection(0);
0252
0253 ConeImplementation<polyconeTypeT>::template DistanceToOut<Real_v>(
0254 *section.fSolid, point - Vector3D<Precision>(0, 0, section.fShift), dir, stepMax, distance);
0255
0256 return;
0257 }
0258
0259 int indexLow = polycone.GetSectionIndex(point.z() - kTolerance);
0260 int indexHigh = polycone.GetSectionIndex(point.z() + kTolerance);
0261 int index = 0;
0262
0263
0264
0265
0266 if (indexLow < 0 && indexHigh < 0) {
0267 distance = -1;
0268 return;
0269 } else if (indexLow < 0 && indexHigh >= 0) {
0270 index = indexHigh;
0271 const PolyconeSection §ion = polycone.GetSection(index);
0272
0273 Inside_t inside;
0274
0275
0276 ConeImplementation<polyconeTypeT>::template Inside<Real_v>(
0277 *section.fSolid, point - Vector3D<Precision>(0, 0, section.fShift), inside);
0278 if (inside == EInside::kOutside) {
0279 distance = -1;
0280 return;
0281 }
0282 } else if (indexLow != indexHigh && (indexLow >= 0)) {
0283
0284 const PolyconeSection §ion = polycone.GetSection(indexLow);
0285
0286 Inside_t inside;
0287
0288
0289
0290 ConeImplementation<polyconeTypeT>::template Inside<Real_v>(
0291 *section.fSolid, point - Vector3D<Precision>(0, 0, section.fShift), inside);
0292
0293 if (inside == EInside::kOutside) {
0294 index = indexHigh;
0295 } else {
0296 index = indexLow;
0297 }
0298 } else {
0299 index = indexLow;
0300 if (index < 0) index = polycone.GetSectionIndex(point.z());
0301 }
0302 if (index < 0) {
0303 distance = 0.;
0304 return;
0305 }
0306
0307 else {
0308 const PolyconeSection §ion = polycone.GetSection(index);
0309
0310 Inside_t inside;
0311
0312
0313 ConeImplementation<polyconeTypeT>::template Inside<Real_v>(
0314 *section.fSolid, point - Vector3D<Precision>(0, 0, section.fShift), inside);
0315 if (inside == EInside::kOutside) {
0316 distance = -1;
0317 return;
0318 }
0319 }
0320
0321 Precision totalDistance = 0.;
0322 Precision dist;
0323 int increment = (dir.z() > 0) ? 1 : -1;
0324 if (std::fabs(dir.z()) < kTolerance) increment = 0;
0325
0326
0327 int istep = 0;
0328 do {
0329 const PolyconeSection §ion = polycone.GetSection(index);
0330
0331 if ((totalDistance != 0) || (istep < 2)) {
0332 pn = point + totalDistance * dir;
0333 pn.z() -= section.fShift;
0334 Inside_t inside;
0335
0336 ConeImplementation<polyconeTypeT>::template Inside<Real_v>(*section.fSolid, pn, inside);
0337
0338 if (inside == EInside::kOutside) {
0339 break;
0340 }
0341 } else
0342 pn.z() -= section.fShift;
0343
0344 istep++;
0345
0346
0347 ConeImplementation<polyconeTypeT>::template DistanceToOut<Real_v>(*section.fSolid, pn, dir, stepMax, dist);
0348 if (dist == -1) return;
0349
0350
0351 if (std::fabs(dist) < 0.5 * kTolerance) {
0352 int index1 = index;
0353 if ((index > 0) && (index < polycone.GetNSections() - 1)) {
0354 index1 += increment;
0355 } else {
0356 if ((index == 0) && (increment > 0)) index1 += increment;
0357 if ((index == polycone.GetNSections() - 1) && (increment < 0)) index1 += increment;
0358 }
0359
0360 Vector3D<Precision> pte = point + (totalDistance + dist) * dir;
0361 const PolyconeSection §ion1 = polycone.GetSection(index1);
0362 pte.z() -= section1.fShift;
0363 Vector3D<Precision> localp;
0364 Inside_t inside22;
0365
0366 ConeImplementation<polyconeTypeT>::template Inside<Real_v>(*section1.fSolid, pte, inside22);
0367 if (inside22 == 3 || (increment == 0)) {
0368 break;
0369 }
0370 }
0371
0372 totalDistance += dist;
0373 index += increment;
0374 } while (increment != 0 && index >= 0 && index < polycone.GetNSections());
0375
0376 distance = totalDistance;
0377
0378 return;
0379 }
0380
0381 template <typename Real_v>
0382 VECGEOM_FORCE_INLINE
0383 VECCORE_ATT_HOST_DEVICE
0384 static void SafetyToIn(UnplacedStruct_t const &polycone, Vector3D<Real_v> const &point, Real_v &safety)
0385 {
0386
0387 Vector3D<Real_v> p = point;
0388 int index = polycone.GetSectionIndex(p.z());
0389
0390 bool needZ = false;
0391 if (index < 0) {
0392 needZ = true;
0393 if (index == -1) index = 0;
0394 if (index == -2) index = polycone.GetNSections() - 1;
0395 }
0396 Precision minSafety = 0;
0397 PolyconeSection const &sec = polycone.GetSection(index);
0398
0399 if (needZ) {
0400
0401
0402 ConeImplementation<polyconeTypeT>::template SafetyToIn<Real_v>(*sec.fSolid,
0403 p - Vector3D<Precision>(0, 0, sec.fShift), safety);
0404 } else {
0405
0406
0407
0408 ConeImplementation<polyconeTypeT>::template SafetyToIn<Real_v>(*sec.fSolid,
0409 p - Vector3D<Precision>(0, 0, sec.fShift), safety);
0410
0411 if (safety < kTolerance) return;
0412 minSafety = safety;
0413 Precision zbase = polycone.fZs[index + 1];
0414
0415 for (int i = index + 1; i < polycone.GetNSections(); ++i) {
0416 Precision dz = polycone.fZs[i] - zbase;
0417 if (dz >= minSafety) break;
0418
0419 PolyconeSection const § = polycone.GetSection(i);
0420
0421
0422
0423
0424 ConeImplementation<polyconeTypeT>::template SafetyToIn<Real_v>(
0425 *sect.fSolid, p - Vector3D<Precision>(0, 0, sect.fShift), safety);
0426
0427 if (safety < minSafety) minSafety = safety;
0428 }
0429
0430
0431 if (index > 0) {
0432 zbase = polycone.fZs[index - 1];
0433 for (int i = index - 1; i >= 0; --i) {
0434 Precision dz = zbase - polycone.fZs[i];
0435 if (dz >= minSafety) break;
0436 PolyconeSection const § = polycone.GetSection(i);
0437
0438
0439
0440
0441 ConeImplementation<polyconeTypeT>::template SafetyToIn<Real_v>(
0442 *sect.fSolid, p - Vector3D<Precision>(0, 0, sect.fShift), safety);
0443
0444 if (safety < minSafety) minSafety = safety;
0445 }
0446 }
0447 safety = minSafety;
0448 }
0449 return;
0450 }
0451
0452 template <typename Real_v>
0453 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Real_v DistanceToSeg(Vector3D<Real_v> const &point,
0454 Vector3D<Precision> segment_start,
0455 Vector3D<Precision> segment_end)
0456 {
0457 Vector3D<Real_v> segment_vector = segment_end - segment_start;
0458 Vector3D<Real_v> point_vector = point - segment_start;
0459 Real_v projection_scalar = point_vector.Dot(segment_vector) / segment_vector.Mag2();
0460 Vector3D<Real_v> projection_point = segment_start + projection_scalar * segment_vector;
0461 vecCore__MaskedAssignFunc(projection_point, projection_scalar < Real_v(0.), Vector3D<Real_v>(segment_start));
0462 vecCore__MaskedAssignFunc(projection_point, projection_scalar > Real_v(1.), Vector3D<Real_v>(segment_end));
0463 Vector3D<Real_v> distVec = point - projection_point;
0464 return distVec.Mag();
0465 }
0466
0467
0468
0469
0470 template <typename Real_v>
0471 VECGEOM_FORCE_INLINE
0472 VECCORE_ATT_HOST_DEVICE
0473 static void SafetyToOut(UnplacedStruct_t const &polycone, Vector3D<Real_v> const &point, Real_v &safety)
0474 {
0475 typedef typename vecCore::Mask_v<Real_v> Bool_v;
0476 safety = Real_v(kInfLength);
0477 Bool_v compIn(false), compOut(false), done(false);
0478 GenericKernelForContainsAndInside<Real_v, Bool_v, true>(polycone, point, compIn, compOut);
0479 vecCore__MaskedAssignFunc(safety, compOut && !done, Real_v(-1.));
0480 done |= compOut;
0481 if (vecCore::MaskFull(done)) return;
0482
0483 Vector3D<Real_v> twoDPoint = Vector3D<Real_v>(point.Perp(), point.z(), 0.);
0484 for (unsigned int currSegIndex = 0; currSegIndex < polycone.fTwoDVec.size(); currSegIndex++) {
0485 unsigned int nextSegIndex = currSegIndex + 1;
0486 if (currSegIndex == polycone.fTwoDVec.size() - 1) {
0487 nextSegIndex = 0;
0488 }
0489
0490 Real_v distance(kInfLength);
0491 if ((polycone.fTwoDVec[currSegIndex].x() == 0 && polycone.fTwoDVec[nextSegIndex].x() == 0) ||
0492 (polycone.fTwoDVec[currSegIndex].x() == polycone.fTwoDVec[nextSegIndex].x() &&
0493 polycone.fTwoDVec[currSegIndex].y() == polycone.fTwoDVec[nextSegIndex].y()))
0494 distance = Real_v(kInfLength);
0495 else
0496 distance = DistanceToSeg(twoDPoint, polycone.fTwoDVec[currSegIndex], polycone.fTwoDVec[nextSegIndex]);
0497
0498 vecCore__MaskedAssignFunc(safety, (distance < safety) && !done, distance);
0499 }
0500
0501 if (polycone.fDeltaPhi < 2 * kPi) {
0502 Real_v safetyPhi = polycone.fPhiWedge.SafetyToOut<Real_v>(point);
0503 vecCore__MaskedAssignFunc(safety, safetyPhi < safety, safetyPhi);
0504 }
0505 }
0506
0507 #if (0)
0508
0509 template <typename Real_v>
0510 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToOut_Old(UnplacedStruct_t const &polycone,
0511 Vector3D<Real_v> const &point,
0512 Real_v &safety)
0513 {
0514 typedef typename vecCore::Mask_v<Real_v> Bool_v;
0515 Bool_v compIn(false), compOut(false);
0516 GenericKernelForContainsAndInside<Real_v, Bool_v, true>(polycone, point, compIn, compOut);
0517 if (compOut) {
0518 safety = -1;
0519 return;
0520 }
0521
0522 int index = polycone.GetSectionIndex(point.z());
0523 if (index < 0) {
0524 safety = -1;
0525 return;
0526 }
0527
0528 PolyconeSection const &sec = polycone.GetSection(index);
0529
0530 Vector3D<Real_v> p = point - Vector3D<Precision>(0, 0, sec.fShift);
0531
0532 ConeImplementation<polyconeTypeT>::template SafetyToOut<Real_v>(*sec.fSolid, p, safety);
0533
0534 Precision minSafety = safety;
0535 if (minSafety == kInfLength) {
0536 safety = 0.;
0537 return;
0538 }
0539 if (minSafety < kTolerance) {
0540 safety = 0.;
0541 return;
0542 }
0543
0544 Precision zbase = polycone.fZs[index + 1];
0545 for (int i = index + 1; i < polycone.GetNSections(); ++i) {
0546 Precision dz = polycone.fZs[i] - zbase;
0547 if (dz >= minSafety) break;
0548 PolyconeSection const § = polycone.GetSection(i);
0549 p = point - Vector3D<Precision>(0, 0, sect.fShift);
0550
0551
0552 ConeImplementation<polyconeTypeT>::template SafetyToIn<Real_v>(*sect.fSolid, p, safety);
0553
0554 if (safety < minSafety) minSafety = safety;
0555 }
0556
0557 if (index > 0) {
0558 zbase = polycone.fZs[index - 1];
0559 for (int i = index - 1; i >= 0; --i) {
0560 Precision dz = zbase - polycone.fZs[i];
0561 if (dz >= minSafety) break;
0562 PolyconeSection const § = polycone.GetSection(i);
0563 p = point - Vector3D<Precision>(0, 0, sect.fShift);
0564
0565
0566 ConeImplementation<polyconeTypeT>::template SafetyToIn<Real_v>(*sect.fSolid, p, safety);
0567
0568 if (safety < minSafety) minSafety = safety;
0569 }
0570 }
0571
0572 safety = minSafety;
0573 return;
0574 }
0575 #endif
0576 };
0577 }
0578 }
0579
0580 #endif