File indexing completed on 2025-09-16 08:52:26
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/cont/Array.hh"
0010 #include "corecel/data/Collection.hh"
0011 #include "corecel/data/CollectionBuilder.hh"
0012 #include "corecel/data/StackAllocatorData.hh"
0013 #include "celeritas/Quantities.hh"
0014 #include "celeritas/Types.hh"
0015 #include "celeritas/em/data/AtomicRelaxationData.hh"
0016 #include "celeritas/em/data/EPlusGGData.hh"
0017 #include "celeritas/em/data/LivermorePEData.hh"
0018 #include "celeritas/grid/XsGridData.hh"
0019 #include "celeritas/neutron/data/NeutronElasticData.hh"
0020
0021 #include "Interaction.hh"
0022 #include "Secondary.hh"
0023
0024 namespace celeritas
0025 {
0026
0027
0028
0029
0030 using ValueGrid = XsGridRecord;
0031 using ValueGridId = OpaqueId<XsGridRecord>;
0032 using ValueTableId = OpaqueId<struct ValueTable>;
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 struct ValueTable
0046 {
0047 ItemRange<ValueGridId> grids;
0048
0049
0050 explicit CELER_FUNCTION operator bool() const { return !grids.empty(); }
0051 };
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 struct ModelXsTable
0064 {
0065 ItemRange<ValueTableId> material;
0066
0067
0068 explicit CELER_FUNCTION operator bool() const { return !material.empty(); }
0069 };
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 struct ModelGroup
0081 {
0082 using Energy = units::MevEnergy;
0083
0084 ItemRange<real_type> energy;
0085 ItemRange<ParticleModelId> model;
0086
0087
0088 explicit CELER_FUNCTION operator bool() const
0089 {
0090 return (energy.size() >= 2) && (model.size() + 1 == energy.size());
0091 }
0092 };
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 struct IntegralXsProcess
0105 {
0106 ItemRange<real_type> energy_max_xs;
0107
0108
0109 explicit CELER_FUNCTION operator bool() const
0110 {
0111 return !energy_max_xs.empty();
0112 }
0113 };
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 struct ProcessGroup
0132 {
0133 ItemRange<ProcessId> processes;
0134 ItemRange<ModelGroup> models;
0135 ItemRange<IntegralXsProcess> integral_xs;
0136 ItemRange<ValueTable> macro_xs;
0137 ValueTableId energy_loss;
0138 ValueTableId range;
0139 ValueTableId inverse_range;
0140 ParticleProcessId at_rest;
0141
0142
0143 explicit CELER_FUNCTION operator bool() const
0144 {
0145 return !processes.empty() && models.size() == processes.size();
0146 }
0147
0148
0149 CELER_FUNCTION ParticleProcessId::size_type size() const
0150 {
0151 return processes.size();
0152 }
0153 };
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 template<Ownership W, MemSpace M>
0164 struct HardwiredModels
0165 {
0166
0167
0168
0169 ProcessId photoelectric;
0170 units::MevEnergy photoelectric_table_thresh;
0171 ModelId livermore_pe;
0172 LivermorePEData<W, M> livermore_pe_data;
0173 AtomicRelaxParamsData<W, M> relaxation_data;
0174
0175
0176 ProcessId positron_annihilation;
0177 ModelId eplusgg;
0178 EPlusGGData eplusgg_data;
0179
0180
0181 ProcessId neutron_elastic;
0182 ModelId chips;
0183 NeutronElasticData<W, M> chips_data;
0184
0185
0186
0187
0188 template<Ownership W2, MemSpace M2>
0189 HardwiredModels& operator=(HardwiredModels<W2, M2> const& other)
0190 {
0191
0192 photoelectric = other.photoelectric;
0193 if (photoelectric)
0194 {
0195
0196 photoelectric_table_thresh = other.photoelectric_table_thresh;
0197 livermore_pe = other.livermore_pe;
0198 livermore_pe_data = other.livermore_pe_data;
0199 }
0200 relaxation_data = other.relaxation_data;
0201 positron_annihilation = other.positron_annihilation;
0202 eplusgg = other.eplusgg;
0203 eplusgg_data = other.eplusgg_data;
0204
0205 neutron_elastic = other.neutron_elastic;
0206 if (neutron_elastic)
0207 {
0208
0209 chips = other.chips;
0210 chips_data = other.chips_data;
0211 }
0212
0213 return *this;
0214 }
0215 };
0216
0217
0218
0219
0220
0221
0222
0223
0224 struct ParticleScalars
0225 {
0226 using Energy = units::MevEnergy;
0227
0228
0229 real_type min_range{};
0230 real_type max_step_over_range{};
0231 Energy lowest_energy{};
0232
0233
0234 bool displaced{};
0235 real_type range_factor{};
0236 MscStepLimitAlgorithm step_limit_algorithm{MscStepLimitAlgorithm::size_};
0237
0238
0239 explicit CELER_FUNCTION operator bool() const
0240 {
0241 return min_range > 0 && max_step_over_range > 0
0242 && lowest_energy > zero_quantity() && range_factor > 0
0243 && range_factor < 1
0244 && step_limit_algorithm != MscStepLimitAlgorithm::size_;
0245 }
0246 };
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 struct PhysicsParamsScalars
0260 {
0261 using Energy = units::MevEnergy;
0262
0263
0264 ProcessId::size_type max_particle_processes{};
0265
0266 ActionId::size_type model_to_action{};
0267
0268 ModelId::size_type num_models{};
0269
0270
0271 real_type min_eprime_over_e{};
0272 real_type linear_loss_limit{};
0273 real_type fixed_step_limiter{};
0274
0275
0276 real_type lambda_limit{};
0277 real_type safety_factor{};
0278
0279
0280 ParticleScalars light;
0281 ParticleScalars heavy;
0282
0283 real_type secondary_stack_factor = 3;
0284
0285
0286 ActionId fixed_step_action{};
0287
0288
0289 explicit CELER_FUNCTION operator bool() const
0290 {
0291 return max_particle_processes > 0 && model_to_action >= 4
0292 && num_models > 0 && min_eprime_over_e > 0
0293 && linear_loss_limit > 0 && secondary_stack_factor > 0
0294 && ((fixed_step_limiter > 0)
0295 == static_cast<bool>(fixed_step_action))
0296 && lambda_limit > 0 && safety_factor >= 0.1 && light && heavy;
0297 }
0298
0299
0300 CELER_FORCEINLINE_FUNCTION ActionId msc_action() const
0301 {
0302 return ActionId{model_to_action - 4};
0303 }
0304
0305
0306 CELER_FORCEINLINE_FUNCTION ActionId range_action() const
0307 {
0308 return ActionId{model_to_action - 3};
0309 }
0310
0311
0312 CELER_FORCEINLINE_FUNCTION ActionId discrete_action() const
0313 {
0314 return ActionId{model_to_action - 2};
0315 }
0316
0317
0318 CELER_FORCEINLINE_FUNCTION ActionId integral_rejection_action() const
0319 {
0320 return ActionId{model_to_action - 1};
0321 }
0322
0323
0324 CELER_FORCEINLINE_FUNCTION ActionId failure_action() const
0325 {
0326 return ActionId{model_to_action + num_models};
0327 }
0328 };
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349 template<Ownership W, MemSpace M>
0350 struct PhysicsParamsData
0351 {
0352
0353
0354 template<class T>
0355 using Items = Collection<T, W, M>;
0356 template<class T>
0357 using ParticleItems = Collection<T, W, M, ParticleId>;
0358 template<class T>
0359 using ParticleModelItems = Collection<T, W, M, ParticleModelId>;
0360
0361
0362
0363
0364 Items<real_type> reals;
0365 Items<ParticleModelId> pmodel_ids;
0366 Items<ValueGrid> value_grids;
0367 Items<ValueGridId> value_grid_ids;
0368 Items<ProcessId> process_ids;
0369 Items<ValueTable> value_tables;
0370 Items<ValueTableId> value_table_ids;
0371 Items<IntegralXsProcess> integral_xs;
0372 Items<ModelGroup> model_groups;
0373 ParticleItems<ProcessGroup> process_groups;
0374 ParticleModelItems<ModelId> model_ids;
0375 ParticleModelItems<ModelXsTable> model_xs;
0376
0377
0378 HardwiredModels<W, M> hardwired;
0379
0380
0381 PhysicsParamsScalars scalars;
0382
0383
0384
0385
0386 explicit CELER_FUNCTION operator bool() const
0387 {
0388 return !process_groups.empty() && !model_ids.empty() && scalars;
0389 }
0390
0391
0392 template<Ownership W2, MemSpace M2>
0393 PhysicsParamsData& operator=(PhysicsParamsData<W2, M2> const& other)
0394 {
0395 CELER_EXPECT(other);
0396
0397 reals = other.reals;
0398 pmodel_ids = other.pmodel_ids;
0399 value_grids = other.value_grids;
0400 value_grid_ids = other.value_grid_ids;
0401 process_ids = other.process_ids;
0402 value_tables = other.value_tables;
0403 value_table_ids = other.value_table_ids;
0404 integral_xs = other.integral_xs;
0405 model_groups = other.model_groups;
0406 process_groups = other.process_groups;
0407 model_ids = other.model_ids;
0408 model_xs = other.model_xs;
0409
0410 hardwired = other.hardwired;
0411
0412 scalars = other.scalars;
0413
0414 return *this;
0415 }
0416 };
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434 struct PhysicsTrackState
0435 {
0436 real_type interaction_mfp;
0437
0438
0439 real_type macro_xs;
0440 real_type energy_deposition;
0441 real_type dedx_range;
0442 MscRange msc_range;
0443 Span<Secondary> secondaries;
0444 ElementComponentId element;
0445 };
0446
0447
0448
0449
0450
0451
0452
0453
0454 struct PhysicsTrackInitializer
0455 {
0456 };
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467 template<Ownership W, MemSpace M>
0468 struct PhysicsStateData
0469 {
0470
0471
0472 template<class T>
0473 using StateItems = celeritas::StateCollection<T, W, M>;
0474 template<class T>
0475 using Items = celeritas::Collection<T, W, M>;
0476
0477
0478
0479 StateItems<PhysicsTrackState> state;
0480 StateItems<MscStep> msc_step;
0481
0482 Items<real_type> per_process_xs;
0483
0484 AtomicRelaxStateData<W, M> relaxation;
0485 StackAllocatorData<Secondary, W, M> secondaries;
0486
0487
0488
0489
0490 explicit CELER_FUNCTION operator bool() const
0491 {
0492 return !state.empty() && secondaries;
0493 }
0494
0495
0496 CELER_FUNCTION size_type size() const { return state.size(); }
0497
0498
0499 template<Ownership W2, MemSpace M2>
0500 PhysicsStateData& operator=(PhysicsStateData<W2, M2>& other)
0501 {
0502 CELER_EXPECT(other);
0503 state = other.state;
0504 msc_step = other.msc_step;
0505
0506 per_process_xs = other.per_process_xs;
0507
0508 relaxation = other.relaxation;
0509 secondaries = other.secondaries;
0510
0511 return *this;
0512 }
0513 };
0514
0515
0516
0517
0518
0519 template<MemSpace M>
0520 inline void resize(PhysicsStateData<Ownership::value, M>* state,
0521 HostCRef<PhysicsParamsData> const& params,
0522 size_type size)
0523 {
0524 CELER_EXPECT(size > 0);
0525 CELER_EXPECT(params.scalars.max_particle_processes > 0);
0526 resize(&state->state, size);
0527 resize(&state->msc_step, size);
0528 resize(&state->per_process_xs,
0529 size * params.scalars.max_particle_processes);
0530 resize(&state->relaxation, params.hardwired.relaxation_data, size);
0531 resize(
0532 &state->secondaries,
0533 static_cast<size_type>(size * params.scalars.secondary_stack_factor));
0534 }
0535
0536
0537 }