File indexing completed on 2026-11-09 10:21:12
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Config.hh"
0010
0011 #if CELERITAS_VECGEOM_VERSION < 0x020200
0012 # error "This file requires VecGeom 2.2+"
0013 #endif
0014
0015 #include <VecGeom/navigation/NavView.h>
0016
0017 #include "corecel/Assert.hh"
0018 #include "corecel/Macros.hh"
0019 #include "corecel/Types.hh"
0020 #include "corecel/cont/Span.hh"
0021 #include "corecel/math/ArraySoftUnit.hh"
0022 #include "corecel/sys/ThreadId.hh"
0023 #include "geocel/Types.hh"
0024
0025 #include "VecgeomData.hh"
0026 #include "VecgeomTypes.hh"
0027
0028 #if !CELER_DEVICE_COMPILE
0029 # include "corecel/io/Logger.hh"
0030 # include "corecel/io/Repr.hh"
0031 # include "geocel/detail/LengthUnits.hh"
0032 #endif
0033
0034 namespace celeritas
0035 {
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 class VgBasicTrackView
0059 {
0060 public:
0061
0062
0063 using Initializer_t = GeoTrackInitializer;
0064 using ParamsRef = NativeCRef<VecgeomParamsData>;
0065 using StateRef = NativeRef<VecgeomStateData>;
0066 using NavView = vecgeom::NavView;
0067 using OpaquePath = NavView::OpaquePath;
0068 using real_type = vg_real_type;
0069 using ImplVolInstanceId = VgVolumeInstanceId;
0070
0071
0072 public:
0073
0074 inline CELER_FUNCTION VgBasicTrackView(
0075 ParamsRef const& data, StateRef const& stateview, TrackSlotId tid);
0076
0077
0078 inline CELER_FUNCTION VgBasicTrackView& operator=(
0079 Initializer_t const& init);
0080
0081
0082
0083
0084
0085 CELER_FORCEINLINE_FUNCTION Real3 const& pos() const { return pos_; }
0086 CELER_FORCEINLINE_FUNCTION Real3 const& dir() const { return dir_; }
0087
0088
0089
0090 inline CELER_FUNCTION VolumeId volume_id() const;
0091
0092 inline CELER_FUNCTION VolumeInstanceId volume_instance_id() const;
0093
0094 inline CELER_FUNCTION VolumeLevelId volume_level() const;
0095
0096 inline CELER_FUNCTION void volume_instance_id(
0097 Span<VolumeInstanceId> levels) const;
0098
0099 template<class F>
0100 inline CELER_FUNCTION void foreach_volume_path(F&& visit) const;
0101
0102
0103 inline CELER_FUNCTION ImplVolumeId impl_volume_id() const;
0104
0105
0106 inline CELER_FUNCTION OpaquePath opaque_path() const;
0107
0108
0109 inline CELER_FUNCTION bool is_outside() const;
0110
0111 inline CELER_FUNCTION bool is_on_boundary() const;
0112
0113 CELER_FORCEINLINE_FUNCTION bool failed() const { return failed_; }
0114
0115 inline CELER_FUNCTION Real3 normal() const;
0116
0117
0118
0119
0120 inline CELER_FUNCTION Propagation find_next_step(real_type max_step);
0121
0122
0123 inline CELER_FUNCTION real_type find_safety(real_type max_step);
0124
0125
0126 inline CELER_FUNCTION void move_to_boundary(real_type step);
0127
0128
0129 inline CELER_FUNCTION void move_internal(real_type step);
0130
0131
0132 inline CELER_FUNCTION void move_internal(Real3 const& pos);
0133
0134
0135 inline CELER_FUNCTION void cross_boundary();
0136
0137
0138 inline CELER_FUNCTION void set_dir(Real3 const& newdir);
0139
0140 private:
0141
0142
0143 using VgLogVol = VgLogicalVolume<MemSpace::native>;
0144 using VgPlacedVol = VgPlacedVolume<MemSpace::native>;
0145
0146
0147
0148
0149 ParamsRef const& params_;
0150 StateRef const& state_;
0151 TrackSlotId tid_;
0152
0153
0154
0155 VgNavState& vgstate_;
0156 VgNavState& vgnext_;
0157 Real3& pos_;
0158 Real3& dir_;
0159
0160
0161
0162
0163 bool failed_{false};
0164
0165
0166
0167 struct LocalNavData;
0168 class LocalNav;
0169
0170
0171
0172
0173 inline CELER_FUNCTION bool is_next_boundary() const;
0174
0175
0176 inline CELER_FUNCTION VgPlacedVol const& physical_volume() const;
0177
0178
0179 inline CELER_FUNCTION VgLogVol const& logical_volume() const;
0180
0181
0182 inline CELER_FUNCTION LocalNav make_nav() const;
0183 };
0184
0185
0186
0187
0188
0189
0190 struct VgBasicTrackView::LocalNavData
0191 {
0192 NavView::NavSetupT nav_params;
0193 VgReal3 temp_pos;
0194 VgReal3 temp_dir;
0195 };
0196
0197 class VgBasicTrackView::LocalNav : public LocalNavData, public vecgeom::NavView
0198 {
0199 public:
0200 explicit CELER_FUNCTION LocalNav(VgBasicTrackView& vtv)
0201 : LocalNavData{{vtv.params_.scalars.world<MemSpace::native>()},
0202 to_vgvector(vtv.pos_),
0203 to_vgvector(vtv.dir_)}
0204 , NavView{this->nav_params,
0205 vtv.vgstate_,
0206 vtv.vgnext_,
0207 this->temp_pos,
0208 this->temp_dir}
0209 {
0210 }
0211 };
0212
0213
0214
0215
0216
0217
0218
0219 CELER_FUNCTION VgBasicTrackView::VgBasicTrackView(
0220 ParamsRef const& params, StateRef const& states, TrackSlotId tid)
0221 : params_(params)
0222 , state_(states)
0223 , tid_(tid)
0224 , vgstate_{states.state[tid]}
0225 , vgnext_{states.next_state[tid]}
0226 , pos_(states.pos[tid])
0227 , dir_(states.dir[tid])
0228 {
0229 }
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 CELER_FUNCTION VgBasicTrackView& VgBasicTrackView::operator=(
0244 Initializer_t const& init)
0245 {
0246 CELER_EXPECT(is_soft_unit_vector(init.dir));
0247 failed_ = false;
0248
0249
0250 dir_ = init.dir;
0251 pos_ = init.pos;
0252 auto nav = this->make_nav();
0253 if (init.parent)
0254 {
0255 VgBasicTrackView other(params_, state_, init.parent);
0256 nav.Initialize(
0257 vecgeom::FullPath{other.opaque_path(), other.is_on_boundary()},
0258 nav.temp_pos,
0259 nav.temp_dir);
0260 }
0261 else
0262 {
0263 nav.Initialize(vecgeom::UnknownPath{}, nav.temp_pos, nav.temp_dir);
0264 }
0265
0266 if (CELER_UNLIKELY(nav.IsOutside()))
0267 {
0268 #if !CELER_DEVICE_COMPILE
0269 auto msg = CELER_LOG_LOCAL(error);
0270 msg << "Failed to initialize geometry state at " << repr(pos_) << ' '
0271 << lengthunits::native_label;
0272 #endif
0273 failed_ = true;
0274 }
0275
0276 CELER_ENSURE(this->dir() == to_array(nav.GetDirection()));
0277 CELER_ENSURE(this->pos() == to_array(nav.GetPosition()));
0278 return *this;
0279 }
0280
0281
0282
0283
0284
0285 CELER_FORCEINLINE_FUNCTION ImplVolumeId VgBasicTrackView::impl_volume_id() const
0286 {
0287 CELER_EXPECT(!this->is_outside());
0288 return id_cast<ImplVolumeId>(this->logical_volume().id());
0289 }
0290
0291
0292
0293
0294
0295 CELER_FORCEINLINE_FUNCTION auto VgBasicTrackView::opaque_path() const
0296 -> OpaquePath
0297 {
0298 return this->make_nav().GetOpaquePath();
0299 }
0300
0301
0302
0303
0304
0305 CELER_FORCEINLINE_FUNCTION bool VgBasicTrackView::is_outside() const
0306 {
0307 return vgstate_.IsOutside();
0308 }
0309
0310
0311
0312
0313
0314 CELER_FORCEINLINE_FUNCTION bool VgBasicTrackView::is_on_boundary() const
0315 {
0316 return vgstate_.IsOnBoundary();
0317 }
0318
0319
0320
0321
0322
0323 CELER_FORCEINLINE_FUNCTION Real3 VgBasicTrackView::normal() const
0324 {
0325
0326 CELER_NOT_IMPLEMENTED("calculating surface normal");
0327 }
0328
0329
0330
0331
0332
0333 CELER_FUNCTION Propagation VgBasicTrackView::find_next_step(real_type max_step)
0334 {
0335 CELER_EXPECT(!this->is_outside());
0336 CELER_EXPECT(max_step > 0);
0337
0338 using Kind = vecgeom::NavFindResultKind;
0339
0340 auto found = this->make_nav().FindNextBoundary(max_step);
0341
0342 Propagation result;
0343 if (found.GetKind() == Kind::hit)
0344 {
0345 result.distance = found.GetDistance();
0346 result.boundary = true;
0347 CELER_ASSERT(found.GetDistance() < max_step);
0348 }
0349 else if (found.GetKind() == Kind::miss)
0350 {
0351 result.distance = max_step;
0352 result.boundary = false;
0353 }
0354 else if (found.GetKind() == Kind::reentrant)
0355 {
0356 result.distance = 0;
0357 result.boundary = true;
0358 }
0359 else if (CELER_UNLIKELY(found.GetKind() == Kind::error))
0360 {
0361 #if !CELER_DEVICE_COMPILE
0362 auto msg = CELER_LOG_LOCAL(debug);
0363 msg << "Failed to find next step at " << repr(pos_) << ' '
0364 << lengthunits::native_label << " along " << repr(dir_);
0365 #endif
0366 failed_ = true;
0367 result.distance = 0;
0368 result.boundary = true;
0369 }
0370 else
0371 {
0372 CELER_ASSERT_UNREACHABLE();
0373 }
0374
0375 CELER_ENSURE(result.distance >= 0 && result.distance <= max_step);
0376 return result;
0377 }
0378
0379
0380
0381
0382
0383
0384
0385
0386 CELER_FUNCTION real_type VgBasicTrackView::find_safety(real_type max_radius)
0387 {
0388 CELER_EXPECT(!this->is_outside());
0389 CELER_EXPECT(!this->is_on_boundary());
0390 CELER_EXPECT(max_radius > 0);
0391
0392 auto safety = this->make_nav().FindSafety(max_radius);
0393 CELER_ENSURE(safety >= 0 && safety <= max_radius);
0394 return safety;
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405 CELER_FUNCTION void VgBasicTrackView::move_to_boundary(real_type dist)
0406 {
0407 CELER_EXPECT(dist >= 0);
0408 CELER_EXPECT(!this->is_outside());
0409 CELER_EXPECT(this->is_next_boundary());
0410
0411 auto nav = this->make_nav();
0412 nav.MoveToBoundary(dist);
0413 pos_ = to_array(nav.GetPosition());
0414 CELER_ENSURE(this->is_on_boundary());
0415 }
0416
0417
0418
0419
0420
0421
0422
0423 CELER_FUNCTION void VgBasicTrackView::cross_boundary()
0424 {
0425 CELER_EXPECT(!this->is_outside());
0426 CELER_EXPECT(this->is_on_boundary());
0427 CELER_EXPECT(this->is_next_boundary());
0428
0429 this->make_nav().CrossBoundary();
0430 CELER_ENSURE(this->is_on_boundary());
0431 }
0432
0433
0434
0435
0436
0437
0438
0439
0440 CELER_FUNCTION void VgBasicTrackView::move_internal(real_type dist)
0441 {
0442 CELER_EXPECT(dist > 0);
0443
0444 auto nav = this->make_nav();
0445 nav.MoveInternal(dist);
0446 pos_ = to_array(nav.GetPosition());
0447
0448 CELER_ENSURE(!this->is_on_boundary());
0449 }
0450
0451
0452
0453
0454
0455
0456
0457
0458 CELER_FUNCTION void VgBasicTrackView::move_internal(Real3 const& pos)
0459 {
0460 pos_ = pos;
0461 auto nav = this->make_nav();
0462 nav.MoveInternal(to_vgvector(pos));
0463 pos_ = to_array(nav.GetPosition());
0464 CELER_ENSURE(!this->is_on_boundary());
0465 }
0466
0467
0468
0469
0470
0471
0472
0473
0474 CELER_FUNCTION void VgBasicTrackView::set_dir(Real3 const& newdir)
0475 {
0476 CELER_EXPECT(is_soft_unit_vector(newdir));
0477 auto nav = this->make_nav();
0478 nav.ChangeDirection(to_vgvector(newdir));
0479 dir_ = to_array(nav.GetDirection());
0480 }
0481
0482
0483
0484
0485
0486
0487
0488 CELER_FORCEINLINE_FUNCTION bool VgBasicTrackView::is_next_boundary() const
0489 {
0490 return vgnext_.IsOnBoundary();
0491 }
0492
0493
0494
0495
0496
0497 CELER_FUNCTION auto VgBasicTrackView::physical_volume() const
0498 -> VgPlacedVol const&
0499 {
0500 VgPlacedVol const* physvol_ptr = vgstate_.Top();
0501 CELER_ENSURE(physvol_ptr);
0502 return *physvol_ptr;
0503 }
0504
0505
0506
0507
0508
0509 CELER_FORCEINLINE_FUNCTION auto VgBasicTrackView::logical_volume() const
0510 -> VgLogVol const&
0511 {
0512 return *this->physical_volume().GetLogicalVolume();
0513 }
0514
0515
0516 CELER_FUNCTION auto VgBasicTrackView::make_nav() const -> LocalNav
0517 {
0518 return LocalNav{const_cast<VgBasicTrackView&>(*this)};
0519 }
0520
0521
0522 }