File indexing completed on 2025-12-29 09:46:59
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <VecGeom/base/Config.h>
0010 #include <VecGeom/base/Cuda.h>
0011 #include <VecGeom/base/Version.h>
0012 #include <VecGeom/navigation/NavStateFwd.h>
0013 #include <VecGeom/navigation/NavigationState.h>
0014 #include <VecGeom/volumes/LogicalVolume.h>
0015 #include <VecGeom/volumes/PlacedVolume.h>
0016
0017 #include "corecel/Config.hh"
0018
0019 #include "corecel/Macros.hh"
0020 #include "corecel/math/Algorithms.hh"
0021 #include "corecel/math/ArrayUtils.hh"
0022 #include "corecel/math/SoftEqual.hh"
0023 #include "corecel/sys/ThreadId.hh"
0024 #include "geocel/Types.hh"
0025
0026 #include "VecgeomData.hh"
0027
0028 #include "detail/VecgeomCompatibility.hh"
0029
0030 #ifdef VECGEOM_USE_SURF
0031 # include "detail/SurfNavigator.hh"
0032 #elif VECGEOM_VERSION >= 0x020000
0033 # include <VecGeom/navigation/BVHNavigator.h>
0034 #else
0035 # include "detail/BVHNavigator.hh"
0036 #endif
0037
0038 namespace celeritas
0039 {
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 class VecgeomTrackView
0055 {
0056 public:
0057
0058
0059 using Initializer_t = GeoTrackInitializer;
0060 using ParamsRef = NativeCRef<VecgeomParamsData>;
0061 using StateRef = NativeRef<VecgeomStateData>;
0062 #ifdef VECGEOM_USE_SURF
0063 using Navigator = celeritas::detail::SurfNavigator;
0064 #elif VECGEOM_VERSION >= 0x020000
0065 using Navigator = vecgeom::BVHNavigator;
0066 #else
0067 using Navigator = celeritas::detail::BVHNavigator;
0068 #endif
0069
0070
0071 public:
0072
0073 inline CELER_FUNCTION VecgeomTrackView(ParamsRef const& data,
0074 StateRef const& stateview,
0075 TrackSlotId tid);
0076
0077
0078 inline CELER_FUNCTION VecgeomTrackView&
0079 operator=(Initializer_t const& init);
0080
0081
0082
0083
0084 static CELER_CONSTEXPR_FUNCTION real_type extra_push() { return 1e-13; }
0085
0086
0087
0088
0089
0090 CELER_FORCEINLINE_FUNCTION Real3 const& pos() const { return pos_; }
0091 CELER_FORCEINLINE_FUNCTION Real3 const& dir() const { return dir_; }
0092
0093
0094
0095 inline CELER_FUNCTION VolumeId volume_id() const;
0096
0097 inline CELER_FUNCTION VolumeInstanceId volume_instance_id() const;
0098
0099 inline CELER_FUNCTION LevelId level() const;
0100
0101 inline CELER_FUNCTION void
0102 volume_instance_id(Span<VolumeInstanceId> levels) const;
0103
0104
0105 inline CELER_FUNCTION ImplSurfaceId impl_surface_id() const;
0106
0107 inline CELER_FUNCTION ImplSurfaceId next_impl_surface_id() const;
0108
0109
0110 CELER_FORCEINLINE_FUNCTION bool is_outside() const;
0111
0112 CELER_FORCEINLINE_FUNCTION bool is_on_boundary() const;
0113
0114 CELER_FORCEINLINE_FUNCTION bool failed() const { return false; }
0115
0116 inline CELER_FUNCTION Real3 normal() const;
0117
0118
0119
0120
0121 inline CELER_FUNCTION Propagation find_next_step();
0122
0123
0124 inline CELER_FUNCTION Propagation find_next_step(real_type max_step);
0125
0126
0127 inline CELER_FUNCTION real_type find_safety();
0128
0129
0130 inline CELER_FUNCTION real_type find_safety(real_type max_step);
0131
0132
0133 inline CELER_FUNCTION void move_to_boundary();
0134
0135
0136 inline CELER_FUNCTION void move_internal(real_type step);
0137
0138
0139 inline CELER_FUNCTION void move_internal(Real3 const& pos);
0140
0141
0142 inline CELER_FUNCTION void cross_boundary();
0143
0144
0145 inline CELER_FUNCTION void set_dir(Real3 const& newdir);
0146
0147 private:
0148
0149
0150 using Volume = vecgeom::LogicalVolume;
0151 using NavState = vecgeom::NavigationState;
0152
0153
0154
0155
0156 ParamsRef const& params_;
0157 StateRef const& state_;
0158 TrackSlotId tid_;
0159
0160
0161
0162 NavState& vgstate_;
0163 NavState& vgnext_;
0164 Real3& pos_;
0165 Real3& dir_;
0166 #ifdef VECGEOM_USE_SURF
0167 long& next_surface_;
0168 #endif
0169
0170
0171
0172 real_type next_step_{0};
0173
0174
0175
0176
0177 inline CELER_FUNCTION bool has_next_step() const;
0178
0179
0180 inline CELER_FUNCTION bool is_next_boundary() const;
0181
0182
0183 inline CELER_FUNCTION Volume const& volume() const;
0184
0185 #ifdef VECGEOM_USE_SURF
0186 static CELER_CONSTEXPR_FUNCTION long null_surface() { return -1; }
0187 #endif
0188 };
0189
0190
0191
0192
0193
0194
0195
0196 CELER_FUNCTION
0197 VecgeomTrackView::VecgeomTrackView(ParamsRef const& params,
0198 StateRef const& states,
0199 TrackSlotId tid)
0200 : params_(params)
0201 , state_(states)
0202 , tid_(tid)
0203 , vgstate_(states.vgstate.at(params_.max_depth, tid))
0204 , vgnext_(states.vgnext.at(params_.max_depth, tid))
0205 , pos_(states.pos[tid])
0206 , dir_(states.dir[tid])
0207 #ifdef VECGEOM_USE_SURF
0208 , next_surface_{states.next_surface[tid]}
0209 #endif
0210 {
0211 }
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 CELER_FUNCTION VecgeomTrackView&
0226 VecgeomTrackView::operator=(Initializer_t const& init)
0227 {
0228 CELER_EXPECT(is_soft_unit_vector(init.dir));
0229
0230
0231 dir_ = init.dir;
0232
0233 if (init.parent)
0234 {
0235
0236 if (tid_ != init.parent)
0237 {
0238 VecgeomTrackView other(params_, state_, init.parent);
0239 other.vgstate_.CopyTo(&vgstate_);
0240 pos_ = other.pos_;
0241 }
0242
0243 vgnext_ = vgstate_;
0244
0245 CELER_ENSURE(this->pos() == init.pos);
0246 CELER_ENSURE(!this->has_next_step());
0247 return *this;
0248 }
0249
0250
0251 pos_ = init.pos;
0252 #ifdef VECGEOM_USE_SURF
0253 next_surface_ = null_surface();
0254 #endif
0255
0256
0257 vgstate_.Clear();
0258 constexpr bool contains_point = true;
0259 #ifdef VECGEOM_USE_SURF
0260 auto world = vecgeom::NavigationState::WorldId();
0261 #else
0262 vecgeom::VPlacedVolume const* world = params_.world_volume;
0263 #endif
0264
0265 Navigator::LocatePointIn(
0266 world, detail::to_vector(pos_), vgstate_, contains_point);
0267 return *this;
0268 }
0269
0270
0271
0272
0273
0274 CELER_FUNCTION ImplSurfaceId VecgeomTrackView::impl_surface_id() const
0275 {
0276 #ifdef VECGEOM_USE_SURF
0277 if (this->is_on_boundary())
0278 {
0279 return id_cast<ImplSurfaceId>(next_surface_);
0280 }
0281 return {};
0282 #else
0283 CELER_ASSERT_UNREACHABLE();
0284 #endif
0285 }
0286
0287
0288
0289
0290
0291 CELER_FUNCTION ImplSurfaceId VecgeomTrackView::next_impl_surface_id() const
0292 {
0293 #ifdef VECGEOM_USE_SURF
0294 if (!this->is_on_boundary())
0295 {
0296 return id_cast<ImplSurfaceId>(next_surface_);
0297 }
0298 return {};
0299 #else
0300 CELER_ASSERT_UNREACHABLE();
0301 #endif
0302 }
0303
0304
0305
0306
0307
0308 CELER_FORCEINLINE_FUNCTION VolumeId VecgeomTrackView::volume_id() const
0309 {
0310 CELER_EXPECT(!this->is_outside());
0311 return id_cast<VolumeId>(this->volume().id());
0312 }
0313
0314
0315
0316
0317
0318 CELER_FUNCTION VolumeInstanceId VecgeomTrackView::volume_instance_id() const
0319 {
0320 CELER_EXPECT(!this->is_outside());
0321 vecgeom::VPlacedVolume const* top = vgstate_.Top();
0322 CELER_ASSERT(top);
0323 return id_cast<VolumeInstanceId>(top->id());
0324 }
0325
0326
0327
0328
0329
0330 CELER_FUNCTION LevelId VecgeomTrackView::level() const
0331 {
0332 return id_cast<LevelId>(vgstate_.GetLevel());
0333 }
0334
0335
0336
0337
0338
0339 CELER_FUNCTION void
0340 VecgeomTrackView::volume_instance_id(Span<VolumeInstanceId> levels) const
0341 {
0342 CELER_EXPECT(levels.size() == this->level().get() + 1);
0343 for (auto lev : range(levels.size()))
0344 {
0345 vecgeom::VPlacedVolume const* pv = vgstate_.At(lev);
0346 CELER_ASSERT(pv);
0347 levels[lev] = id_cast<VolumeInstanceId>(vgstate_.At(lev)->id());
0348 }
0349 }
0350
0351
0352
0353
0354
0355 CELER_FUNCTION bool VecgeomTrackView::is_outside() const
0356 {
0357 return vgstate_.IsOutside();
0358 }
0359
0360
0361
0362
0363
0364 CELER_FUNCTION bool VecgeomTrackView::is_on_boundary() const
0365 {
0366 return vgstate_.IsOnBoundary();
0367 }
0368
0369
0370
0371
0372
0373 CELER_FUNCTION Real3 VecgeomTrackView::normal() const
0374 {
0375 CELER_NOT_IMPLEMENTED("VecgeomTrackView::normal");
0376 }
0377
0378
0379
0380
0381
0382
0383
0384 CELER_FUNCTION Propagation VecgeomTrackView::find_next_step()
0385 {
0386 if (this->is_outside())
0387 {
0388
0389 auto* pplvol = params_.world_volume;
0390 next_step_ = pplvol->DistanceToIn(detail::to_vector(pos_),
0391 detail::to_vector(dir_),
0392 vecgeom::kInfLength);
0393
0394 next_step_ = max(next_step_, this->extra_push());
0395 vgnext_.Clear();
0396 Propagation result;
0397 result.distance = next_step_;
0398 result.boundary = next_step_ < vecgeom::kInfLength;
0399
0400 if (result.boundary)
0401 {
0402 vgnext_.Push(pplvol);
0403 vgnext_.SetBoundaryState(true);
0404 }
0405
0406 return result;
0407 }
0408
0409 return this->find_next_step(vecgeom::kInfLength);
0410 }
0411
0412
0413
0414
0415
0416 CELER_FUNCTION Propagation VecgeomTrackView::find_next_step(real_type max_step)
0417 {
0418 CELER_EXPECT(!this->is_outside());
0419 CELER_EXPECT(max_step > 0);
0420
0421 #ifdef VECGEOM_USE_SURF
0422
0423 next_surface_ = null_surface();
0424 #endif
0425
0426 next_step_ = Navigator::ComputeStepAndNextVolume(detail::to_vector(pos_),
0427 detail::to_vector(dir_),
0428 max_step,
0429 vgstate_,
0430 vgnext_
0431 #ifdef VECGEOM_USE_SURF
0432 ,
0433 next_surface_
0434 #endif
0435 );
0436 next_step_ = max(next_step_, this->extra_push());
0437
0438 if (!this->is_next_boundary())
0439 {
0440
0441
0442
0443 CELER_ASSERT(soft_equal(next_step_, max_step));
0444 next_step_ = max_step;
0445 }
0446
0447 Propagation result;
0448 result.distance = next_step_;
0449 result.boundary = this->is_next_boundary();
0450
0451 CELER_ENSURE(this->has_next_step());
0452 CELER_ENSURE(result.distance > 0);
0453 CELER_ENSURE(result.distance <= max(max_step, this->extra_push()));
0454 CELER_ENSURE(result.boundary || result.distance == max_step
0455 || max_step < this->extra_push());
0456 return result;
0457 }
0458
0459
0460
0461
0462
0463 CELER_FUNCTION real_type VecgeomTrackView::find_safety()
0464 {
0465 return this->find_safety(vecgeom::kInfLength);
0466 }
0467
0468
0469
0470
0471
0472
0473
0474
0475 CELER_FUNCTION real_type VecgeomTrackView::find_safety(real_type max_radius)
0476 {
0477 CELER_EXPECT(!this->is_outside());
0478 CELER_EXPECT(!this->is_on_boundary());
0479 CELER_EXPECT(max_radius > 0);
0480
0481 real_type safety = Navigator::ComputeSafety(detail::to_vector(this->pos()),
0482 vgstate_
0483 #if VECGEOM_VERSION >= 0x200000
0484 ,
0485 max_radius
0486 #endif
0487 );
0488 safety = min<real_type>(safety, max_radius);
0489
0490
0491
0492 return max<real_type>(safety, 0);
0493 }
0494
0495
0496
0497
0498
0499 CELER_FUNCTION void VecgeomTrackView::move_to_boundary()
0500 {
0501 CELER_EXPECT(this->has_next_step());
0502 CELER_EXPECT(this->is_next_boundary());
0503
0504
0505 axpy(next_step_, dir_, &pos_);
0506 next_step_ = 0;
0507 vgstate_.SetBoundaryState(true);
0508
0509 CELER_ENSURE(this->is_on_boundary());
0510 }
0511
0512
0513
0514
0515
0516
0517
0518 CELER_FUNCTION void VecgeomTrackView::cross_boundary()
0519 {
0520 CELER_EXPECT(this->is_on_boundary());
0521 CELER_EXPECT(this->is_next_boundary());
0522
0523
0524 if (vgnext_.Top() != nullptr)
0525 {
0526 #ifdef VECGEOM_USE_SURF
0527 if (!vgstate_.IsOutside())
0528 {
0529
0530
0531 Navigator::RelocateToNextVolume(detail::to_vector(this->pos_),
0532 detail::to_vector(this->dir_),
0533 next_surface_,
0534 vgnext_);
0535 }
0536 #else
0537
0538 auto temp_pos = detail::to_vector(this->pos_);
0539 Navigator::RelocateToNextVolume(
0540 temp_pos, detail::to_vector(this->dir_), vgnext_);
0541 #endif
0542 }
0543
0544 vgstate_ = vgnext_;
0545
0546 CELER_ENSURE(this->is_on_boundary());
0547 }
0548
0549
0550
0551
0552
0553
0554
0555
0556 CELER_FUNCTION void VecgeomTrackView::move_internal(real_type dist)
0557 {
0558 CELER_EXPECT(this->has_next_step());
0559 CELER_EXPECT(dist > 0 && dist <= next_step_);
0560 CELER_EXPECT(dist != next_step_ || !this->is_next_boundary());
0561
0562
0563 axpy(dist, dir_, &pos_);
0564 next_step_ -= dist;
0565 vgstate_.SetBoundaryState(false);
0566
0567 CELER_ENSURE(!this->is_on_boundary());
0568 }
0569
0570
0571
0572
0573
0574
0575
0576
0577 CELER_FUNCTION void VecgeomTrackView::move_internal(Real3 const& pos)
0578 {
0579 pos_ = pos;
0580 next_step_ = 0;
0581 vgstate_.SetBoundaryState(false);
0582
0583 CELER_ENSURE(!this->is_on_boundary());
0584 }
0585
0586
0587
0588
0589
0590
0591
0592
0593 CELER_FUNCTION void VecgeomTrackView::set_dir(Real3 const& newdir)
0594 {
0595 CELER_EXPECT(is_soft_unit_vector(newdir));
0596 dir_ = newdir;
0597 next_step_ = 0;
0598 }
0599
0600
0601
0602
0603
0604
0605
0606 CELER_FUNCTION bool VecgeomTrackView::has_next_step() const
0607 {
0608 return next_step_ != 0;
0609 }
0610
0611
0612
0613
0614
0615 CELER_FUNCTION bool VecgeomTrackView::is_next_boundary() const
0616 {
0617 CELER_EXPECT(this->has_next_step() || this->is_on_boundary());
0618 return vgnext_.IsOnBoundary();
0619 }
0620
0621
0622
0623
0624
0625 CELER_FUNCTION auto VecgeomTrackView::volume() const -> Volume const&
0626 {
0627 vecgeom::VPlacedVolume const* physvol_ptr = vgstate_.Top();
0628 CELER_ENSURE(physvol_ptr);
0629 return *physvol_ptr->GetLogicalVolume();
0630 }
0631
0632
0633 }