File indexing completed on 2025-01-18 10:13:59
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef NAVIGATION_VNAVIGATOR_H_
0009 #define NAVIGATION_VNAVIGATOR_H_
0010
0011 #include "VecGeom/base/Global.h"
0012 #include "VecGeom/base/Vector3D.h"
0013 #include "VecGeom/base/SOA3D.h"
0014 #include "VecGeom/base/Transformation3D.h"
0015 #include "VecGeom/navigation/NavigationState.h"
0016 #include "VecGeom/navigation/GlobalLocator.h"
0017 #include "VecGeom/volumes/PlacedVolume.h"
0018 #include "VecGeom/volumes/LogicalVolume.h"
0019 #include "VecGeom/navigation/VSafetyEstimator.h"
0020 #include "VecGeom/navigation/NavStateFwd.h"
0021
0022 namespace vecgeom {
0023 inline namespace VECGEOM_IMPL_NAMESPACE {
0024
0025
0026 template <typename T>
0027 class Vector3D;
0028
0029 class LogicalVolume;
0030 class Transformation3D;
0031 class VPlacedVolume;
0032
0033
0034
0035 class VNavigator {
0036
0037 public:
0038 VNavigator() : fSafetyEstimator(nullptr) {}
0039
0040 VECCORE_ATT_HOST_DEVICE
0041 VSafetyEstimator const *GetSafetyEstimator() const { return fSafetyEstimator; }
0042
0043
0044
0045
0046
0047
0048
0049
0050 VECCORE_ATT_HOST_DEVICE
0051 virtual Precision ComputeStepAndPropagatedState(Vector3D<Precision> const & ,
0052 Vector3D<Precision> const & ,
0053 Precision ,
0054 NavigationState const & ,
0055 NavigationState & ) const = 0;
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 virtual Precision ComputeStep(Vector3D<Precision> const & , Vector3D<Precision> const & ,
0067 Precision , NavigationState const & ,
0068 NavigationState & ) const = 0;
0069
0070
0071
0072
0073 VECCORE_ATT_HOST_DEVICE
0074 virtual Precision ComputeStepAndSafety(Vector3D<Precision> const & ,
0075 Vector3D<Precision> const & , Precision ,
0076 NavigationState & , bool , Precision & ,
0077 bool indicateDaughterHit = false) const = 0;
0078
0079
0080 VECCORE_ATT_HOST_DEVICE
0081 void FindNextBoundaryAndStep(Vector3D<Precision> const &globalpoint, Vector3D<Precision> const &globaldir,
0082 NavigationState const &in_state, NavigationState &out_state, Precision step_limit,
0083 Precision &step) const
0084 {
0085 step = ComputeStepAndPropagatedState(globalpoint, globaldir, step_limit, in_state, out_state);
0086 }
0087
0088
0089 void FindNextBoundaryAndStepAndSafety(Vector3D<Precision> const &globalpoint, Vector3D<Precision> const &globaldir,
0090 NavigationState const &in_state, NavigationState &out_state,
0091 Precision step_limit, Precision &step, bool calcsafety, Precision &safety) const
0092 {
0093 step = ComputeStepAndSafetyAndPropagatedState(globalpoint, globaldir, step_limit, in_state, out_state, calcsafety,
0094 safety);
0095 }
0096
0097
0098 VECCORE_ATT_HOST_DEVICE
0099 virtual Precision ComputeStepAndSafetyAndPropagatedState(Vector3D<Precision> const & ,
0100 Vector3D<Precision> const & ,
0101 Precision ,
0102 NavigationState const & ,
0103 NavigationState & , bool ,
0104 Precision & ) const = 0;
0105
0106
0107
0108
0109 VECCORE_ATT_HOST_DEVICE
0110 virtual bool CheckDaughterIntersections(LogicalVolume const * , Vector3D<Precision> const & ,
0111 Vector3D<Precision> const & ,
0112 NavigationState const * , NavigationState * ,
0113 Precision & , VPlacedVolume const *& ) const = 0;
0114
0115
0116
0117
0118 VECCORE_ATT_HOST_DEVICE
0119 virtual bool CheckDaughterIntersections(LogicalVolume const * , Vector3D<Precision> const & ,
0120 Vector3D<Precision> const & , VPlacedVolume const * ,
0121 Precision & , VPlacedVolume const *& ) const
0122 {
0123 assert(false);
0124 return false;
0125 }
0126
0127
0128 virtual void ComputeStepsAndPropagatedStates(SOA3D<Precision> const & ,
0129 SOA3D<Precision> const & ,
0130 Precision const * ,
0131 NavigationState const *const * ,
0132 NavigationState ** , Precision * ) const = 0;
0133
0134
0135 VECCORE_ATT_HOST_DEVICE
0136 virtual void ComputeStepsAndSafetiesAndPropagatedStates(SOA3D<Precision> const &points, SOA3D<Precision> const &dirs,
0137 Precision const *psteps, NavStatePool const &instates,
0138 NavStatePool &outstates, Precision *outsteps,
0139 bool const *calcsafety, Precision *safeties) const = 0;
0140
0141 VECCORE_ATT_HOST_DEVICE
0142 virtual void ComputeStepsAndSafetiesAndPropagatedStates(SOA3D<Precision> const & ,
0143 SOA3D<Precision> const & ,
0144 Precision const * ,
0145 NavigationState const *const * ,
0146 NavigationState ** , Precision * ,
0147 bool const * ,
0148 Precision * ) const = 0;
0149
0150
0151 VECCORE_ATT_HOST_DEVICE
0152 virtual void ComputeStepsAndSafeties(SOA3D<Precision> const & ,
0153 SOA3D<Precision> const & ,
0154 Precision const * ,
0155 NavigationState const *const * , Precision * ,
0156 bool const * , Precision * ) const = 0;
0157
0158 protected:
0159
0160 VECCORE_ATT_HOST_DEVICE
0161 virtual void Relocate(Vector3D<Precision> const & , NavigationState const &__restrict__ ,
0162 NavigationState &__restrict__ ) const = 0;
0163
0164
0165
0166 VECGEOM_FORCE_INLINE
0167 VECCORE_ATT_HOST_DEVICE
0168 static Vector3D<Precision> MovePointAfterBoundary(Vector3D<Precision> const &localpoint,
0169 Vector3D<Precision> const &dir, Precision step)
0170 {
0171 const Precision extra = 1E-6;
0172 return localpoint + (step + extra) * dir;
0173 }
0174
0175 public:
0176 VECCORE_ATT_DEVICE
0177 virtual ~VNavigator(){};
0178
0179
0180 virtual const char *GetName() const = 0;
0181
0182 typedef VSafetyEstimator SafetyEstimator_t;
0183
0184 protected:
0185 VECCORE_ATT_HOST_DEVICE
0186 VNavigator(VSafetyEstimator *s) : fSafetyEstimator(s) {}
0187 VSafetyEstimator *fSafetyEstimator;
0188
0189
0190 VECGEOM_FORCE_INLINE
0191 VECCORE_ATT_HOST_DEVICE
0192 static Precision PrepareOutState(NavigationState const &__restrict__ in_state,
0193 NavigationState &__restrict__ out_state, Precision geom_step, Precision step_limit,
0194 VPlacedVolume const *hitcandidate, bool &doneafterthisstep)
0195 {
0196
0197 in_state.CopyTo(&out_state);
0198 doneafterthisstep = false;
0199
0200
0201
0202
0203
0204
0205 if (geom_step == kInfLength && step_limit > 0.) {
0206 geom_step = vecgeom::kTolerance;
0207 out_state.SetBoundaryState(true);
0208 do {
0209 out_state.Pop();
0210 } while (out_state.Top()->GetLogicalVolume()->GetUnplacedVolume()->IsAssembly());
0211 doneafterthisstep = true;
0212 return geom_step;
0213 }
0214
0215
0216
0217 if (geom_step > step_limit) {
0218
0219 geom_step = step_limit;
0220 out_state.SetBoundaryState(false);
0221 return geom_step;
0222 }
0223
0224
0225 out_state.SetBoundaryState(true);
0226 out_state.SetLastExited();
0227 if (hitcandidate) out_state.Push(hitcandidate);
0228
0229 if (geom_step < 0.) {
0230
0231
0232 geom_step = 0.;
0233 }
0234 return geom_step;
0235 }
0236
0237
0238 template <typename T>
0239 VECGEOM_FORCE_INLINE
0240 VECCORE_ATT_HOST_DEVICE
0241 static T TreatDistanceToMother(VPlacedVolume const *pvol, Vector3D<T> const &localpoint, Vector3D<T> const &localdir,
0242 T step_limit)
0243 {
0244 T step;
0245 assert(pvol != nullptr && "currentvolume is null in navigation");
0246 step = pvol->DistanceToOut(localpoint, localdir, step_limit);
0247 vecCore::MaskedAssign(step, step < T(0.), T(0.));
0248 return step;
0249 }
0250
0251
0252
0253
0254
0255
0256
0257
0258 template <typename T>
0259 VECGEOM_FORCE_INLINE
0260 VECCORE_ATT_HOST_DEVICE
0261 static void DoGlobalToLocalTransformation(NavigationState const &in_state, Vector3D<T> const &globalpoint,
0262 Vector3D<T> const &globaldir, Vector3D<T> &localpoint,
0263 Vector3D<T> &localdir)
0264 {
0265
0266 Transformation3D m;
0267 in_state.TopMatrix(m);
0268 localpoint = m.Transform(globalpoint);
0269 localdir = m.TransformDirection(globaldir);
0270 }
0271
0272
0273
0274 template <typename T, unsigned int ChunkSize>
0275 VECGEOM_FORCE_INLINE
0276 VECCORE_ATT_HOST_DEVICE
0277 static void DoGlobalToLocalTransformations(NavigationState const *const *in_states,
0278 SOA3D<Precision> const &globalpoints, SOA3D<Precision> const &globaldirs,
0279 unsigned int from_index, Vector3D<T> &localpoint, Vector3D<T> &localdir)
0280 {
0281 for (unsigned int i = 0; i < ChunkSize; ++i) {
0282 unsigned int trackid = from_index + i;
0283 Transformation3D m;
0284
0285
0286 in_states[trackid]->TopMatrix(m);
0287 auto tmp = m.Transform(globalpoints[trackid]);
0288
0289 using vecCore::AssignLane;
0290 AssignLane(localpoint.x(), i, tmp.x());
0291 AssignLane(localpoint.y(), i, tmp.y());
0292 AssignLane(localpoint.z(), i, tmp.z());
0293 tmp = m.TransformDirection(globaldirs[trackid]);
0294 AssignLane(localdir.x(), i, tmp.x());
0295 AssignLane(localdir.y(), i, tmp.y());
0296 AssignLane(localdir.z(), i, tmp.z());
0297 }
0298 }
0299
0300
0301
0302 template <typename T, unsigned int ChunkSize>
0303 VECGEOM_FORCE_INLINE
0304 VECCORE_ATT_HOST_DEVICE
0305 static void DoGlobalToLocalTransformations(NavStatePool const &in_states, SOA3D<Precision> const &globalpoints,
0306 SOA3D<Precision> const &globaldirs, unsigned int from_index,
0307 Vector3D<T> &localpoint, Vector3D<T> &localdir)
0308 {
0309 for (unsigned int i = 0; i < ChunkSize; ++i) {
0310 unsigned int trackid = from_index + i;
0311 Transformation3D m;
0312
0313
0314 in_states[trackid]->TopMatrix(m);
0315 auto tmp = m.Transform(globalpoints[trackid]);
0316
0317 using vecCore::AssignLane;
0318 AssignLane(localpoint.x(), i, tmp.x());
0319 AssignLane(localpoint.y(), i, tmp.y());
0320 AssignLane(localpoint.z(), i, tmp.z());
0321 tmp = m.TransformDirection(globaldirs[trackid]);
0322 AssignLane(localdir.x(), i, tmp.x());
0323 AssignLane(localdir.y(), i, tmp.y());
0324 AssignLane(localdir.z(), i, tmp.z());
0325 }
0326 }
0327 };
0328
0329
0330
0331 template <typename Impl, bool MotherIsConvex = false>
0332 class VNavigatorHelper : public VNavigator {
0333 protected:
0334 using VNavigator::VNavigator;
0335
0336 public:
0337
0338
0339
0340
0341
0342 template <typename T, unsigned int ChunkSize>
0343 VECCORE_ATT_HOST_DEVICE
0344 static void DaughterIntersectionsLooper(VNavigator const *nav, LogicalVolume const *lvol,
0345 Vector3D<T> const &localpoint, Vector3D<T> const &localdir,
0346 NavigationState const *const *in_states, NavigationState **out_states,
0347 unsigned int from_index, Precision *out_steps,
0348 VPlacedVolume const *hitcandidates[ChunkSize])
0349 {
0350
0351 using vecCore::LaneAt;
0352 for (unsigned int i = 0; i < ChunkSize; ++i) {
0353 unsigned int trackid = from_index + i;
0354 ((Impl *)nav)
0355 ->Impl::CheckDaughterIntersections(
0356 lvol,
0357 Vector3D<Precision>(LaneAt(localpoint.x(), i), LaneAt(localpoint.y(), i), LaneAt(localpoint.z(), i)),
0358 Vector3D<Precision>(LaneAt(localdir.x(), i), LaneAt(localdir.y(), i), LaneAt(localdir.z(), i)),
0359 in_states[trackid], out_states[trackid], out_steps[trackid], hitcandidates[i]);
0360 }
0361 }
0362
0363
0364
0365
0366
0367
0368 template <typename T, unsigned int ChunkSize>
0369 VECCORE_ATT_HOST_DEVICE
0370 static void DaughterIntersectionsLooper(VNavigator const *nav, LogicalVolume const *lvol,
0371 Vector3D<T> const &localpoint, Vector3D<T> const &localdir,
0372 NavStatePool const &in_states, NavStatePool &out_states,
0373 unsigned int from_index, Precision *out_steps,
0374 VPlacedVolume const *hitcandidates[ChunkSize])
0375 {
0376
0377 using vecCore::LaneAt;
0378 for (unsigned int i = 0; i < ChunkSize; ++i) {
0379 unsigned int trackid = from_index + i;
0380 ((Impl *)nav)
0381 ->Impl::CheckDaughterIntersections(
0382 lvol,
0383 Vector3D<Precision>(LaneAt(localpoint.x(), i), LaneAt(localpoint.y(), i), LaneAt(localpoint.z(), i)),
0384 Vector3D<Precision>(LaneAt(localdir.x(), i), LaneAt(localdir.y(), i), LaneAt(localdir.z(), i)),
0385 in_states[trackid], out_states[trackid], out_steps[trackid], hitcandidates[i]);
0386 }
0387 }
0388
0389
0390
0391
0392 template <typename T, unsigned int ChunkSize>
0393 VECCORE_ATT_HOST_DEVICE
0394 static void DaughterIntersectionsLooper(VNavigator const *nav, LogicalVolume const *lvol,
0395 Vector3D<T> const &localpoint, Vector3D<T> const &localdir,
0396 NavigationState const *const *in_states, unsigned int from_index,
0397 Precision *out_steps, VPlacedVolume const *hitcandidates[ChunkSize])
0398 {
0399
0400 using vecCore::LaneAt;
0401 for (unsigned int i = 0; i < ChunkSize; ++i) {
0402 unsigned int trackid = from_index + i;
0403 ((Impl *)nav)
0404 ->Impl::CheckDaughterIntersections(
0405 lvol,
0406 Vector3D<Precision>(LaneAt(localpoint.x(), i), LaneAt(localpoint.y(), i), LaneAt(localpoint.z(), i)),
0407 Vector3D<Precision>(LaneAt(localdir.x(), i), LaneAt(localdir.y(), i), LaneAt(localdir.z(), i)),
0408 in_states[trackid], nullptr, out_steps[trackid], hitcandidates[i]);
0409 }
0410 }
0411
0412
0413 template <typename T, unsigned int ChunkSize>
0414 VECCORE_ATT_HOST_DEVICE static void SafetyLooper(VNavigator const *nav, VPlacedVolume const *pvol,
0415 Vector3D<T> const &localpoint, unsigned int from_index,
0416 bool const *calcsafeties, Precision *out_safeties)
0417 {
0418
0419
0420 using SafetyE_t = typename Impl::SafetyEstimator_t;
0421 using Bool_v = vecCore::Mask_v<T>;
0422 Bool_v m;
0423 for (unsigned int i = 0; i < ChunkSize; ++i) {
0424 vecCore::AssignMaskLane(m, i, calcsafeties[from_index + i]);
0425 }
0426
0427 T safety(0.);
0428 if (!vecCore::MaskEmpty(m)) {
0429 safety = ((SafetyE_t *)nav->GetSafetyEstimator())->ComputeSafetyForLocalPoint(localpoint, pvol, m);
0430 }
0431 vecCore::Store(safety, &out_safeties[from_index]);
0432 }
0433
0434 public:
0435 VECCORE_ATT_HOST_DEVICE
0436 virtual Precision ComputeStepAndPropagatedState(Vector3D<Precision> const &globalpoint,
0437 Vector3D<Precision> const &globaldir, Precision step_limit,
0438 NavigationState const &in_state,
0439 NavigationState &out_state) const override
0440 {
0441 #ifdef DEBUGNAV
0442 static size_t counter = 0;
0443 counter++;
0444 #endif
0445
0446
0447 Vector3D<Precision> localpoint;
0448 Vector3D<Precision> localdir;
0449 Impl::DoGlobalToLocalTransformation(in_state, globalpoint, globaldir, localpoint, localdir);
0450
0451 VPlacedVolume const *hitcandidate = nullptr;
0452 auto pvol = in_state.Top();
0453 auto lvol = pvol->GetLogicalVolume();
0454 Precision step = Impl::TreatDistanceToMother(pvol, localpoint, localdir, step_limit);
0455
0456 if (lvol->GetDaughters().size() > 0)
0457 ((Impl *)this)
0458 ->Impl::CheckDaughterIntersections(lvol, localpoint, localdir, &in_state, &out_state, step, hitcandidate);
0459
0460
0461 bool done;
0462 step = Impl::PrepareOutState(in_state, out_state, step, step_limit, hitcandidate, done);
0463 if (done) {
0464 if (out_state.Top() != nullptr) {
0465 assert(!out_state.Top()->GetLogicalVolume()->GetUnplacedVolume()->IsAssembly());
0466 }
0467 return step;
0468 }
0469
0470 if (!out_state.IsOnBoundary()) return step;
0471
0472
0473
0474 ((Impl *)this)->Impl::Relocate(MovePointAfterBoundary(localpoint, localdir, step), in_state, out_state);
0475 if (out_state.Top() != nullptr) {
0476 while (out_state.Top()->IsAssembly()) {
0477 out_state.Pop();
0478 }
0479 assert(!out_state.Top()->GetLogicalVolume()->GetUnplacedVolume()->IsAssembly());
0480 }
0481 return step;
0482 }
0483
0484 virtual Precision ComputeStep(Vector3D<Precision> const &globalpoint, Vector3D<Precision> const &globaldir,
0485 Precision step_limit, NavigationState const &in_state,
0486 NavigationState &out_state) const override
0487 {
0488 #ifdef DEBUGNAV
0489 static size_t counter = 0;
0490 counter++;
0491 #endif
0492
0493
0494 Vector3D<Precision> localpoint;
0495 Vector3D<Precision> localdir;
0496 Impl::DoGlobalToLocalTransformation(in_state, globalpoint, globaldir, localpoint, localdir);
0497
0498 VPlacedVolume const *hitcandidate = nullptr;
0499 auto pvol = in_state.Top();
0500 auto lvol = pvol->GetLogicalVolume();
0501 Precision step = Impl::TreatDistanceToMother(pvol, localpoint, localdir, step_limit);
0502
0503 if (lvol->GetDaughters().size() > 0)
0504 ((Impl *)this)
0505 ->Impl::CheckDaughterIntersections(lvol, localpoint, localdir, &in_state, &out_state, step, hitcandidate);
0506
0507
0508 bool done;
0509 step = Impl::PrepareOutState(in_state, out_state, step, step_limit, hitcandidate, done);
0510 if (done) {
0511 if (out_state.Top() != nullptr) {
0512 assert(!out_state.Top()->GetLogicalVolume()->GetUnplacedVolume()->IsAssembly());
0513 }
0514 return step;
0515 }
0516
0517 if (!out_state.IsOnBoundary()) return step;
0518
0519 return step;
0520 }
0521
0522 VECCORE_ATT_HOST_DEVICE
0523 virtual Precision ComputeStepAndSafety(Vector3D<Precision> const &globalpoint, Vector3D<Precision> const &globaldir,
0524 Precision step_limit, NavigationState &in_state, bool calcsafety,
0525 Precision &safety, bool indicateDaughterHit = false) const override
0526 {
0527
0528 #ifdef DEBUGNAV
0529 static size_t counter = 0;
0530 counter++;
0531 #endif
0532
0533
0534 Vector3D<Precision> localpoint;
0535 Vector3D<Precision> localdir;
0536 NavigationState *out_state = nullptr;
0537
0538 Impl::DoGlobalToLocalTransformation(in_state, globalpoint, globaldir, localpoint, localdir);
0539
0540
0541 using SafetyE_t = typename Impl::SafetyEstimator_t;
0542 if (calcsafety) {
0543
0544 safety = ((SafetyE_t *)fSafetyEstimator)->SafetyE_t::ComputeSafetyForLocalPoint(localpoint, in_state.Top());
0545 }
0546
0547 VPlacedVolume const *hitcandidate = nullptr;
0548 auto pvol = in_state.Top();
0549 auto lvol = pvol->GetLogicalVolume();
0550 Precision step = step_limit;
0551
0552
0553 bool safetydone = calcsafety && safety >= step;
0554
0555 if (!safetydone) {
0556 step = Impl::TreatDistanceToMother(pvol, localpoint, localdir, step_limit);
0557
0558 if (lvol->GetDaughters().size() > 0)
0559 ((Impl *)this)
0560 ->Impl::CheckDaughterIntersections(lvol, localpoint, localdir, &in_state, out_state, step, hitcandidate);
0561 }
0562 if (indicateDaughterHit && hitcandidate) in_state.Push(hitcandidate);
0563 return Min(step, step_limit);
0564 }
0565
0566 VECCORE_ATT_HOST_DEVICE
0567 virtual void ComputeStepsAndSafeties(SOA3D<Precision> const &globalpoints, SOA3D<Precision> const &globaldirs,
0568 Precision const *step_limits, NavigationState const *const *in_states,
0569 Precision *out_steps, bool const *calcsafeties,
0570 Precision *out_safeties) const override
0571 {
0572
0573 using Real_v = vecgeom::VectorBackend::Real_v;
0574 (void)(Real_v *)(nullptr);
0575 const auto size = globalpoints.size();
0576 auto pvol = in_states[0]->Top();
0577 auto lvol = pvol->GetLogicalVolume();
0578
0579 auto i = decltype(size){0};
0580 constexpr auto kVS = vecCore::VectorSize<Real_v>();
0581 for (; i < (size - (kVS - 1)); i += kVS) {
0582 NavigateAChunkNoReloc<Real_v, kVS>(this, pvol, lvol, globalpoints, globaldirs, step_limits, in_states, out_steps,
0583 calcsafeties, out_safeties, i);
0584 }
0585
0586
0587 for (; i < size; ++i) {
0588 out_steps[i] = ((Impl *)this)
0589 ->Impl::ComputeStepAndSafety(globalpoints[i], globaldirs[i], step_limits[i],
0590 *const_cast<NavigationState *>(in_states[i]), calcsafeties[i],
0591 out_safeties[i]);
0592 }
0593 i = decltype(size){0};
0594 for (; i < size; ++i)
0595 out_steps[i] = vecCore::math::Min(out_steps[i], step_limits[i]);
0596 }
0597
0598
0599
0600 template <typename T, unsigned int ChunkSize>
0601 static void NavigateAChunk(VNavigator const *__restrict__ nav, VPlacedVolume const *__restrict__ pvol,
0602 LogicalVolume const *__restrict__ lvol, SOA3D<Precision> const &__restrict__ globalpoints,
0603 SOA3D<Precision> const &__restrict__ globaldirs, Precision const *__restrict__ step_limits,
0604 NavigationState const *const *__restrict__ in_states,
0605 NavigationState **__restrict__ out_states, Precision *__restrict__ out_steps,
0606 unsigned int from_index)
0607 {
0608
0609 VPlacedVolume const *hitcandidates[ChunkSize] = {};
0610
0611 Vector3D<T> localpoint, localdir;
0612 Impl::template DoGlobalToLocalTransformations<T, ChunkSize>(in_states, globalpoints, globaldirs, from_index,
0613 localpoint, localdir);
0614
0615 T slimit(vecCore::FromPtr<T>(step_limits + from_index));
0616
0617 T step = Impl::template TreatDistanceToMother<T>(pvol, localpoint, localdir, slimit);
0618 vecCore::Store(step, out_steps + from_index);
0619
0620
0621 Impl::template DaughterIntersectionsLooper<T, ChunkSize>(nav, lvol, localpoint, localdir, in_states, out_states,
0622 from_index, out_steps, hitcandidates);
0623
0624
0625 for (unsigned int i = 0; i < ChunkSize; ++i) {
0626 unsigned int trackid = from_index + i;
0627 bool done;
0628 out_steps[trackid] = Impl::PrepareOutState(*in_states[trackid], *out_states[trackid], out_steps[trackid],
0629 vecCore::LaneAt(slimit, i), hitcandidates[i], done);
0630 if (done) continue;
0631
0632 if (!out_states[trackid]->IsOnBoundary()) continue;
0633
0634
0635 using vecCore::LaneAt;
0636 ((Impl *)nav)
0637 ->Impl::Relocate(
0638 MovePointAfterBoundary(
0639 Vector3D<Precision>(LaneAt(localpoint.x(), i), LaneAt(localpoint.y(), i), LaneAt(localpoint.z(), i)),
0640 Vector3D<Precision>(LaneAt(localdir.x(), i), LaneAt(localdir.y(), i), LaneAt(localdir.z(), i)),
0641 out_steps[trackid]),
0642 *in_states[trackid], *out_states[trackid]);
0643 }
0644 }
0645
0646
0647
0648
0649
0650 template <typename T, unsigned int ChunkSize>
0651 VECCORE_ATT_HOST_DEVICE
0652 static void NavigateAChunk(VNavigator const *__restrict__ nav, VPlacedVolume const *__restrict__ pvol,
0653 LogicalVolume const *__restrict__ lvol, SOA3D<Precision> const &__restrict__ globalpoints,
0654 SOA3D<Precision> const &__restrict__ globaldirs, Precision const *__restrict__ step_limits,
0655 NavigationState const *const *__restrict__ in_states,
0656 NavigationState **__restrict__ out_states, Precision *__restrict__ out_steps,
0657 bool const *__restrict__ calcsafeties, Precision *__restrict__ out_safeties,
0658 unsigned int from_index)
0659 {
0660
0661 VPlacedVolume const *hitcandidates[ChunkSize] = {};
0662
0663 Vector3D<T> localpoint, localdir;
0664 Impl::template DoGlobalToLocalTransformations<T, ChunkSize>(in_states, globalpoints, globaldirs, from_index,
0665 localpoint, localdir);
0666
0667
0668 Impl::template SafetyLooper<T, ChunkSize>(nav, pvol, localpoint, from_index, calcsafeties, out_safeties);
0669
0670 T slimit(vecCore::FromPtr<T>(step_limits + from_index));
0671
0672 T step = Impl::template TreatDistanceToMother<T>(pvol, localpoint, localdir, slimit);
0673 vecCore::Store(step, out_steps + from_index);
0674
0675
0676 Impl::template DaughterIntersectionsLooper<T, ChunkSize>(nav, lvol, localpoint, localdir, in_states, out_states,
0677 from_index, out_steps, hitcandidates);
0678
0679 using vecCore::LaneAt;
0680
0681
0682 for (unsigned int i = 0; i < ChunkSize; ++i) {
0683 unsigned int trackid = from_index + i;
0684 bool done;
0685 out_steps[trackid] = Impl::PrepareOutState(*in_states[trackid], *out_states[trackid], out_steps[trackid],
0686 LaneAt(slimit, i), hitcandidates[i], done);
0687 if (done) continue;
0688
0689 if (!out_states[trackid]->IsOnBoundary()) continue;
0690
0691
0692 ((Impl *)nav)
0693 ->Impl::Relocate(
0694 MovePointAfterBoundary(
0695 Vector3D<Precision>(LaneAt(localpoint.x(), i), LaneAt(localpoint.y(), i), LaneAt(localpoint.z(), i)),
0696 Vector3D<Precision>(LaneAt(localdir.x(), i), LaneAt(localdir.y(), i), LaneAt(localdir.z(), i)),
0697 out_steps[trackid]),
0698 *in_states[trackid], *out_states[trackid]);
0699 }
0700 }
0701
0702
0703
0704
0705
0706 template <typename T, unsigned int ChunkSize>
0707 VECCORE_ATT_HOST_DEVICE
0708 static void NavigateAChunk(VNavigator const *__restrict__ nav, VPlacedVolume const *__restrict__ pvol,
0709 LogicalVolume const *__restrict__ lvol, SOA3D<Precision> const &__restrict__ globalpoints,
0710 SOA3D<Precision> const &__restrict__ globaldirs, Precision const *__restrict__ step_limits,
0711 NavStatePool const &in_states, NavStatePool &out_states, Precision *__restrict__ out_steps,
0712 bool const *__restrict__ calcsafeties, Precision *__restrict__ out_safeties,
0713 unsigned int from_index)
0714 {
0715 VPlacedVolume const *hitcandidates[ChunkSize] = {};
0716
0717 Vector3D<T> localpoint, localdir;
0718 Impl::template DoGlobalToLocalTransformations<T, ChunkSize>(in_states, globalpoints, globaldirs, from_index,
0719 localpoint, localdir);
0720
0721
0722 Impl::template SafetyLooper<T, ChunkSize>(nav, pvol, localpoint, from_index, calcsafeties, out_safeties);
0723
0724 T slimit(vecCore::FromPtr<T>(step_limits + from_index));
0725
0726 T step = Impl::template TreatDistanceToMother<T>(pvol, localpoint, localdir, slimit);
0727 vecCore::Store(step, out_steps + from_index);
0728
0729
0730 Impl::template DaughterIntersectionsLooper<T, ChunkSize>(nav, lvol, localpoint, localdir, in_states, out_states,
0731 from_index, out_steps, hitcandidates);
0732
0733 using vecCore::LaneAt;
0734
0735
0736 for (unsigned int i = 0; i < ChunkSize; ++i) {
0737 unsigned int trackid = from_index + i;
0738 bool done;
0739 out_steps[trackid] = Impl::PrepareOutState(*in_states[trackid], *out_states[trackid], out_steps[trackid],
0740 LaneAt(slimit, i), hitcandidates[i], done);
0741 if (done) continue;
0742
0743 if (!out_states[trackid]->IsOnBoundary()) continue;
0744
0745
0746 ((Impl *)nav)
0747 ->Impl::Relocate(
0748 MovePointAfterBoundary(
0749 Vector3D<Precision>(LaneAt(localpoint.x(), i), LaneAt(localpoint.y(), i), LaneAt(localpoint.z(), i)),
0750 Vector3D<Precision>(LaneAt(localdir.x(), i), LaneAt(localdir.y(), i), LaneAt(localdir.z(), i)),
0751 out_steps[trackid]),
0752 *in_states[trackid], *out_states[trackid]);
0753 }
0754 }
0755
0756
0757
0758
0759
0760 template <typename T, unsigned int ChunkSize>
0761 VECCORE_ATT_HOST_DEVICE
0762 static void NavigateAChunkNoReloc(VNavigator const *__restrict__ nav, VPlacedVolume const *__restrict__ pvol,
0763 LogicalVolume const *__restrict__ lvol,
0764 SOA3D<Precision> const &__restrict__ globalpoints,
0765 SOA3D<Precision> const &__restrict__ globaldirs,
0766 Precision const *__restrict__ step_limits,
0767 NavigationState const *const *__restrict__ in_states,
0768 Precision *__restrict__ out_steps, bool const *__restrict__ calcsafeties,
0769 Precision *__restrict__ out_safeties, unsigned int from_index)
0770 {
0771 VPlacedVolume const *hitcandidates[ChunkSize] = {};
0772
0773 Vector3D<T> localpoint, localdir;
0774 Impl::template DoGlobalToLocalTransformations<T, ChunkSize>(in_states, globalpoints, globaldirs, from_index,
0775 localpoint, localdir);
0776
0777
0778 Impl::template SafetyLooper<T, ChunkSize>(nav, pvol, localpoint, from_index, calcsafeties, out_safeties);
0779
0780 T slimit(vecCore::FromPtr<T>(step_limits + from_index));
0781
0782 T step = Impl::template TreatDistanceToMother<T>(pvol, localpoint, localdir, slimit);
0783 vecCore::Store(step, out_steps + from_index);
0784
0785
0786 Impl::template DaughterIntersectionsLooper<T, ChunkSize>(nav, lvol, localpoint, localdir, in_states, from_index,
0787 out_steps, hitcandidates);
0788 }
0789
0790
0791
0792
0793 virtual void ComputeStepsAndPropagatedStates(SOA3D<Precision> const &__restrict__ globalpoints,
0794 SOA3D<Precision> const &__restrict__ globaldirs,
0795 Precision const *__restrict__ step_limit,
0796 NavigationState const *const *__restrict__ in_states,
0797 NavigationState **__restrict__ out_states,
0798 Precision *__restrict__ out_steps) const override
0799 {
0800
0801
0802
0803 using Real_v = vecgeom::VectorBackend::Real_v;
0804 (void)(Real_v *)(nullptr);
0805 const auto size = globalpoints.size();
0806 auto pvol = in_states[0]->Top();
0807 auto lvol = pvol->GetLogicalVolume();
0808
0809 auto i = decltype(size){0};
0810 constexpr auto kVS = vecCore::VectorSize<Real_v>();
0811 for (; i < (size - (kVS - 1)); i += kVS) {
0812 NavigateAChunk<Real_v, kVS>(this, pvol, lvol, globalpoints, globaldirs, step_limit, in_states, out_states,
0813 out_steps, i);
0814 }
0815
0816
0817 for (; i < size; ++i) {
0818 out_steps[i] = ((Impl *)this)
0819 ->Impl::ComputeStepAndPropagatedState(globalpoints[i], globaldirs[i], step_limit[i],
0820 *in_states[i], *out_states[i]);
0821 }
0822 }
0823
0824
0825
0826
0827 VECCORE_ATT_HOST_DEVICE
0828 virtual void ComputeStepsAndSafetiesAndPropagatedStates(SOA3D<Precision> const &__restrict__ globalpoints,
0829 SOA3D<Precision> const &__restrict__ globaldirs,
0830 Precision const *__restrict__ step_limit,
0831 NavStatePool const &in_states, NavStatePool &out_states,
0832 Precision *__restrict__ out_steps,
0833 bool const *__restrict__ calcsafeties,
0834 Precision *__restrict__ out_safeties) const override
0835 {
0836
0837
0838 const auto size = globalpoints.size();
0839 auto pvol = in_states[0]->Top();
0840 auto lvol = pvol->GetLogicalVolume();
0841
0842 auto i = decltype(size){0};
0843 constexpr auto kVS = vecCore::VectorSize<Real_v>();
0844 for (; i < (size - (kVS - 1)); i += kVS) {
0845 NavigateAChunk<Real_v, kVS>(this, pvol, lvol, globalpoints, globaldirs, step_limit, in_states, out_states,
0846 out_steps, calcsafeties, out_safeties, i);
0847 }
0848
0849
0850 for (; i < size; ++i) {
0851 out_steps[i] = ((Impl *)this)
0852 ->Impl::ComputeStepAndSafetyAndPropagatedState(globalpoints[i], globaldirs[i], step_limit[i],
0853 *in_states[i], *out_states[i], calcsafeties[i],
0854 out_safeties[i]);
0855 }
0856 }
0857
0858
0859
0860
0861 VECCORE_ATT_HOST_DEVICE
0862 virtual void ComputeStepsAndSafetiesAndPropagatedStates(
0863 SOA3D<Precision> const &__restrict__ globalpoints, SOA3D<Precision> const &__restrict__ globaldirs,
0864 Precision const *__restrict__ step_limit, NavigationState const *const *__restrict__ in_states,
0865 NavigationState **__restrict__ out_states, Precision *__restrict__ out_steps,
0866 bool const *__restrict__ calcsafeties, Precision *__restrict__ out_safeties) const override
0867 {
0868
0869
0870
0871 using Real_v = vecgeom::VectorBackend::Real_v;
0872 (void)(Real_v *)(nullptr);
0873 const auto size = globalpoints.size();
0874 auto pvol = in_states[0]->Top();
0875 auto lvol = pvol->GetLogicalVolume();
0876
0877 auto i = decltype(size){0};
0878 constexpr auto kVS = vecCore::VectorSize<Real_v>();
0879 for (; i < (size - (kVS - 1)); i += kVS) {
0880 NavigateAChunk<Real_v, kVS>(this, pvol, lvol, globalpoints, globaldirs, step_limit, in_states, out_states,
0881 out_steps, calcsafeties, out_safeties, i);
0882 }
0883
0884 for (; i < size; ++i) {
0885 out_steps[i] = ((Impl *)this)
0886 ->Impl::ComputeStepAndSafetyAndPropagatedState(globalpoints[i], globaldirs[i], step_limit[i],
0887 *in_states[i], *out_states[i], calcsafeties[i],
0888 out_safeties[i]);
0889 }
0890 }
0891
0892 #ifdef TRIVIAL
0893
0894
0895 virtual void ComputeStepsAndPropagatedStates(SOA3D<Precision> const &__restrict__ globalpoints,
0896 SOA3D<Precision> const &__restrict__ globaldirs,
0897 Precision const *__restrict__ step_limit,
0898 NavigationState const *const *__restrict__ in_states,
0899 NavigationState **__restrict__ out_states,
0900 Precision *__restrict__ out_steps) const override
0901 {
0902 for (unsigned int i = 0; i < globalpoints.size(); ++i) {
0903 out_steps[i] = ((Impl *)this)
0904 ->Impl::ComputeStepAndPropagatedState(globalpoints[i], globaldirs[i], step_limit[i],
0905 *in_states[i], *out_states[i]);
0906 }
0907 }
0908
0909 VECCORE_ATT_HOST_DEVICE
0910 virtual void ComputeStepsAndSafetiesAndPropagatedStates(
0911 SOA3D<Precision> const &__restrict__ globalpoints, SOA3D<Precision> const &__restrict__ globaldirs,
0912 Precision const *__restrict__ step_limit, NavigationState const *const *__restrict__ in_states,
0913 NavigationState **__restrict__ out_states, Precision *__restrict__ out_steps,
0914 bool const *__restrict__ calcsafeties, Precision *__restrict__ out_safeties) const override
0915 {
0916
0917 for (unsigned int i = 0; i < globalpoints.size(); ++i) {
0918 out_steps[i] = ((Impl *)this)
0919 ->Impl::ComputeStepAndSafetyAndPropagatedState(globalpoints[i], globaldirs[i], step_limit[i],
0920 *in_states[i], *out_states[i], calcsafeties[i],
0921 out_safeties[i]);
0922 }
0923 }
0924 #endif
0925
0926
0927
0928 VECCORE_ATT_HOST_DEVICE
0929 virtual Precision ComputeStepAndSafetyAndPropagatedState(Vector3D<Precision> const &globalpoint,
0930 Vector3D<Precision> const &globaldir, Precision step_limit,
0931 NavigationState const &__restrict__ in_state,
0932 NavigationState &__restrict__ out_state, bool calcsafety,
0933 Precision &safety_out) const override
0934 {
0935
0936 Vector3D<Precision> localpoint;
0937 Vector3D<Precision> localdir;
0938 Impl::DoGlobalToLocalTransformation(in_state, globalpoint, globaldir, localpoint, localdir);
0939
0940
0941 using SafetyE_t = typename Impl::SafetyEstimator_t;
0942 safety_out = 0.;
0943 if (calcsafety) {
0944
0945 safety_out = ((SafetyE_t *)fSafetyEstimator)->SafetyE_t::ComputeSafetyForLocalPoint(localpoint, in_state.Top());
0946 }
0947
0948 VPlacedVolume const *hitcandidate = nullptr;
0949 auto pvol = in_state.Top();
0950 auto lvol = pvol->GetLogicalVolume();
0951 Precision step = Impl::TreatDistanceToMother(pvol, localpoint, localdir, step_limit);;
0952 if (lvol->GetDaughters().size() > 0)
0953
0954 ((Impl *)this)
0955 ->Impl::CheckDaughterIntersections(lvol, localpoint, localdir, &in_state, &out_state, step, hitcandidate);
0956
0957
0958 bool done;
0959 step = Impl::PrepareOutState(in_state, out_state, step, step_limit, hitcandidate, done);
0960 if (done) return step;
0961
0962
0963 if (!out_state.IsOnBoundary()) return step;
0964
0965
0966
0967 ((Impl *)this)->Impl::Relocate(MovePointAfterBoundary(localpoint, localdir, step), in_state, out_state);
0968 return step;
0969 }
0970
0971 protected:
0972
0973 VECGEOM_FORCE_INLINE
0974 VECCORE_ATT_HOST_DEVICE
0975 virtual void Relocate(Vector3D<Precision> const &pointafterboundary, NavigationState const &__restrict__ in_state,
0976 NavigationState &__restrict__ out_state) const override
0977 {
0978
0979
0980 if (out_state.Top() == in_state.Top()) {
0981 GlobalLocator::RelocatePointFromPathForceDifferent(pointafterboundary, out_state);
0982 #ifdef CHECK_RELOCATION_ERRORS
0983 assert(in_state.Distance(out_state) != 0 && " error relocating when leaving ");
0984 #endif
0985 } else {
0986
0987 VPlacedVolume const *nextvol = out_state.Top();
0988 out_state.Pop();
0989 GlobalLocator::LocateGlobalPoint(nextvol, nextvol->GetTransformation()->Transform(pointafterboundary), out_state,
0990 false);
0991 #ifdef CHECK_RELOCATION_ERRORS
0992 assert(in_state.Distance(out_state) != 0 && " error relocating when entering ");
0993 #endif
0994 return;
0995 }
0996 }
0997
0998 public:
0999 static const char *GetClassName() { return Impl::gClassNameString; }
1000
1001 virtual const char *GetName() const override { return GetClassName(); }
1002 };
1003 }
1004 }
1005
1006 #endif