File indexing completed on 2025-10-29 08:44: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
0072 struct DetailedInitializer
0073 {
0074 VecgeomTrackView const& other;
0075 Real3 const& dir;
0076 };
0077
0078 public:
0079
0080 inline CELER_FUNCTION VecgeomTrackView(ParamsRef const& data,
0081 StateRef const& stateview,
0082 TrackSlotId tid);
0083
0084
0085 inline CELER_FUNCTION VecgeomTrackView&
0086 operator=(Initializer_t const& init);
0087
0088 inline CELER_FUNCTION VecgeomTrackView&
0089 operator=(DetailedInitializer const& init);
0090
0091
0092
0093
0094 static CELER_CONSTEXPR_FUNCTION real_type extra_push() { return 1e-13; }
0095
0096
0097
0098
0099
0100 CELER_FORCEINLINE_FUNCTION Real3 const& pos() const { return pos_; }
0101 CELER_FORCEINLINE_FUNCTION Real3 const& dir() const { return dir_; }
0102
0103
0104
0105 inline CELER_FUNCTION VolumeId volume_id() const;
0106
0107 inline CELER_FUNCTION VolumeInstanceId volume_instance_id() const;
0108
0109 inline CELER_FUNCTION LevelId level() const;
0110
0111 inline CELER_FUNCTION void
0112 volume_instance_id(Span<VolumeInstanceId> levels) const;
0113
0114
0115
0116 CELER_FUNCTION SurfaceId surface_id() const { return {}; }
0117
0118
0119
0120 CELER_FORCEINLINE_FUNCTION bool is_outside() const;
0121
0122 CELER_FORCEINLINE_FUNCTION bool is_on_boundary() const;
0123
0124 CELER_FORCEINLINE_FUNCTION bool failed() const { return false; }
0125
0126
0127
0128
0129 inline CELER_FUNCTION Propagation find_next_step();
0130
0131
0132 inline CELER_FUNCTION Propagation find_next_step(real_type max_step);
0133
0134
0135 inline CELER_FUNCTION real_type find_safety();
0136
0137
0138 inline CELER_FUNCTION real_type find_safety(real_type max_step);
0139
0140
0141 inline CELER_FUNCTION void move_to_boundary();
0142
0143
0144 inline CELER_FUNCTION void move_internal(real_type step);
0145
0146
0147 inline CELER_FUNCTION void move_internal(Real3 const& pos);
0148
0149
0150 inline CELER_FUNCTION void cross_boundary();
0151
0152
0153 inline CELER_FUNCTION void set_dir(Real3 const& newdir);
0154
0155 private:
0156
0157
0158 using Volume = vecgeom::LogicalVolume;
0159 using NavState = vecgeom::NavigationState;
0160
0161
0162
0163
0164 ParamsRef const& params_;
0165
0166
0167
0168 NavState& vgstate_;
0169 NavState& vgnext_;
0170 Real3& pos_;
0171 Real3& dir_;
0172 #ifdef VECGEOM_USE_SURF
0173 long& next_surface_;
0174 #endif
0175
0176
0177
0178 real_type next_step_{0};
0179
0180
0181
0182
0183 inline CELER_FUNCTION bool has_next_step() const;
0184
0185
0186 inline CELER_FUNCTION bool is_next_boundary() const;
0187
0188
0189 inline CELER_FUNCTION Volume const& volume() const;
0190
0191 #ifdef VECGEOM_USE_SURF
0192 static CELER_CONSTEXPR_FUNCTION long null_surface() { return -1; }
0193 #endif
0194 };
0195
0196
0197
0198
0199
0200
0201
0202 CELER_FUNCTION
0203 VecgeomTrackView::VecgeomTrackView(ParamsRef const& params,
0204 StateRef const& states,
0205 TrackSlotId tid)
0206 : params_(params)
0207 , vgstate_(states.vgstate.at(params_.max_depth, tid))
0208 , vgnext_(states.vgnext.at(params_.max_depth, tid))
0209 , pos_(states.pos[tid])
0210 , dir_(states.dir[tid])
0211 #ifdef VECGEOM_USE_SURF
0212 , next_surface_{states.next_surface[tid]}
0213 #endif
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 pos_ = init.pos;
0232 dir_ = init.dir;
0233 #ifdef VECGEOM_USE_SURF
0234 next_surface_ = null_surface();
0235 #endif
0236
0237
0238 vgstate_.Clear();
0239 constexpr bool contains_point = true;
0240 #ifdef VECGEOM_USE_SURF
0241 auto world = vecgeom::NavigationState::WorldId();
0242 #else
0243 vecgeom::VPlacedVolume const* world = params_.world_volume;
0244 #endif
0245
0246 Navigator::LocatePointIn(
0247 world, detail::to_vector(pos_), vgstate_, contains_point);
0248 return *this;
0249 }
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 CELER_FUNCTION
0260 VecgeomTrackView& VecgeomTrackView::operator=(DetailedInitializer const& init)
0261 {
0262 CELER_EXPECT(is_soft_unit_vector(init.dir));
0263
0264 if (this != &init.other)
0265 {
0266
0267 init.other.vgstate_.CopyTo(&vgstate_);
0268 pos_ = init.other.pos_;
0269 }
0270
0271
0272 vgnext_ = vgstate_;
0273 dir_ = init.dir;
0274
0275 CELER_ENSURE(!this->has_next_step());
0276 return *this;
0277 }
0278
0279
0280
0281
0282
0283 CELER_FORCEINLINE_FUNCTION VolumeId VecgeomTrackView::volume_id() const
0284 {
0285 CELER_EXPECT(!this->is_outside());
0286 return id_cast<VolumeId>(this->volume().id());
0287 }
0288
0289
0290
0291
0292
0293 CELER_FUNCTION VolumeInstanceId VecgeomTrackView::volume_instance_id() const
0294 {
0295 CELER_EXPECT(!this->is_outside());
0296 vecgeom::VPlacedVolume const* top = vgstate_.Top();
0297 CELER_ASSERT(top);
0298 return id_cast<VolumeInstanceId>(top->id());
0299 }
0300
0301
0302
0303
0304
0305 CELER_FUNCTION LevelId VecgeomTrackView::level() const
0306 {
0307 return id_cast<LevelId>(vgstate_.GetLevel());
0308 }
0309
0310
0311
0312
0313
0314 CELER_FUNCTION void
0315 VecgeomTrackView::volume_instance_id(Span<VolumeInstanceId> levels) const
0316 {
0317 CELER_EXPECT(levels.size() == this->level().get() + 1);
0318 for (auto lev : range(levels.size()))
0319 {
0320 vecgeom::VPlacedVolume const* pv = vgstate_.At(lev);
0321 CELER_ASSERT(pv);
0322 levels[lev] = id_cast<VolumeInstanceId>(vgstate_.At(lev)->id());
0323 }
0324 }
0325
0326
0327
0328
0329
0330 CELER_FUNCTION bool VecgeomTrackView::is_outside() const
0331 {
0332 return vgstate_.IsOutside();
0333 }
0334
0335
0336
0337
0338
0339 CELER_FUNCTION bool VecgeomTrackView::is_on_boundary() const
0340 {
0341 return vgstate_.IsOnBoundary();
0342 }
0343
0344
0345
0346
0347
0348
0349
0350 CELER_FUNCTION Propagation VecgeomTrackView::find_next_step()
0351 {
0352 if (this->is_outside())
0353 {
0354
0355 auto* pplvol = params_.world_volume;
0356 next_step_ = pplvol->DistanceToIn(detail::to_vector(pos_),
0357 detail::to_vector(dir_),
0358 vecgeom::kInfLength);
0359
0360 next_step_ = max(next_step_, this->extra_push());
0361 vgnext_.Clear();
0362 Propagation result;
0363 result.distance = next_step_;
0364 result.boundary = next_step_ < vecgeom::kInfLength;
0365
0366 if (result.boundary)
0367 {
0368 vgnext_.Push(pplvol);
0369 vgnext_.SetBoundaryState(true);
0370 }
0371
0372 return result;
0373 }
0374
0375 return this->find_next_step(vecgeom::kInfLength);
0376 }
0377
0378
0379
0380
0381
0382 CELER_FUNCTION Propagation VecgeomTrackView::find_next_step(real_type max_step)
0383 {
0384 CELER_EXPECT(!this->is_outside());
0385 CELER_EXPECT(max_step > 0);
0386
0387 #ifdef VECGEOM_USE_SURF
0388
0389 next_surface_ = null_surface();
0390 #endif
0391
0392 next_step_ = Navigator::ComputeStepAndNextVolume(detail::to_vector(pos_),
0393 detail::to_vector(dir_),
0394 max_step,
0395 vgstate_,
0396 vgnext_
0397 #ifdef VECGEOM_USE_SURF
0398 ,
0399 next_surface_
0400 #endif
0401 );
0402 next_step_ = max(next_step_, this->extra_push());
0403
0404 if (!this->is_next_boundary())
0405 {
0406
0407
0408
0409 CELER_ASSERT(soft_equal(next_step_, max_step));
0410 next_step_ = max_step;
0411 }
0412
0413 Propagation result;
0414 result.distance = next_step_;
0415 result.boundary = this->is_next_boundary();
0416
0417 CELER_ENSURE(this->has_next_step());
0418 CELER_ENSURE(result.distance > 0);
0419 CELER_ENSURE(result.distance <= max(max_step, this->extra_push()));
0420 CELER_ENSURE(result.boundary || result.distance == max_step
0421 || max_step < this->extra_push());
0422 return result;
0423 }
0424
0425
0426
0427
0428
0429 CELER_FUNCTION real_type VecgeomTrackView::find_safety()
0430 {
0431 return this->find_safety(vecgeom::kInfLength);
0432 }
0433
0434
0435
0436
0437
0438
0439
0440
0441 CELER_FUNCTION real_type VecgeomTrackView::find_safety(real_type max_radius)
0442 {
0443 CELER_EXPECT(!this->is_outside());
0444 CELER_EXPECT(!this->is_on_boundary());
0445 CELER_EXPECT(max_radius > 0);
0446
0447 real_type safety = Navigator::ComputeSafety(detail::to_vector(this->pos()),
0448 vgstate_
0449 #if VECGEOM_VERSION >= 0x200000
0450 ,
0451 max_radius
0452 #endif
0453 );
0454 safety = min<real_type>(safety, max_radius);
0455
0456
0457
0458 return max<real_type>(safety, 0);
0459 }
0460
0461
0462
0463
0464
0465 CELER_FUNCTION void VecgeomTrackView::move_to_boundary()
0466 {
0467 CELER_EXPECT(this->has_next_step());
0468 CELER_EXPECT(this->is_next_boundary());
0469
0470
0471 axpy(next_step_, dir_, &pos_);
0472 next_step_ = 0;
0473 vgstate_.SetBoundaryState(true);
0474
0475 CELER_ENSURE(this->is_on_boundary());
0476 }
0477
0478
0479
0480
0481
0482
0483
0484 CELER_FUNCTION void VecgeomTrackView::cross_boundary()
0485 {
0486 CELER_EXPECT(this->is_on_boundary());
0487 CELER_EXPECT(this->is_next_boundary());
0488
0489
0490 if (vgnext_.Top() != nullptr)
0491 {
0492 #ifdef VECGEOM_USE_SURF
0493 if (!vgstate_.IsOutside())
0494 {
0495
0496
0497 Navigator::RelocateToNextVolume(detail::to_vector(this->pos_),
0498 detail::to_vector(this->dir_),
0499 next_surface_,
0500 vgnext_);
0501 }
0502 #else
0503
0504 auto temp_pos = detail::to_vector(this->pos_);
0505 Navigator::RelocateToNextVolume(
0506 temp_pos, detail::to_vector(this->dir_), vgnext_);
0507 #endif
0508 }
0509
0510 vgstate_ = vgnext_;
0511
0512 CELER_ENSURE(this->is_on_boundary());
0513 }
0514
0515
0516
0517
0518
0519
0520
0521
0522 CELER_FUNCTION void VecgeomTrackView::move_internal(real_type dist)
0523 {
0524 CELER_EXPECT(this->has_next_step());
0525 CELER_EXPECT(dist > 0 && dist <= next_step_);
0526 CELER_EXPECT(dist != next_step_ || !this->is_next_boundary());
0527
0528
0529 axpy(dist, dir_, &pos_);
0530 next_step_ -= dist;
0531 vgstate_.SetBoundaryState(false);
0532
0533 CELER_ENSURE(!this->is_on_boundary());
0534 }
0535
0536
0537
0538
0539
0540
0541
0542
0543 CELER_FUNCTION void VecgeomTrackView::move_internal(Real3 const& pos)
0544 {
0545 pos_ = pos;
0546 next_step_ = 0;
0547 vgstate_.SetBoundaryState(false);
0548
0549 CELER_ENSURE(!this->is_on_boundary());
0550 }
0551
0552
0553
0554
0555
0556
0557
0558
0559 CELER_FUNCTION void VecgeomTrackView::set_dir(Real3 const& newdir)
0560 {
0561 CELER_EXPECT(is_soft_unit_vector(newdir));
0562 dir_ = newdir;
0563 next_step_ = 0;
0564 }
0565
0566
0567
0568
0569
0570
0571
0572 CELER_FUNCTION bool VecgeomTrackView::has_next_step() const
0573 {
0574 return next_step_ != 0;
0575 }
0576
0577
0578
0579
0580
0581 CELER_FUNCTION bool VecgeomTrackView::is_next_boundary() const
0582 {
0583 CELER_EXPECT(this->has_next_step() || this->is_on_boundary());
0584 return vgnext_.IsOnBoundary();
0585 }
0586
0587
0588
0589
0590
0591 CELER_FUNCTION auto VecgeomTrackView::volume() const -> Volume const&
0592 {
0593 vecgeom::VPlacedVolume const* physvol_ptr = vgstate_.Top();
0594 CELER_ENSURE(physvol_ptr);
0595 return *physvol_ptr->GetLogicalVolume();
0596 }
0597
0598
0599 }