File indexing completed on 2026-01-07 10:14:33
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Macros.hh"
0010 #include "corecel/Types.hh"
0011 #include "corecel/cont/Array.hh"
0012 #include "corecel/math/Algorithms.hh"
0013 #include "corecel/sys/ThreadId.hh"
0014
0015 #include "LevelStateAccessor.hh"
0016 #include "OrangeData.hh"
0017 #include "OrangeTypes.hh"
0018 #include "transform/TransformVisitor.hh"
0019 #include "univ/SimpleUnitTracker.hh"
0020 #include "univ/TrackerVisitor.hh"
0021 #include "univ/UniverseTypeTraits.hh"
0022 #include "univ/detail/Types.hh"
0023
0024 #include "detail/UniverseIndexer.hh"
0025
0026 #if !CELER_DEVICE_COMPILE
0027 # include "corecel/io/Logger.hh"
0028 # include "corecel/io/Repr.hh"
0029 #endif
0030
0031 namespace celeritas
0032 {
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 class OrangeTrackView
0072 {
0073 public:
0074
0075
0076 using ParamsRef = NativeCRef<OrangeParamsData>;
0077 using StateRef = NativeRef<OrangeStateData>;
0078 using Initializer_t = GeoTrackInitializer;
0079
0080
0081 public:
0082
0083 inline CELER_FUNCTION OrangeTrackView(ParamsRef const& params,
0084 StateRef const& states,
0085 TrackSlotId tid);
0086
0087
0088 inline CELER_FUNCTION OrangeTrackView& operator=(Initializer_t const& init);
0089
0090
0091
0092
0093 inline CELER_FUNCTION Real3 const& pos() const;
0094
0095 inline CELER_FUNCTION Real3 const& dir() const;
0096
0097
0098 inline CELER_FUNCTION VolumeId volume_id() const;
0099
0100 inline CELER_FUNCTION VolumeInstanceId volume_instance_id() const;
0101
0102 inline CELER_FUNCTION LevelId const& level() const;
0103
0104 inline CELER_FUNCTION void volume_instance_id(Span<VolumeInstanceId>) const;
0105
0106
0107 inline CELER_FUNCTION ImplVolumeId impl_volume_id() const;
0108
0109 inline CELER_FUNCTION ImplSurfaceId impl_surface_id() const;
0110
0111 inline CELER_FUNCTION ImplSurfaceId next_impl_surface_id() const;
0112
0113
0114 inline CELER_FUNCTION bool is_outside() const;
0115
0116 inline CELER_FUNCTION bool is_on_boundary() const;
0117
0118 CELER_FORCEINLINE_FUNCTION bool failed() const { return failed_; }
0119
0120 inline CELER_FUNCTION Real3 normal() const;
0121
0122
0123
0124
0125 inline CELER_FUNCTION Propagation find_next_step();
0126
0127
0128 inline CELER_FUNCTION Propagation find_next_step(real_type max_step);
0129
0130
0131 inline CELER_FUNCTION real_type find_safety();
0132
0133
0134 inline CELER_FUNCTION real_type find_safety(real_type max_step);
0135
0136
0137 inline CELER_FUNCTION void move_to_boundary();
0138
0139
0140 inline CELER_FUNCTION void move_internal(real_type step);
0141
0142
0143 inline CELER_FUNCTION void move_internal(Real3 const& pos);
0144
0145
0146 inline CELER_FUNCTION void cross_boundary();
0147
0148
0149 inline CELER_FUNCTION void set_dir(Real3 const& newdir);
0150
0151 private:
0152
0153
0154 using LSA = LevelStateAccessor;
0155
0156
0157 struct DetailedInitializer
0158 {
0159 TrackSlotId parent;
0160 Real3 const& dir;
0161 };
0162
0163
0164
0165 ParamsRef const& params_;
0166 StateRef const& states_;
0167 TrackSlotId track_slot_;
0168 bool failed_{false};
0169
0170
0171
0172
0173 inline CELER_FUNCTION void level(LevelId);
0174
0175
0176 inline CELER_FUNCTION void boundary(BoundaryResult);
0177
0178
0179 inline CELER_FUNCTION void next_step(real_type dist);
0180
0181
0182 inline CELER_FUNCTION void next_surf(detail::OnLocalSurface const&);
0183
0184
0185 inline CELER_FUNCTION void next_surface_level(LevelId);
0186
0187
0188
0189
0190 inline CELER_FUNCTION LevelId const& surface_level() const;
0191
0192
0193 inline CELER_FUNCTION LocalSurfaceId const& surf() const;
0194
0195
0196 inline CELER_FUNCTION Sense const& sense() const;
0197
0198
0199 inline CELER_FUNCTION BoundaryResult const& boundary() const;
0200
0201
0202 inline CELER_FUNCTION real_type const& next_step() const;
0203
0204
0205 inline CELER_FUNCTION detail::OnLocalSurface next_surf() const;
0206
0207
0208 inline CELER_FUNCTION LevelId const& next_surface_level() const;
0209
0210
0211
0212
0213 inline CELER_FUNCTION OrangeTrackView&
0214 operator=(DetailedInitializer const& init);
0215
0216
0217 inline CELER_FUNCTION Propagation
0218 find_next_step_impl(detail::Intersection isect);
0219
0220
0221 inline CELER_FUNCTION Span<SenseValue> make_temp_sense() const;
0222
0223
0224 inline CELER_FUNCTION detail::TempNextFace make_temp_next() const;
0225
0226 inline CELER_FUNCTION detail::LocalState
0227 make_local_state(LevelId level) const;
0228
0229
0230 inline CELER_FUNCTION bool has_next_step() const;
0231
0232
0233 inline CELER_FUNCTION bool has_next_surface() const;
0234
0235
0236 inline CELER_FUNCTION void clear_next();
0237
0238
0239 inline CELER_FUNCTION void
0240 surface(LevelId level, detail::OnLocalSurface surf);
0241
0242
0243 inline CELER_FUNCTION void clear_surface();
0244
0245
0246 inline CELER_FUNCTION LSA make_lsa() const;
0247
0248
0249 inline CELER_FUNCTION LSA make_lsa(LevelId level) const;
0250
0251
0252 inline CELER_FUNCTION DaughterId get_daughter(LSA const& lsa) const;
0253
0254
0255 inline CELER_FUNCTION TransformId get_transform(DaughterId daughter_id) const;
0256
0257
0258 inline CELER_FUNCTION TransformId get_transform(LevelId lev) const;
0259
0260
0261 inline CELER_FUNCTION Real3 geo_normal() const;
0262 };
0263
0264
0265
0266
0267
0268
0269
0270 CELER_FUNCTION
0271 OrangeTrackView::OrangeTrackView(ParamsRef const& params,
0272 StateRef const& states,
0273 TrackSlotId tid)
0274 : params_(params), states_(states), track_slot_(tid)
0275 {
0276 CELER_EXPECT(params_);
0277 CELER_EXPECT(states_);
0278 CELER_EXPECT(track_slot_ < states.size());
0279 }
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 CELER_FUNCTION OrangeTrackView&
0290 OrangeTrackView::operator=(Initializer_t const& init)
0291 {
0292 CELER_EXPECT(is_soft_unit_vector(init.dir));
0293
0294 if (init.parent)
0295 {
0296
0297 *this = {init.parent, init.dir};
0298 CELER_ENSURE(this->pos() == init.pos);
0299 return *this;
0300 }
0301
0302 failed_ = false;
0303
0304
0305 detail::LocalState local;
0306 local.pos = init.pos;
0307 local.dir = init.dir;
0308 local.volume = {};
0309 local.surface = {};
0310 local.temp_sense = this->make_temp_sense();
0311
0312
0313 TransformVisitor apply_transform{params_};
0314 auto transform_down_local = [&local](auto&& t) {
0315 local.pos = t.transform_down(local.pos);
0316 local.dir = t.rotate_down(local.dir);
0317 };
0318
0319
0320 UniverseId univ_id = top_universe_id();
0321 DaughterId daughter_id;
0322 LevelId level{0};
0323 do
0324 {
0325 TrackerVisitor visit_tracker{params_};
0326 auto tinit = visit_tracker(
0327 [&local](auto&& t) { return t.initialize(local); }, univ_id);
0328
0329 if (!tinit.volume || tinit.surface)
0330 {
0331 #if !CELER_DEVICE_COMPILE
0332 auto msg = CELER_LOG_LOCAL(error);
0333 msg << "Failed to initialize geometry state: ";
0334 if (!tinit.volume)
0335 {
0336 msg << "could not find associated volume";
0337 }
0338 else
0339 {
0340 msg << "started on a surface ("
0341 << tinit.surface.id().unchecked_get() << ")";
0342 }
0343 msg << " in universe " << univ_id.unchecked_get()
0344 << " at local position " << repr(local.pos);
0345 #endif
0346
0347
0348 failed_ = true;
0349 tinit.volume = orange_exterior_volume;
0350 }
0351
0352 auto lsa = this->make_lsa(level);
0353 lsa.vol() = tinit.volume;
0354 lsa.pos() = local.pos;
0355 lsa.dir() = local.dir;
0356 lsa.universe() = univ_id;
0357
0358 daughter_id = visit_tracker(
0359 [&tinit](auto&& t) { return t.daughter(tinit.volume); }, univ_id);
0360
0361 if (daughter_id)
0362 {
0363 auto const& daughter = params_.daughters[daughter_id];
0364
0365 apply_transform(transform_down_local, daughter.trans_id);
0366
0367 univ_id = daughter.universe_id;
0368 ++level;
0369 }
0370
0371 } while (daughter_id);
0372
0373
0374 this->level(level);
0375
0376
0377 this->boundary(BoundaryResult::exiting);
0378 this->clear_surface();
0379 this->clear_next();
0380
0381 CELER_ENSURE(!this->has_next_step());
0382 return *this;
0383 }
0384
0385
0386
0387
0388
0389 CELER_FUNCTION
0390 OrangeTrackView& OrangeTrackView::operator=(DetailedInitializer const& init)
0391 {
0392 CELER_EXPECT(is_soft_unit_vector(init.dir));
0393
0394 failed_ = false;
0395
0396 if (track_slot_ != init.parent)
0397 {
0398
0399 OrangeTrackView other(params_, states_, init.parent);
0400 this->level(states_.level[other.track_slot_]);
0401 this->surface(other.surface_level(), {other.surf(), other.sense()});
0402 this->boundary(other.boundary());
0403
0404 for (auto lev : range(LevelId{this->level() + 1}))
0405 {
0406
0407 auto lsa = this->make_lsa(lev);
0408 lsa = other.make_lsa(lev);
0409 }
0410 }
0411
0412
0413
0414 this->clear_next();
0415
0416
0417 Real3 localdir = init.dir;
0418 auto apply_transform = TransformVisitor{params_};
0419 auto rotate_down
0420 = [&localdir](auto&& t) { localdir = t.rotate_down(localdir); };
0421 for (auto lev : range(LevelId{this->level()}))
0422 {
0423 auto lsa = this->make_lsa(lev);
0424 lsa.dir() = localdir;
0425 apply_transform(rotate_down,
0426 this->get_transform(this->get_daughter(lsa)));
0427 }
0428
0429
0430 this->make_lsa().dir() = localdir;
0431
0432 CELER_ENSURE(!this->has_next_step());
0433 return *this;
0434 }
0435
0436
0437
0438
0439
0440 CELER_FUNCTION Real3 const& OrangeTrackView::pos() const
0441 {
0442 return this->make_lsa(LevelId{0}).pos();
0443 }
0444
0445
0446
0447
0448
0449 CELER_FUNCTION Real3 const& OrangeTrackView::dir() const
0450 {
0451 return this->make_lsa(LevelId{0}).dir();
0452 }
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462 CELER_FUNCTION VolumeId OrangeTrackView::volume_id() const
0463 {
0464 ImplVolumeId impl_id = this->impl_volume_id();
0465 return impl_id;
0466 }
0467
0468
0469
0470
0471
0472
0473
0474
0475 CELER_FUNCTION VolumeInstanceId OrangeTrackView::volume_instance_id() const
0476 {
0477 return {};
0478 }
0479
0480
0481
0482
0483
0484 CELER_FORCEINLINE_FUNCTION LevelId const& OrangeTrackView::level() const
0485 {
0486 return states_.level[track_slot_];
0487 }
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497 CELER_FUNCTION void
0498 OrangeTrackView::volume_instance_id(Span<VolumeInstanceId> levels) const
0499 {
0500 CELER_EXPECT(levels.size() == this->level().get() + 1);
0501 for (auto lev : range(levels.size()))
0502 {
0503 levels[lev] = {};
0504 }
0505 }
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515 CELER_FUNCTION ImplVolumeId OrangeTrackView::impl_volume_id() const
0516 {
0517 auto lsa = this->make_lsa();
0518 detail::UniverseIndexer ui(params_.universe_indexer_data);
0519 return ui.global_volume(lsa.universe(), lsa.vol());
0520 }
0521
0522
0523
0524
0525
0526 CELER_FUNCTION ImplSurfaceId OrangeTrackView::impl_surface_id() const
0527 {
0528 if (this->is_on_boundary())
0529 {
0530 auto lsa = this->make_lsa(this->surface_level());
0531 detail::UniverseIndexer ui{params_.universe_indexer_data};
0532 return ui.global_surface(lsa.universe(), this->surf());
0533 }
0534 else
0535 {
0536 return ImplSurfaceId{};
0537 }
0538 }
0539
0540
0541
0542
0543
0544 CELER_FUNCTION ImplSurfaceId OrangeTrackView::next_impl_surface_id() const
0545 {
0546 CELER_EXPECT(this->has_next_surface());
0547 auto lsa = this->make_lsa(this->next_surface_level());
0548 detail::UniverseIndexer ui{params_.universe_indexer_data};
0549 return ui.global_surface(lsa.universe(), this->next_surf().id());
0550 }
0551
0552
0553
0554
0555
0556 CELER_FUNCTION bool OrangeTrackView::is_outside() const
0557 {
0558
0559
0560 auto lsa = this->make_lsa(LevelId{0});
0561 return lsa.vol() == orange_exterior_volume;
0562 }
0563
0564
0565
0566
0567
0568 CELER_FORCEINLINE_FUNCTION bool OrangeTrackView::is_on_boundary() const
0569 {
0570 return static_cast<bool>(this->surface_level());
0571 }
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581 CELER_FUNCTION Real3 OrangeTrackView::normal() const
0582 {
0583 CELER_EXPECT(this->is_on_boundary());
0584
0585 auto normal = this->geo_normal();
0586
0587 if (this->sense() == Sense::outside)
0588 {
0589 normal = negate(normal);
0590 }
0591
0592 return normal;
0593 }
0594
0595
0596
0597
0598
0599 CELER_FUNCTION Propagation OrangeTrackView::find_next_step()
0600 {
0601 if (CELER_UNLIKELY(this->boundary() == BoundaryResult::reentrant))
0602 {
0603
0604 return {0, true};
0605 }
0606
0607
0608 auto global_isect = [this] {
0609 SimpleUnitTracker t{params_, SimpleUnitId{0}};
0610 return t.intersect(this->make_local_state(LevelId{0}));
0611 }();
0612
0613 return this->find_next_step_impl(global_isect);
0614 }
0615
0616
0617
0618
0619
0620
0621
0622
0623 CELER_FUNCTION Propagation OrangeTrackView::find_next_step(real_type max_step)
0624 {
0625 CELER_EXPECT(max_step > 0);
0626
0627 if (CELER_UNLIKELY(this->boundary() == BoundaryResult::reentrant))
0628 {
0629
0630 return {0, true};
0631 }
0632
0633
0634 auto global_isect = [this, &max_step] {
0635 SimpleUnitTracker t{params_, SimpleUnitId{0}};
0636 return t.intersect(this->make_local_state(LevelId{0}), max_step);
0637 }();
0638
0639 auto result = this->find_next_step_impl(global_isect);
0640 CELER_ENSURE(result.distance <= max_step);
0641 return result;
0642 }
0643
0644
0645
0646
0647
0648 CELER_FUNCTION void OrangeTrackView::move_to_boundary()
0649 {
0650 CELER_EXPECT(this->boundary() != BoundaryResult::reentrant);
0651 CELER_EXPECT(this->has_next_step());
0652 CELER_EXPECT(this->has_next_surface());
0653
0654
0655 real_type const dist = this->next_step();
0656 for (auto i : range(this->level() + 1))
0657 {
0658 auto lsa = this->make_lsa(LevelId{i});
0659 axpy(dist, lsa.dir(), &lsa.pos());
0660 }
0661
0662 this->surface(this->next_surface_level(), this->next_surf());
0663 this->clear_next();
0664 CELER_ENSURE(this->is_on_boundary());
0665 }
0666
0667
0668
0669
0670
0671
0672
0673
0674 CELER_FUNCTION void OrangeTrackView::move_internal(real_type dist)
0675 {
0676 CELER_EXPECT(this->has_next_step());
0677 CELER_EXPECT(dist > 0 && dist <= this->next_step());
0678 CELER_EXPECT(dist != this->next_step() || !this->has_next_surface());
0679
0680
0681 for (auto i : range(this->level() + 1))
0682 {
0683 auto lsa = this->make_lsa(LevelId{i});
0684 axpy(dist, lsa.dir(), &lsa.pos());
0685 }
0686 this->next_step(this->next_step() - dist);
0687 this->clear_surface();
0688 }
0689
0690
0691
0692
0693
0694
0695
0696
0697 CELER_FUNCTION void OrangeTrackView::move_internal(Real3 const& pos)
0698 {
0699
0700 auto local_pos = pos;
0701 auto apply_transform = TransformVisitor{params_};
0702 auto translate_down
0703 = [&local_pos](auto&& t) { local_pos = t.transform_down(local_pos); };
0704 for (auto lev : range(LevelId{this->level()}))
0705 {
0706 auto lsa = this->make_lsa(lev);
0707 lsa.pos() = local_pos;
0708
0709
0710 apply_transform(translate_down,
0711 this->get_transform(this->get_daughter(lsa)));
0712 }
0713
0714
0715 auto lsa = this->make_lsa();
0716 lsa.pos() = local_pos;
0717
0718
0719 this->clear_surface();
0720 this->clear_next();
0721 }
0722
0723
0724
0725
0726
0727
0728
0729
0730 CELER_FUNCTION void OrangeTrackView::cross_boundary()
0731 {
0732 CELER_EXPECT(this->is_on_boundary());
0733 CELER_EXPECT(!this->has_next_step());
0734
0735 if (CELER_UNLIKELY(this->boundary() == BoundaryResult::reentrant))
0736 {
0737
0738
0739 this->boundary(BoundaryResult::exiting);
0740 return;
0741 }
0742
0743
0744 states_.sense[track_slot_] = flip_sense(this->sense());
0745 this->boundary(BoundaryResult::exiting);
0746
0747
0748 LevelId level{this->surface_level()};
0749 UniverseId universe;
0750 LocalVolumeId volume;
0751 detail::LocalState local;
0752 {
0753 auto lsa = this->make_lsa(level);
0754 universe = lsa.universe();
0755 local.pos = lsa.pos();
0756 local.dir = lsa.dir();
0757 local.volume = lsa.vol();
0758 local.surface = {this->surf(), this->sense()};
0759 local.temp_sense = this->make_temp_sense();
0760 }
0761
0762 TrackerVisitor visit_tracker{params_};
0763
0764
0765
0766 volume = visit_tracker(
0767 [&local](auto&& t) { return t.cross_boundary(local).volume; },
0768 universe);
0769 if (CELER_UNLIKELY(!volume))
0770 {
0771
0772 #if !CELER_DEVICE_COMPILE
0773 CELER_LOG_LOCAL(error)
0774 << "track failed to cross local surface "
0775 << this->surf().unchecked_get() << " in universe "
0776 << universe.unchecked_get() << " at local position "
0777 << repr(local.pos) << " along local direction " << repr(local.dir);
0778 #endif
0779
0780
0781 failed_ = true;
0782 volume = orange_exterior_volume;
0783 }
0784 make_lsa(level).vol() = volume;
0785
0786
0787
0788 local.volume = {};
0789 local.surface = {};
0790
0791
0792
0793 auto daughter_id = visit_tracker(
0794 [volume](auto&& t) { return t.daughter(volume); }, universe);
0795 while (daughter_id)
0796 {
0797 ++level;
0798 {
0799
0800 auto const& daughter = params_.daughters[daughter_id];
0801 TransformVisitor apply_transform{params_};
0802 auto transform_down_local = [&local](auto&& t) {
0803 local.pos = t.transform_down(local.pos);
0804 local.dir = t.rotate_down(local.dir);
0805 };
0806 apply_transform(transform_down_local, daughter.trans_id);
0807 universe = daughter.universe_id;
0808 }
0809
0810
0811 volume = visit_tracker(
0812 [&local](auto&& t) { return t.initialize(local).volume; },
0813 universe);
0814
0815 if (!volume)
0816 {
0817 #if !CELER_DEVICE_COMPILE
0818 auto msg = CELER_LOG_LOCAL(error);
0819 msg << "track failed to cross boundary: could not find associated "
0820 "volume in universe "
0821 << universe.unchecked_get() << " at local position "
0822 << repr(local.pos);
0823 #endif
0824
0825
0826 failed_ = true;
0827 volume = orange_exterior_volume;
0828 }
0829 daughter_id = visit_tracker(
0830 [volume](auto&& t) { return t.daughter(volume); }, universe);
0831
0832 auto lsa = make_lsa(level);
0833 lsa.vol() = volume;
0834 lsa.pos() = local.pos;
0835 lsa.dir() = local.dir;
0836 lsa.universe() = universe;
0837 }
0838
0839
0840 this->level(level);
0841
0842 CELER_ENSURE(this->is_on_boundary());
0843 }
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857 CELER_FUNCTION void OrangeTrackView::set_dir(Real3 const& newdir)
0858 {
0859 CELER_EXPECT(is_soft_unit_vector(newdir));
0860
0861 if (this->is_on_boundary())
0862 {
0863
0864
0865 auto normal = this->geo_normal();
0866
0867
0868
0869 if ((dot_product(normal, newdir) >= 0)
0870 != (dot_product(normal, this->dir()) >= 0))
0871 {
0872
0873
0874 this->boundary(flip_boundary(this->boundary()));
0875 }
0876 }
0877
0878
0879 Real3 localdir = newdir;
0880 auto apply_transform = TransformVisitor{params_};
0881 auto rotate_down
0882 = [&localdir](auto&& t) { localdir = t.rotate_down(localdir); };
0883 for (auto lev : range(this->level()))
0884 {
0885 auto lsa = this->make_lsa(lev);
0886 lsa.dir() = localdir;
0887 apply_transform(rotate_down,
0888 this->get_transform(this->get_daughter(lsa)));
0889 }
0890
0891 this->make_lsa().dir() = localdir;
0892
0893 this->clear_next();
0894 }
0895
0896
0897
0898
0899
0900
0901
0902 CELER_FORCEINLINE_FUNCTION void OrangeTrackView::level(LevelId lev)
0903 {
0904 states_.level[track_slot_] = lev;
0905 }
0906
0907
0908
0909
0910 CELER_FORCEINLINE_FUNCTION void OrangeTrackView::boundary(BoundaryResult br)
0911 {
0912 states_.boundary[track_slot_] = br;
0913 }
0914
0915
0916
0917
0918 CELER_FORCEINLINE_FUNCTION void OrangeTrackView::next_step(real_type dist)
0919 {
0920 states_.next_step[track_slot_] = dist;
0921 }
0922
0923
0924
0925
0926 CELER_FORCEINLINE_FUNCTION void
0927 OrangeTrackView::next_surf(detail::OnLocalSurface const& s)
0928 {
0929 states_.next_surf[track_slot_] = s.id();
0930 states_.next_sense[track_slot_] = s.unchecked_sense();
0931 }
0932
0933
0934
0935
0936 CELER_FORCEINLINE_FUNCTION void OrangeTrackView::next_surface_level(LevelId lev)
0937 {
0938 states_.next_level[track_slot_] = lev;
0939 }
0940
0941
0942
0943
0944
0945
0946 CELER_FORCEINLINE_FUNCTION LevelId const& OrangeTrackView::surface_level() const
0947 {
0948 return states_.surface_level[track_slot_];
0949 }
0950
0951
0952
0953
0954 CELER_FORCEINLINE_FUNCTION LocalSurfaceId const& OrangeTrackView::surf() const
0955 {
0956 return states_.surf[track_slot_];
0957 }
0958
0959
0960
0961
0962 CELER_FORCEINLINE_FUNCTION Sense const& OrangeTrackView::sense() const
0963 {
0964 return states_.sense[track_slot_];
0965 }
0966
0967
0968
0969
0970 CELER_FORCEINLINE_FUNCTION BoundaryResult const&
0971 OrangeTrackView::boundary() const
0972 {
0973 return states_.boundary[track_slot_];
0974 }
0975
0976
0977
0978
0979 CELER_FORCEINLINE_FUNCTION real_type const& OrangeTrackView::next_step() const
0980 {
0981 return states_.next_step[track_slot_];
0982 }
0983
0984
0985
0986
0987 CELER_FORCEINLINE_FUNCTION detail::OnLocalSurface
0988 OrangeTrackView::next_surf() const
0989 {
0990 return {states_.next_surf[track_slot_], states_.next_sense[track_slot_]};
0991 }
0992
0993
0994
0995
0996 CELER_FORCEINLINE_FUNCTION LevelId const&
0997 OrangeTrackView::next_surface_level() const
0998 {
0999 return states_.next_level[track_slot_];
1000 }
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011 CELER_FUNCTION Propagation
1012 OrangeTrackView::find_next_step_impl(detail::Intersection isect)
1013 {
1014 TrackerVisitor visit_tracker{params_};
1015
1016
1017 LevelId min_level{0};
1018
1019
1020
1021 for (auto levelid : range(LevelId{1}, this->level() + 1))
1022 {
1023 auto univ_id = this->make_lsa(levelid).universe();
1024 auto local_isect = visit_tracker(
1025 [local_state = this->make_local_state(levelid), &isect](auto&& t) {
1026 return t.intersect(local_state, isect.distance);
1027 },
1028 univ_id);
1029
1030 if (local_isect.distance < isect.distance)
1031 {
1032 isect = local_isect;
1033 min_level = levelid;
1034 }
1035 }
1036
1037 this->next_step(isect.distance);
1038 this->next_surf(isect.surface);
1039 if (isect)
1040 {
1041
1042 this->next_surface_level(min_level);
1043 }
1044
1045 Propagation result;
1046 result.distance = isect.distance;
1047 result.boundary = static_cast<bool>(isect);
1048 return result;
1049 }
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059 CELER_FUNCTION real_type OrangeTrackView::find_safety()
1060 {
1061 CELER_EXPECT(!this->is_on_boundary());
1062
1063 TrackerVisitor visit_tracker{params_};
1064
1065 real_type min_safety_dist = numeric_limits<real_type>::infinity();
1066
1067 for (auto lev : range(LevelId{this->level() + 1}))
1068 {
1069 auto lsa = this->make_lsa(lev);
1070 auto sd = visit_tracker(
1071 [&lsa](auto&& t) { return t.safety(lsa.pos(), lsa.vol()); },
1072 lsa.universe());
1073 min_safety_dist = celeritas::min(min_safety_dist, sd);
1074 }
1075 return min_safety_dist;
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085 CELER_FUNCTION real_type OrangeTrackView::find_safety(real_type)
1086 {
1087 return this->find_safety();
1088 }
1089
1090
1091
1092
1093
1094 CELER_FUNCTION Span<SenseValue> OrangeTrackView::make_temp_sense() const
1095 {
1096 auto const max_faces = params_.scalars.max_faces;
1097 auto offset = track_slot_.get() * max_faces;
1098 return states_.temp_sense[AllItems<SenseValue, MemSpace::native>{}].subspan(
1099 offset, max_faces);
1100 }
1101
1102
1103
1104
1105
1106 CELER_FUNCTION detail::TempNextFace OrangeTrackView::make_temp_next() const
1107 {
1108 auto const max_isect = params_.scalars.max_intersections;
1109 auto offset = track_slot_.get() * max_isect;
1110
1111 detail::TempNextFace result;
1112 result.face = states_.temp_face[AllItems<FaceId>{}].data() + offset;
1113 result.distance = states_.temp_distance[AllItems<real_type>{}].data()
1114 + offset;
1115 result.isect = states_.temp_isect[AllItems<size_type>{}].data() + offset;
1116 result.size = max_isect;
1117
1118 return result;
1119 }
1120
1121
1122
1123
1124
1125 CELER_FUNCTION detail::LocalState
1126 OrangeTrackView::make_local_state(LevelId level) const
1127 {
1128 detail::LocalState local;
1129
1130 auto lsa = this->make_lsa(level);
1131
1132 local.pos = lsa.pos();
1133 local.dir = lsa.dir();
1134 local.volume = lsa.vol();
1135 if (level == this->surface_level())
1136 {
1137 local.surface = {this->surf(), this->sense()};
1138 }
1139 else
1140 {
1141 local.surface = {};
1142 }
1143 local.temp_sense = this->make_temp_sense();
1144 local.temp_next = this->make_temp_next();
1145 return local;
1146 }
1147
1148
1149
1150
1151
1152 CELER_FORCEINLINE_FUNCTION bool OrangeTrackView::has_next_step() const
1153 {
1154 return this->next_step() != 0;
1155 }
1156
1157
1158
1159
1160
1161 CELER_FORCEINLINE_FUNCTION bool OrangeTrackView::has_next_surface() const
1162 {
1163 return static_cast<bool>(states_.next_surf[track_slot_]);
1164 }
1165
1166
1167
1168
1169
1170 CELER_FUNCTION void OrangeTrackView::clear_next()
1171 {
1172 this->next_step(0);
1173 states_.next_surf[track_slot_] = {};
1174 CELER_ENSURE(!this->has_next_step() && !this->has_next_surface());
1175 }
1176
1177
1178
1179
1180
1181 CELER_FUNCTION void
1182 OrangeTrackView::surface(LevelId level, detail::OnLocalSurface surf)
1183 {
1184 states_.surface_level[track_slot_] = level;
1185 states_.surf[track_slot_] = surf.id();
1186 states_.sense[track_slot_] = surf.unchecked_sense();
1187 }
1188
1189
1190
1191
1192
1193 CELER_FUNCTION void OrangeTrackView::clear_surface()
1194 {
1195 states_.surface_level[track_slot_] = {};
1196 CELER_ENSURE(!this->is_on_boundary());
1197 }
1198
1199
1200
1201
1202
1203 CELER_FORCEINLINE_FUNCTION auto OrangeTrackView::make_lsa() const -> LSA
1204 {
1205 return this->make_lsa(this->level());
1206 }
1207
1208
1209
1210
1211
1212 CELER_FORCEINLINE_FUNCTION auto OrangeTrackView::make_lsa(LevelId level) const
1213 -> LSA
1214 {
1215 return LSA(&states_, track_slot_, level);
1216 }
1217
1218
1219
1220
1221
1222
1223
1224 CELER_FUNCTION DaughterId OrangeTrackView::get_daughter(LSA const& lsa) const
1225 {
1226 TrackerVisitor visit_tracker{params_};
1227 return visit_tracker([&lsa](auto&& t) { return t.daughter(lsa.vol()); },
1228 lsa.universe());
1229 }
1230
1231
1232
1233
1234
1235 CELER_FUNCTION TransformId
1236 OrangeTrackView::get_transform(DaughterId daughter_id) const
1237 {
1238 CELER_EXPECT(daughter_id);
1239 return params_.daughters[daughter_id].trans_id;
1240 }
1241
1242
1243
1244
1245
1246 CELER_FUNCTION TransformId OrangeTrackView::get_transform(LevelId lev) const
1247 {
1248 CELER_EXPECT(lev < this->level());
1249 LSA lsa(&states_, track_slot_, lev);
1250 return this->get_transform(this->get_daughter(lsa));
1251 }
1252
1253
1254
1255
1256
1257 CELER_FUNCTION Real3 OrangeTrackView::geo_normal() const
1258 {
1259 CELER_EXPECT(this->is_on_boundary());
1260
1261 auto lsa = this->make_lsa(this->surface_level());
1262 TrackerVisitor visit_tracker{params_};
1263 auto normal = visit_tracker(
1264 [pos = lsa.pos(), local_surface = this->surf()](auto&& t) {
1265 return t.normal(pos, local_surface);
1266 },
1267 lsa.universe());
1268
1269
1270 auto apply_transform = TransformVisitor{params_};
1271 auto rotate_up = [&normal](auto&& t) { normal = t.rotate_up(normal); };
1272 for (auto level : range<int>(this->level().unchecked_get()).step(-1))
1273 {
1274 apply_transform(rotate_up, this->get_transform(LevelId(level)));
1275 }
1276
1277 CELER_ENSURE(is_soft_unit_vector(normal));
1278
1279 return normal;
1280 }
1281
1282
1283 }