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