File indexing completed on 2025-02-22 10:31:30
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include "corecel/Config.hh"
0011
0012 #include "corecel/Assert.hh"
0013 #include "corecel/Macros.hh"
0014 #include "corecel/Types.hh"
0015 #include "celeritas/Quantities.hh"
0016 #include "celeritas/Types.hh"
0017 #include "celeritas/em/xs/EPlusGGMacroXsCalculator.hh"
0018 #include "celeritas/em/xs/LivermorePEMicroXsCalculator.hh"
0019 #include "celeritas/grid/GridIdFinder.hh"
0020 #include "celeritas/grid/XsCalculator.hh"
0021 #include "celeritas/mat/MaterialView.hh"
0022 #include "celeritas/mat/TabulatedElementSelector.hh"
0023 #include "celeritas/neutron/xs/NeutronElasticMicroXsCalculator.hh"
0024 #include "celeritas/phys/MacroXsCalculator.hh"
0025
0026 #include "PhysicsData.hh"
0027
0028 namespace celeritas
0029 {
0030
0031
0032
0033
0034
0035
0036
0037 class PhysicsTrackView
0038 {
0039 public:
0040
0041
0042 using Initializer_t = PhysicsTrackInitializer;
0043 using PhysicsParamsRef = NativeCRef<PhysicsParamsData>;
0044 using PhysicsStateRef = NativeRef<PhysicsStateData>;
0045 using Energy = units::MevEnergy;
0046 using ModelFinder = GridIdFinder<Energy, ParticleModelId>;
0047
0048
0049 public:
0050
0051 inline CELER_FUNCTION PhysicsTrackView(PhysicsParamsRef const& params,
0052 PhysicsStateRef const& states,
0053 ParticleId particle,
0054 MaterialId material,
0055 TrackSlotId tid);
0056
0057
0058 inline CELER_FUNCTION PhysicsTrackView& operator=(Initializer_t const&);
0059
0060
0061 inline CELER_FUNCTION void interaction_mfp(real_type);
0062
0063
0064 inline CELER_FUNCTION void reset_interaction_mfp();
0065
0066
0067 inline CELER_FUNCTION void dedx_range(real_type);
0068
0069
0070 inline CELER_FUNCTION void msc_range(MscRange const&);
0071
0072
0073
0074
0075 CELER_FORCEINLINE_FUNCTION bool has_interaction_mfp() const;
0076
0077
0078 CELER_FORCEINLINE_FUNCTION real_type interaction_mfp() const;
0079
0080
0081 CELER_FORCEINLINE_FUNCTION real_type dedx_range() const;
0082
0083
0084 CELER_FORCEINLINE_FUNCTION MscRange const& msc_range() const;
0085
0086
0087 CELER_FORCEINLINE_FUNCTION MaterialId material_id() const;
0088
0089
0090
0091
0092 inline CELER_FUNCTION ParticleProcessId::size_type
0093 num_particle_processes() const;
0094
0095
0096 inline CELER_FUNCTION ProcessId process(ParticleProcessId) const;
0097
0098
0099 inline CELER_FUNCTION ValueGridId value_grid(ValueGridType table,
0100 ParticleProcessId) const;
0101
0102
0103 inline CELER_FUNCTION IntegralXsProcess const&
0104 integral_xs_process(ParticleProcessId ppid) const;
0105
0106
0107 inline CELER_FUNCTION real_type calc_xs(ParticleProcessId ppid,
0108 MaterialView const& material,
0109 Energy energy) const;
0110
0111
0112 inline CELER_FUNCTION real_type calc_max_xs(IntegralXsProcess const& process,
0113 ParticleProcessId ppid,
0114 MaterialView const& material,
0115 Energy energy) const;
0116
0117
0118 inline CELER_FUNCTION
0119 ModelFinder make_model_finder(ParticleProcessId) const;
0120
0121
0122 inline CELER_FUNCTION ValueTableId value_table(ParticleModelId) const;
0123
0124
0125 inline CELER_FUNCTION
0126 TabulatedElementSelector make_element_selector(ValueTableId,
0127 Energy) const;
0128
0129
0130 inline CELER_FUNCTION bool has_at_rest() const;
0131
0132
0133
0134
0135 inline CELER_FUNCTION ModelId action_to_model(ActionId) const;
0136
0137
0138 inline CELER_FUNCTION ActionId model_to_action(ModelId) const;
0139
0140
0141 inline CELER_FUNCTION ModelId model_id(ParticleModelId) const;
0142
0143
0144 inline CELER_FUNCTION real_type range_to_step(real_type range) const;
0145
0146
0147 CELER_FORCEINLINE_FUNCTION PhysicsParamsScalars const& scalars() const;
0148
0149
0150 inline CELER_FUNCTION size_type num_particles() const;
0151
0152
0153 template<class T>
0154 inline CELER_FUNCTION T make_calculator(ValueGridId) const;
0155
0156
0157
0158
0159 inline CELER_FUNCTION ModelId hardwired_model(ParticleProcessId ppid,
0160 Energy energy) const;
0161
0162
0163 inline CELER_FUNCTION ParticleProcessId eloss_ppid() const;
0164
0165 private:
0166 PhysicsParamsRef const& params_;
0167 PhysicsStateRef const& states_;
0168 ParticleId const particle_;
0169 MaterialId const material_;
0170 TrackSlotId const track_slot_;
0171
0172
0173
0174 CELER_FORCEINLINE_FUNCTION PhysicsTrackState& state();
0175 CELER_FORCEINLINE_FUNCTION PhysicsTrackState const& state() const;
0176 CELER_FORCEINLINE_FUNCTION ProcessGroup const& process_group() const;
0177 };
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 CELER_FUNCTION
0188 PhysicsTrackView::PhysicsTrackView(PhysicsParamsRef const& params,
0189 PhysicsStateRef const& states,
0190 ParticleId pid,
0191 MaterialId mid,
0192 TrackSlotId tid)
0193 : params_(params)
0194 , states_(states)
0195 , particle_(pid)
0196 , material_(mid)
0197 , track_slot_(tid)
0198 {
0199 CELER_EXPECT(track_slot_);
0200 }
0201
0202
0203
0204
0205
0206 CELER_FUNCTION PhysicsTrackView&
0207 PhysicsTrackView::operator=(Initializer_t const&)
0208 {
0209 this->state().interaction_mfp = 0;
0210 this->state().msc_range = {};
0211 return *this;
0212 }
0213
0214
0215
0216
0217
0218
0219
0220 CELER_FUNCTION void PhysicsTrackView::interaction_mfp(real_type mfp)
0221 {
0222 CELER_EXPECT(mfp > 0);
0223 this->state().interaction_mfp = mfp;
0224 }
0225
0226
0227
0228
0229
0230
0231
0232 CELER_FUNCTION void PhysicsTrackView::reset_interaction_mfp()
0233 {
0234 this->state().interaction_mfp = 0;
0235 }
0236
0237
0238
0239
0240
0241
0242
0243 CELER_FUNCTION void PhysicsTrackView::dedx_range(real_type range)
0244 {
0245 CELER_EXPECT(range > 0);
0246 this->state().dedx_range = range;
0247 }
0248
0249
0250
0251
0252
0253
0254
0255 CELER_FUNCTION void PhysicsTrackView::msc_range(MscRange const& msc_range)
0256 {
0257 this->state().msc_range = msc_range;
0258 }
0259
0260
0261
0262
0263
0264 CELER_FUNCTION MaterialId PhysicsTrackView::material_id() const
0265 {
0266 return material_;
0267 }
0268
0269
0270
0271
0272
0273 CELER_FUNCTION bool PhysicsTrackView::has_interaction_mfp() const
0274 {
0275 return this->state().interaction_mfp > 0;
0276 }
0277
0278
0279
0280
0281
0282 CELER_FUNCTION real_type PhysicsTrackView::interaction_mfp() const
0283 {
0284 real_type mfp = this->state().interaction_mfp;
0285 CELER_ENSURE(mfp >= 0);
0286 return mfp;
0287 }
0288
0289
0290
0291
0292
0293 CELER_FUNCTION real_type PhysicsTrackView::dedx_range() const
0294 {
0295 real_type range = this->state().dedx_range;
0296 CELER_ENSURE(range > 0);
0297 return range;
0298 }
0299
0300
0301
0302
0303
0304 CELER_FUNCTION MscRange const& PhysicsTrackView::msc_range() const
0305 {
0306 return this->state().msc_range;
0307 }
0308
0309
0310
0311
0312
0313 CELER_FUNCTION ParticleProcessId::size_type
0314 PhysicsTrackView::num_particle_processes() const
0315 {
0316 return this->process_group().size();
0317 }
0318
0319
0320
0321
0322
0323 CELER_FUNCTION ProcessId PhysicsTrackView::process(ParticleProcessId ppid) const
0324 {
0325 CELER_EXPECT(ppid < this->num_particle_processes());
0326 return params_.process_ids[this->process_group().processes[ppid.get()]];
0327 }
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340 CELER_FUNCTION auto
0341 PhysicsTrackView::value_grid(ValueGridType table_type,
0342 ParticleProcessId ppid) const -> ValueGridId
0343 {
0344 CELER_EXPECT(int(table_type) < int(ValueGridType::size_));
0345 CELER_EXPECT(ppid < this->num_particle_processes());
0346 ValueTableId table_id
0347 = this->process_group().tables[table_type][ppid.get()];
0348
0349 CELER_ASSERT(table_id);
0350 ValueTable const& table = params_.value_tables[table_id];
0351 if (!table)
0352 return {};
0353
0354 CELER_EXPECT(material_ < table.grids.size());
0355 auto grid_id_ref = table.grids[material_.get()];
0356 if (!grid_id_ref)
0357 return {};
0358
0359 return params_.value_grid_ids[grid_id_ref];
0360 }
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388 CELER_FUNCTION auto PhysicsTrackView::integral_xs_process(
0389 ParticleProcessId ppid) const -> IntegralXsProcess const&
0390 {
0391 CELER_EXPECT(ppid < this->num_particle_processes());
0392 return params_.integral_xs[this->process_group().integral_xs[ppid.get()]];
0393 }
0394
0395
0396
0397
0398
0399 CELER_FUNCTION real_type PhysicsTrackView::calc_xs(ParticleProcessId ppid,
0400 MaterialView const& material,
0401 Energy energy) const
0402 {
0403 real_type result = 0;
0404
0405 if (auto model_id = this->hardwired_model(ppid, energy))
0406 {
0407
0408
0409 if (model_id == params_.hardwired.livermore_pe)
0410 {
0411 auto calc_xs = MacroXsCalculator<LivermorePEMicroXsCalculator>(
0412 params_.hardwired.livermore_pe_data, material);
0413 result = calc_xs(energy);
0414 }
0415 else if (model_id == params_.hardwired.eplusgg)
0416 {
0417 auto calc_xs = EPlusGGMacroXsCalculator(
0418 params_.hardwired.eplusgg_data, material);
0419 result = calc_xs(energy);
0420 }
0421 else if (model_id == params_.hardwired.chips)
0422 {
0423 auto calc_xs = MacroXsCalculator<NeutronElasticMicroXsCalculator>(
0424 params_.hardwired.chips_data, material);
0425 result = calc_xs(energy);
0426 }
0427 }
0428 else if (auto grid_id = this->value_grid(ValueGridType::macro_xs, ppid))
0429 {
0430
0431 auto calc_xs = this->make_calculator<XsCalculator>(grid_id);
0432 result = calc_xs(energy);
0433 }
0434
0435 CELER_ENSURE(result >= 0);
0436 return result;
0437 }
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455 CELER_FUNCTION real_type
0456 PhysicsTrackView::calc_max_xs(IntegralXsProcess const& process,
0457 ParticleProcessId ppid,
0458 MaterialView const& material,
0459 Energy energy) const
0460 {
0461 CELER_EXPECT(process);
0462 CELER_EXPECT(material_ < process.energy_max_xs.size());
0463
0464 real_type energy_max_xs
0465 = params_.reals[process.energy_max_xs[material_.get()]];
0466 real_type energy_xi = energy.value() * params_.scalars.min_eprime_over_e;
0467 if (energy_max_xs >= energy_xi && energy_max_xs < energy.value())
0468 {
0469 return this->calc_xs(ppid, material, Energy{energy_max_xs});
0470 }
0471 return max(this->calc_xs(ppid, material, energy),
0472 this->calc_xs(ppid, material, Energy{energy_xi}));
0473 }
0474
0475
0476
0477
0478
0479
0480
0481 CELER_FUNCTION ModelId PhysicsTrackView::hardwired_model(ParticleProcessId ppid,
0482 Energy energy) const
0483 {
0484 ProcessId process = this->process(ppid);
0485 if ((process == params_.hardwired.photoelectric
0486 && energy < params_.hardwired.photoelectric_table_thresh)
0487 || (process == params_.hardwired.positron_annihilation)
0488 || (process == params_.hardwired.neutron_elastic))
0489 {
0490 auto find_model = this->make_model_finder(ppid);
0491 return this->model_id(find_model(energy));
0492 }
0493
0494 return {};
0495 }
0496
0497
0498
0499
0500
0501 CELER_FUNCTION ParticleProcessId PhysicsTrackView::eloss_ppid() const
0502 {
0503 return this->process_group().eloss_ppid;
0504 }
0505
0506
0507
0508
0509
0510 CELER_FUNCTION auto
0511 PhysicsTrackView::make_model_finder(ParticleProcessId ppid) const -> ModelFinder
0512 {
0513 CELER_EXPECT(ppid < this->num_particle_processes());
0514 ModelGroup const& md
0515 = params_.model_groups[this->process_group().models[ppid.get()]];
0516 return ModelFinder(params_.reals[md.energy], params_.pmodel_ids[md.model]);
0517 }
0518
0519
0520
0521
0522
0523
0524
0525
0526 CELER_FUNCTION
0527 ValueTableId PhysicsTrackView::value_table(ParticleModelId pmid) const
0528 {
0529 CELER_EXPECT(pmid < params_.model_xs.size());
0530
0531
0532 ModelXsTable const& model_xs = params_.model_xs[pmid];
0533 if (!model_xs)
0534 return {};
0535
0536
0537 CELER_ASSERT(material_ < model_xs.material.size());
0538 auto const& table_id_ref = model_xs.material[material_.get()];
0539 if (!table_id_ref)
0540 return {};
0541
0542 CELER_ASSERT(table_id_ref < params_.value_table_ids.size());
0543 return params_.value_table_ids[table_id_ref];
0544 }
0545
0546
0547
0548
0549
0550 CELER_FUNCTION
0551 TabulatedElementSelector
0552 PhysicsTrackView::make_element_selector(ValueTableId table_id,
0553 Energy energy) const
0554 {
0555 CELER_EXPECT(table_id < params_.value_tables.size());
0556 ValueTable const& table = params_.value_tables[table_id];
0557 return TabulatedElementSelector{table,
0558 params_.value_grids,
0559 params_.value_grid_ids,
0560 params_.reals,
0561 energy};
0562 }
0563
0564
0565
0566
0567
0568 CELER_FUNCTION bool PhysicsTrackView::has_at_rest() const
0569 {
0570 return this->process_group().has_at_rest;
0571 }
0572
0573
0574
0575
0576
0577 CELER_FUNCTION ModelId PhysicsTrackView::action_to_model(ActionId action) const
0578 {
0579 if (!action)
0580 return ModelId{};
0581
0582
0583 ModelId::size_type result = action.unchecked_get()
0584 - params_.scalars.model_to_action;
0585 if (result >= params_.scalars.num_models)
0586 return ModelId{};
0587
0588 return ModelId{result};
0589 }
0590
0591
0592
0593
0594
0595 CELER_FUNCTION ActionId PhysicsTrackView::model_to_action(ModelId model) const
0596 {
0597 CELER_ASSERT(model < params_.scalars.num_models);
0598 return ActionId{model.unchecked_get() + params_.scalars.model_to_action};
0599 }
0600
0601
0602
0603
0604
0605 CELER_FUNCTION ModelId PhysicsTrackView::model_id(ParticleModelId pmid) const
0606 {
0607 CELER_EXPECT(pmid < params_.model_ids.size());
0608 return params_.model_ids[pmid];
0609 }
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624 CELER_FUNCTION real_type PhysicsTrackView::range_to_step(real_type range) const
0625 {
0626 CELER_ASSERT(range >= 0);
0627 real_type const rho = params_.scalars.min_range;
0628 if (range < rho * (1 + celeritas::sqrt_tol()))
0629 {
0630
0631
0632
0633 return range;
0634 }
0635
0636 real_type const alpha = params_.scalars.max_step_over_range;
0637 real_type step = alpha * range + rho * (1 - alpha) * (2 - rho / range);
0638 CELER_ENSURE(step > 0 && step <= range);
0639 return step;
0640 }
0641
0642
0643
0644
0645
0646 CELER_FORCEINLINE_FUNCTION PhysicsParamsScalars const&
0647 PhysicsTrackView::scalars() const
0648 {
0649 return params_.scalars;
0650 }
0651
0652
0653
0654
0655
0656 CELER_FUNCTION size_type PhysicsTrackView::num_particles() const
0657 {
0658 return params_.process_groups.size();
0659 }
0660
0661
0662
0663
0664
0665
0666
0667
0668 template<class T>
0669 CELER_FUNCTION T PhysicsTrackView::make_calculator(ValueGridId id) const
0670 {
0671 CELER_EXPECT(id < params_.value_grids.size());
0672 return T{params_.value_grids[id], params_.reals};
0673 }
0674
0675
0676
0677
0678
0679 CELER_FUNCTION PhysicsTrackState& PhysicsTrackView::state()
0680 {
0681 return states_.state[track_slot_];
0682 }
0683
0684
0685 CELER_FUNCTION PhysicsTrackState const& PhysicsTrackView::state() const
0686 {
0687 return states_.state[track_slot_];
0688 }
0689
0690
0691 CELER_FUNCTION ProcessGroup const& PhysicsTrackView::process_group() const
0692 {
0693 CELER_EXPECT(particle_ < params_.process_groups.size());
0694 return params_.process_groups[particle_];
0695 }
0696
0697
0698 }