File indexing completed on 2025-02-22 10:31:32
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include "corecel/Macros.hh"
0011 #include "corecel/cont/EnumArray.hh"
0012 #include "corecel/cont/Range.hh"
0013 #include "corecel/data/Collection.hh"
0014 #include "corecel/data/CollectionBuilder.hh"
0015 #include "celeritas/Quantities.hh"
0016 #include "celeritas/Types.hh"
0017 #include "celeritas/Units.hh"
0018
0019 namespace celeritas
0020 {
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 struct StepPointSelection
0031 {
0032 bool time{false};
0033 bool pos{false};
0034 bool dir{false};
0035 bool volume_id{false};
0036 bool energy{false};
0037
0038
0039 static constexpr StepPointSelection all()
0040 {
0041 return StepPointSelection{true, true, true, true, true};
0042 }
0043
0044
0045 explicit CELER_FUNCTION operator bool() const
0046 {
0047 return time || pos || dir || volume_id || energy;
0048 }
0049
0050
0051 StepPointSelection& operator|=(StepPointSelection const& other)
0052 {
0053 this->time |= other.time;
0054 this->pos |= other.pos;
0055 this->dir |= other.dir;
0056 this->volume_id |= other.volume_id;
0057 this->energy |= other.energy;
0058 return *this;
0059 }
0060 };
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 struct StepSelection
0071 {
0072 EnumArray<StepPoint, StepPointSelection> points;
0073
0074 bool event_id{false};
0075 bool parent_id{false};
0076 bool track_step_count{false};
0077 bool action_id{false};
0078 bool step_length{false};
0079 bool particle{false};
0080 bool energy_deposition{false};
0081
0082
0083 static constexpr StepSelection all()
0084 {
0085 return StepSelection{
0086 {StepPointSelection::all(), StepPointSelection::all()},
0087 true,
0088 true,
0089 true,
0090 true,
0091 true,
0092 true,
0093 true};
0094 }
0095
0096
0097 explicit CELER_FUNCTION operator bool() const
0098 {
0099 return points[StepPoint::pre] || points[StepPoint::post] || event_id
0100 || parent_id || track_step_count || action_id || step_length
0101 || particle || energy_deposition;
0102 }
0103
0104
0105 StepSelection& operator|=(StepSelection const& other)
0106 {
0107 for (auto sp : range(StepPoint::size_))
0108 {
0109 points[sp] |= other.points[sp];
0110 }
0111
0112 this->event_id |= other.event_id;
0113 this->parent_id |= other.parent_id;
0114 this->track_step_count |= other.track_step_count;
0115 this->action_id |= other.action_id;
0116 this->step_length |= other.step_length;
0117 this->particle |= other.particle;
0118 this->energy_deposition |= other.energy_deposition;
0119 return *this;
0120 }
0121 };
0122
0123
0124
0125
0126
0127
0128
0129 template<Ownership W, MemSpace M>
0130 struct StepParamsData
0131 {
0132
0133
0134
0135 StepSelection selection;
0136
0137
0138 Collection<DetectorId, W, M, VolumeId> detector;
0139
0140
0141 bool nonzero_energy_deposition{false};
0142
0143
0144
0145
0146 explicit CELER_FUNCTION operator bool() const
0147 {
0148 return static_cast<bool>(selection);
0149 }
0150
0151
0152 template<Ownership W2, MemSpace M2>
0153 StepParamsData& operator=(StepParamsData<W2, M2> const& other)
0154 {
0155 CELER_EXPECT(other);
0156 selection = other.selection;
0157 detector = other.detector;
0158 nonzero_energy_deposition = other.nonzero_energy_deposition;
0159 return *this;
0160 }
0161 };
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 template<Ownership W, MemSpace M>
0174 struct StepPointStateData
0175 {
0176
0177
0178 template<class T>
0179 using StateItems = celeritas::StateCollection<T, W, M>;
0180 using Energy = units::MevEnergy;
0181
0182
0183 StateItems<real_type> time;
0184
0185
0186 StateItems<Real3> pos;
0187 StateItems<Real3> dir;
0188 StateItems<VolumeId> volume_id;
0189
0190
0191 StateItems<Energy> energy;
0192
0193
0194
0195
0196 explicit CELER_FUNCTION operator bool() const { return true; }
0197
0198
0199 template<Ownership W2, MemSpace M2>
0200 StepPointStateData& operator=(StepPointStateData<W2, M2>& other)
0201 {
0202 CELER_EXPECT(other);
0203 time = other.time;
0204 pos = other.pos;
0205 dir = other.dir;
0206 volume_id = other.volume_id;
0207 energy = other.energy;
0208 return *this;
0209 }
0210 };
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 template<Ownership W, MemSpace M>
0226 struct StepStateDataImpl
0227 {
0228
0229
0230 using StepPointData = StepPointStateData<W, M>;
0231 template<class T>
0232 using StateItems = celeritas::StateCollection<T, W, M>;
0233 using Energy = units::MevEnergy;
0234
0235
0236
0237
0238 EnumArray<StepPoint, StepPointData> points;
0239
0240
0241 StateItems<TrackId> track_id;
0242
0243
0244 StateItems<DetectorId> detector;
0245
0246
0247 StateItems<EventId> event_id;
0248 StateItems<TrackId> parent_id;
0249 StateItems<ActionId> action_id;
0250 StateItems<size_type> track_step_count;
0251 StateItems<real_type> step_length;
0252
0253
0254 StateItems<ParticleId> particle;
0255 StateItems<Energy> energy_deposition;
0256
0257
0258
0259
0260 explicit CELER_FUNCTION operator bool() const
0261 {
0262 auto right_sized = [this](auto const& t) {
0263 return (t.size() == this->size()) || t.empty();
0264 };
0265
0266 return !track_id.empty() && right_sized(detector)
0267 && right_sized(event_id) && right_sized(parent_id)
0268 && right_sized(track_step_count) && right_sized(action_id)
0269 && right_sized(step_length) && right_sized(particle)
0270 && right_sized(energy_deposition);
0271 }
0272
0273
0274 CELER_FUNCTION TrackSlotId::size_type size() const
0275 {
0276 return track_id.size();
0277 }
0278
0279
0280 template<Ownership W2, MemSpace M2>
0281 StepStateDataImpl& operator=(StepStateDataImpl<W2, M2>& other)
0282 {
0283
0284
0285 CELER_EXPECT(other || (M == MemSpace::host && other.size() == 0));
0286
0287 for (auto sp : range(StepPoint::size_))
0288 {
0289 points[sp] = other.points[sp];
0290 }
0291
0292 track_id = other.track_id;
0293 parent_id = other.parent_id;
0294 detector = other.detector;
0295 event_id = other.event_id;
0296 track_step_count = other.track_step_count;
0297 action_id = other.action_id;
0298 step_length = other.step_length;
0299 particle = other.particle;
0300 energy_deposition = other.energy_deposition;
0301 return *this;
0302 }
0303 };
0304
0305
0306
0307
0308
0309
0310
0311
0312 template<Ownership W, MemSpace M>
0313 struct StepStateData
0314 {
0315
0316
0317 using StepDataImpl = StepStateDataImpl<W, M>;
0318 template<class T>
0319 using StateItems = celeritas::StateCollection<T, W, M>;
0320
0321
0322
0323
0324 StepDataImpl data;
0325
0326
0327 StepDataImpl scratch;
0328
0329
0330 StateItems<size_type> valid_id;
0331
0332
0333 StreamId stream_id;
0334
0335
0336
0337
0338 explicit CELER_FUNCTION operator bool() const
0339 {
0340 auto right_sized = [this](auto const& t) {
0341 return (t.size() == this->size())
0342 || (t.size() == 0 && M == MemSpace::host);
0343 };
0344
0345 return data.size() > 0 && right_sized(scratch) && right_sized(valid_id)
0346 && stream_id;
0347 }
0348
0349
0350 CELER_FUNCTION TrackSlotId::size_type size() const { return data.size(); }
0351
0352
0353 template<Ownership W2, MemSpace M2>
0354 StepStateData& operator=(StepStateData<W2, M2>& other)
0355 {
0356 CELER_EXPECT(other);
0357
0358 data = other.data;
0359 scratch = other.scratch;
0360 valid_id = other.valid_id;
0361 stream_id = other.stream_id;
0362 return *this;
0363 }
0364 };
0365
0366
0367
0368
0369
0370
0371
0372 template<MemSpace M>
0373 inline void resize(StepPointStateData<Ownership::value, M>* state,
0374 StepPointSelection selection,
0375 size_type size)
0376 {
0377 CELER_EXPECT(size > 0);
0378 #define SD_RESIZE_IF_SELECTED(ATTR) \
0379 do \
0380 { \
0381 if (selection.ATTR) \
0382 { \
0383 resize(&state->ATTR, size); \
0384 } \
0385 } while (0)
0386
0387 SD_RESIZE_IF_SELECTED(time);
0388 SD_RESIZE_IF_SELECTED(pos);
0389 SD_RESIZE_IF_SELECTED(dir);
0390 SD_RESIZE_IF_SELECTED(volume_id);
0391 SD_RESIZE_IF_SELECTED(energy);
0392
0393 #undef SD_RESIZE_IF_SELECTED
0394 }
0395
0396
0397
0398
0399
0400 template<MemSpace M>
0401 inline void resize(StepStateDataImpl<Ownership::value, M>* state,
0402 HostCRef<StepParamsData> const& params,
0403 size_type size)
0404 {
0405 CELER_EXPECT(state->size() == 0);
0406 CELER_EXPECT(size > 0);
0407
0408 for (auto sp : range(StepPoint::size_))
0409 {
0410 resize(&state->points[sp], params.selection.points[sp], size);
0411 }
0412
0413 #define SD_RESIZE_IF_SELECTED(ATTR) \
0414 do \
0415 { \
0416 if (params.selection.ATTR) \
0417 { \
0418 resize(&state->ATTR, size); \
0419 } \
0420 } while (0)
0421
0422 resize(&state->track_id, size);
0423 if (!params.detector.empty())
0424 {
0425 resize(&state->detector, size);
0426 }
0427
0428 SD_RESIZE_IF_SELECTED(event_id);
0429 SD_RESIZE_IF_SELECTED(parent_id);
0430 SD_RESIZE_IF_SELECTED(track_step_count);
0431 SD_RESIZE_IF_SELECTED(step_length);
0432 SD_RESIZE_IF_SELECTED(action_id);
0433 SD_RESIZE_IF_SELECTED(particle);
0434 SD_RESIZE_IF_SELECTED(energy_deposition);
0435 }
0436
0437
0438
0439
0440
0441 template<MemSpace M>
0442 inline void resize(StepStateData<Ownership::value, M>* state,
0443 HostCRef<StepParamsData> const& params,
0444 StreamId stream_id,
0445 size_type size)
0446 {
0447 CELER_EXPECT(state->size() == 0);
0448 CELER_EXPECT(size > 0);
0449
0450 state->stream_id = stream_id;
0451
0452 resize(&state->data, params, size);
0453
0454 if constexpr (M == MemSpace::device)
0455 {
0456
0457 resize(&state->scratch, params, size);
0458 resize(&state->valid_id, size);
0459 }
0460 }
0461
0462
0463 }