File indexing completed on 2026-01-01 09:53:32
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Assert.hh"
0010 #include "corecel/OpaqueId.hh"
0011 #include "corecel/Types.hh"
0012 #include "corecel/cont/Range.hh"
0013 #include "corecel/data/Collection.hh"
0014 #include "corecel/data/CollectionBuilder.hh"
0015 #include "corecel/sys/ThreadId.hh"
0016 #include "geocel/BoundingBox.hh"
0017
0018 #include "OrangeTypes.hh"
0019 #include "SenseUtils.hh"
0020
0021 #include "detail/BIHData.hh"
0022
0023 namespace celeritas
0024 {
0025
0026
0027
0028
0029
0030 inline constexpr LocalVolumeId orange_exterior_volume{0};
0031
0032
0033 inline constexpr UniverseId orange_global_universe{0};
0034
0035
0036
0037
0038
0039 struct OrangeParamsScalars
0040 {
0041
0042
0043
0044 size_type max_depth{};
0045 size_type max_faces{};
0046 size_type max_intersections{};
0047 size_type max_logic_depth{};
0048
0049
0050 Tolerance<> tol;
0051
0052
0053 explicit CELER_FUNCTION operator bool() const
0054 {
0055 return max_depth > 0 && max_faces > 0 && max_intersections > 0 && tol;
0056 }
0057 };
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 struct VolumeRecord
0068 {
0069 ItemRange<LocalSurfaceId> faces;
0070 ItemRange<logic_int> logic;
0071
0072 logic_int max_intersections{0};
0073 logic_int flags{0};
0074 DaughterId daughter_id;
0075 OrientedBoundingZoneId obz_id;
0076
0077
0078
0079
0080 enum Flags : logic_int
0081 {
0082 internal_surfaces = 0x1,
0083 implicit_vol = 0x2,
0084 simple_safety = 0x4,
0085 embedded_universe = 0x8
0086 };
0087 };
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108 struct SurfacesRecord
0109 {
0110 using RealId = OpaqueId<real_type>;
0111
0112 ItemRange<SurfaceType> types;
0113 ItemRange<RealId> data_offsets;
0114
0115
0116 CELER_FUNCTION size_type size() const { return types.size(); }
0117
0118
0119 explicit CELER_FUNCTION operator bool() const
0120 {
0121 return data_offsets.size() == types.size();
0122 }
0123 };
0124
0125
0126
0127
0128
0129
0130
0131
0132 struct ConnectivityRecord
0133 {
0134 ItemRange<LocalVolumeId> neighbors;
0135 };
0136
0137
0138
0139
0140
0141 struct OrientedBoundingZoneRecord
0142 {
0143 using Real3 = Array<fast_real_type, 3>;
0144
0145
0146 Array<Real3, 2> half_widths;
0147
0148
0149
0150 Array<TransformId, 2> offset_ids;
0151
0152
0153
0154 TransformId trans_id;
0155
0156
0157 explicit CELER_FUNCTION operator bool() const
0158 {
0159 return offset_ids[0] && offset_ids[1] && trans_id;
0160 }
0161 };
0162
0163
0164
0165
0166
0167 template<size_type N>
0168 struct RaggedRightIndexerData
0169 {
0170 using Sizes = Array<size_type, N>;
0171 using Offsets = Array<size_type, N + 1>;
0172
0173 Offsets offsets;
0174
0175
0176 static RaggedRightIndexerData from_sizes(Sizes sizes)
0177 {
0178 CELER_EXPECT(sizes.size() > 0);
0179
0180 Offsets offs;
0181 offs[0] = 0;
0182 for (auto i : range(N))
0183 {
0184 CELER_EXPECT(sizes[i] > 0);
0185 offs[i + 1] = sizes[i] + offs[i];
0186 }
0187 return RaggedRightIndexerData{offs};
0188 }
0189 };
0190
0191
0192
0193
0194
0195 struct TransformRecord
0196 {
0197 using RealId = OpaqueId<real_type>;
0198 TransformType type{TransformType::size_};
0199 RealId data_offset;
0200
0201
0202 explicit CELER_FUNCTION operator bool() const
0203 {
0204 return type != TransformType::size_ && data_offset;
0205 }
0206 };
0207
0208
0209
0210
0211
0212 struct SimpleUnitRecord
0213 {
0214 using VolumeRecordId = OpaqueId<VolumeRecord>;
0215
0216
0217 SurfacesRecord surfaces;
0218 ItemRange<ConnectivityRecord> connectivity;
0219
0220
0221 ItemMap<LocalVolumeId, VolumeRecordId> volumes;
0222
0223
0224 detail::BIHTree bih_tree;
0225
0226 LocalVolumeId background{};
0227 bool simple_safety{};
0228
0229
0230 explicit CELER_FUNCTION operator bool() const
0231 {
0232 return surfaces && connectivity.size() == surfaces.types.size()
0233 && !volumes.empty();
0234 }
0235 };
0236
0237
0238
0239
0240
0241 struct RectArrayRecord
0242 {
0243 using Dims = Array<size_type, 3>;
0244 using Grid = Array<ItemRange<real_type>, 3>;
0245 using SurfaceIndexerData = RaggedRightIndexerData<3>;
0246
0247
0248 ItemMap<LocalVolumeId, DaughterId> daughters;
0249
0250
0251 Dims dims;
0252 Grid grid;
0253 SurfaceIndexerData surface_indexer_data;
0254
0255
0256 explicit CELER_FUNCTION operator bool() const
0257 {
0258 return !daughters.empty() && !grid[to_int(Axis::x)].empty()
0259 && !grid[to_int(Axis::y)].empty()
0260 && !grid[to_int(Axis::z)].empty();
0261 }
0262 };
0263
0264
0265
0266
0267
0268
0269
0270
0271 template<Ownership W, MemSpace M>
0272 struct UniverseIndexerData
0273 {
0274 Collection<size_type, W, M> surfaces;
0275 Collection<size_type, W, M> volumes;
0276
0277 template<Ownership W2, MemSpace M2>
0278 UniverseIndexerData& operator=(UniverseIndexerData<W2, M2> const& other)
0279 {
0280 CELER_EXPECT(other);
0281
0282 surfaces = other.surfaces;
0283 volumes = other.volumes;
0284
0285 CELER_ENSURE(*this);
0286 return *this;
0287 }
0288
0289 explicit CELER_FUNCTION operator bool() const
0290 {
0291 return !surfaces.empty() && !volumes.empty();
0292 }
0293 };
0294
0295
0296
0297
0298
0299
0300
0301 template<Ownership W, MemSpace M>
0302 struct BIHTreeData
0303 {
0304 template<class T>
0305 using Items = Collection<T, W, M>;
0306
0307
0308 Items<FastBBox> bboxes;
0309 Items<LocalVolumeId> local_volume_ids;
0310 Items<detail::BIHInnerNode> inner_nodes;
0311 Items<detail::BIHLeafNode> leaf_nodes;
0312
0313
0314 explicit CELER_FUNCTION operator bool() const
0315 {
0316
0317 return !bboxes.empty() && !local_volume_ids.empty()
0318 && !leaf_nodes.empty();
0319 }
0320
0321
0322 template<Ownership W2, MemSpace M2>
0323 BIHTreeData& operator=(BIHTreeData<W2, M2> const& other)
0324 {
0325 bboxes = other.bboxes;
0326 local_volume_ids = other.local_volume_ids;
0327 inner_nodes = other.inner_nodes;
0328 leaf_nodes = other.leaf_nodes;
0329
0330 CELER_ENSURE(static_cast<bool>(*this) == static_cast<bool>(other));
0331 return *this;
0332 }
0333 };
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347 template<Ownership W, MemSpace M>
0348 struct OrangeParamsData
0349 {
0350 template<class T>
0351 using Items = Collection<T, W, M>;
0352 template<class T>
0353 using ImplVolumeItems = Collection<T, W, M, ImplVolumeId>;
0354 template<class T>
0355 using UnivItems = Collection<T, W, M, UniverseId>;
0356
0357 using RealId = SurfacesRecord::RealId;
0358
0359
0360
0361
0362 OrangeParamsScalars scalars;
0363
0364
0365 UnivItems<UniverseType> universe_types;
0366 UnivItems<size_type> universe_indices;
0367 Items<SimpleUnitRecord> simple_units;
0368 Items<RectArrayRecord> rect_arrays;
0369 Items<TransformRecord> transforms;
0370
0371
0372 BIHTreeData<W, M> bih_tree_data;
0373
0374
0375 Items<LocalSurfaceId> local_surface_ids;
0376 Items<LocalVolumeId> local_volume_ids;
0377 Items<RealId> real_ids;
0378 Items<logic_int> logic_ints;
0379 Items<real_type> reals;
0380 Items<FastReal3> fast_real3s;
0381 Items<SurfaceType> surface_types;
0382 Items<ConnectivityRecord> connectivity_records;
0383 Items<VolumeRecord> volume_records;
0384 Items<Daughter> daughters;
0385 Items<OrientedBoundingZoneRecord> obz_records;
0386
0387 UniverseIndexerData<W, M> universe_indexer_data;
0388
0389
0390
0391
0392 explicit CELER_FUNCTION operator bool() const
0393 {
0394 return scalars && !universe_types.empty()
0395 && universe_indices.size() == universe_types.size()
0396 && (bih_tree_data || !simple_units.empty())
0397 && ((!local_volume_ids.empty() && !logic_ints.empty()
0398 && !reals.empty())
0399 || surface_types.empty())
0400 && !volume_records.empty() && universe_indexer_data;
0401 }
0402
0403
0404 template<Ownership W2, MemSpace M2>
0405 OrangeParamsData& operator=(OrangeParamsData<W2, M2> const& other)
0406 {
0407 scalars = other.scalars;
0408
0409 universe_types = other.universe_types;
0410 universe_indices = other.universe_indices;
0411 simple_units = other.simple_units;
0412 rect_arrays = other.rect_arrays;
0413 transforms = other.transforms;
0414
0415 bih_tree_data = other.bih_tree_data;
0416
0417 local_surface_ids = other.local_surface_ids;
0418 local_volume_ids = other.local_volume_ids;
0419 real_ids = other.real_ids;
0420 logic_ints = other.logic_ints;
0421 reals = other.reals;
0422 surface_types = other.surface_types;
0423 connectivity_records = other.connectivity_records;
0424 volume_records = other.volume_records;
0425 obz_records = other.obz_records;
0426 daughters = other.daughters;
0427 universe_indexer_data = other.universe_indexer_data;
0428
0429 CELER_ENSURE(static_cast<bool>(*this) == static_cast<bool>(other));
0430 return *this;
0431 }
0432 };
0433
0434
0435
0436
0437
0438
0439
0440 template<Ownership W, MemSpace M>
0441 struct OrangeStateData
0442 {
0443
0444
0445 template<class T>
0446 using StateItems = celeritas::StateCollection<T, W, M>;
0447 template<class T>
0448 using Items = celeritas::Collection<T, W, M>;
0449
0450
0451
0452
0453
0454
0455 size_type max_depth{0};
0456
0457
0458 StateItems<LevelId> level;
0459 StateItems<LevelId> surface_level;
0460 StateItems<LocalSurfaceId> surf;
0461 StateItems<Sense> sense;
0462 StateItems<BoundaryResult> boundary;
0463
0464
0465 StateItems<LevelId> next_level;
0466 StateItems<real_type> next_step;
0467 StateItems<LocalSurfaceId> next_surf;
0468 StateItems<Sense> next_sense;
0469
0470
0471 Items<Real3> pos;
0472 Items<Real3> dir;
0473 Items<LocalVolumeId> vol;
0474 Items<UniverseId> universe;
0475
0476
0477 Items<SenseValue> temp_sense;
0478
0479
0480 Items<FaceId> temp_face;
0481 Items<real_type> temp_distance;
0482 Items<size_type> temp_isect;
0483
0484
0485
0486
0487 explicit CELER_FUNCTION operator bool() const
0488 {
0489
0490 return max_depth > 0
0491 && !level.empty()
0492 && surface_level.size() == this->size()
0493 && surf.size() == this->size()
0494 && sense.size() == this->size()
0495 && boundary.size() == this->size()
0496 && next_level.size() == this->size()
0497 && next_step.size() == this->size()
0498 && next_surf.size() == this->size()
0499 && next_sense.size() == this->size()
0500 && pos.size() == max_depth * this->size()
0501 && dir.size() == max_depth * this->size()
0502 && vol.size() == max_depth * this->size()
0503 && universe.size() == max_depth * this->size()
0504 && !temp_sense.empty()
0505 && !temp_face.empty()
0506 && temp_distance.size() == temp_face.size()
0507 && temp_isect.size() == temp_face.size();
0508
0509 }
0510
0511
0512 CELER_FUNCTION TrackSlotId::size_type size() const { return level.size(); }
0513
0514
0515 template<Ownership W2, MemSpace M2>
0516 OrangeStateData& operator=(OrangeStateData<W2, M2>& other)
0517 {
0518 CELER_EXPECT(other);
0519 max_depth = other.max_depth;
0520
0521 level = other.level;
0522 surface_level = other.surface_level;
0523 surf = other.surf;
0524 sense = other.sense;
0525 boundary = other.boundary;
0526
0527 next_level = other.next_level;
0528 next_step = other.next_step;
0529 next_surf = other.next_surf;
0530 next_sense = other.next_sense;
0531
0532 pos = other.pos;
0533 dir = other.dir;
0534 vol = other.vol;
0535 universe = other.universe;
0536
0537 temp_sense = other.temp_sense;
0538
0539 temp_face = other.temp_face;
0540 temp_distance = other.temp_distance;
0541 temp_isect = other.temp_isect;
0542
0543 CELER_ENSURE(*this);
0544 return *this;
0545 }
0546 };
0547
0548
0549
0550
0551
0552 template<MemSpace M>
0553 inline void resize(OrangeStateData<Ownership::value, M>* data,
0554 HostCRef<OrangeParamsData> const& params,
0555 size_type num_tracks)
0556 {
0557 CELER_EXPECT(data);
0558 CELER_EXPECT(num_tracks > 0);
0559
0560 data->max_depth = params.scalars.max_depth;
0561
0562 resize(&data->level, num_tracks);
0563 resize(&data->surface_level, num_tracks);
0564 resize(&data->surf, num_tracks);
0565 resize(&data->sense, num_tracks);
0566 resize(&data->boundary, num_tracks);
0567
0568 resize(&data->next_level, num_tracks);
0569 resize(&data->next_step, num_tracks);
0570 resize(&data->next_surf, num_tracks);
0571 resize(&data->next_sense, num_tracks);
0572
0573 size_type level_states = params.scalars.max_depth * num_tracks;
0574 resize(&data->pos, level_states);
0575 resize(&data->dir, level_states);
0576 resize(&data->vol, level_states);
0577 resize(&data->universe, level_states);
0578
0579 size_type face_states = params.scalars.max_faces * num_tracks;
0580 resize(&data->temp_sense, face_states);
0581
0582 size_type isect_states = params.scalars.max_intersections * num_tracks;
0583 resize(&data->temp_face, isect_states);
0584 resize(&data->temp_distance, isect_states);
0585 resize(&data->temp_isect, isect_states);
0586
0587 CELER_ENSURE(*data);
0588 }
0589
0590
0591 }