From 5d80e6c499f9e544d5674daad2f377948e1daa8f Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 31 Jan 2023 09:01:20 -0500 Subject: [PATCH 1/9] Reorganize ImportTableType enums --- src/celeritas/io/ImportPhysicsTable.cc | 13 +++++++------ src/celeritas/io/ImportPhysicsTable.hh | 16 ++++++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/celeritas/io/ImportPhysicsTable.cc b/src/celeritas/io/ImportPhysicsTable.cc index 79dbac1b26..7da1ded9c4 100644 --- a/src/celeritas/io/ImportPhysicsTable.cc +++ b/src/celeritas/io/ImportPhysicsTable.cc @@ -18,19 +18,20 @@ namespace celeritas char const* to_cstring(ImportTableType value) { static EnumStringMapper const to_cstring_impl{ + "lambda", + "lambda_prim", "dedx", + "range", + "dedx_process", - "dedx_subsec", "dedx_unrestricted", - "ionization", - "ionization_subsec", "csda_range", - "range", + + "dedx_subsec", + "ionization_subsec", "secondary_range", "inverse_range", - "lambda", "sublambda", - "lambda_prim", }; return to_cstring_impl(value); } diff --git a/src/celeritas/io/ImportPhysicsTable.hh b/src/celeritas/io/ImportPhysicsTable.hh index 8c48d85786..a3e2365356 100644 --- a/src/celeritas/io/ImportPhysicsTable.hh +++ b/src/celeritas/io/ImportPhysicsTable.hh @@ -30,19 +30,23 @@ namespace celeritas */ enum class ImportTableType { + lambda, //!< Macroscopic cross section + lambda_prim, //!< Cross section scaled by energy dedx, //!< Energy loss summed over processes + range, //!< Integrated inverse energy loss + + //// Unused by celeritas //// dedx_process, //!< Energy loss table for a process - dedx_subsec, dedx_unrestricted, - ionization, - ionization_subsec, csda_range, //!< Continuous slowing down approximation - range, + + //// Removed in Geant4@11 //// + dedx_subsec, + ionization_subsec, secondary_range, inverse_range, //!< Inverse mapping of range: (range -> energy) - lambda, //!< Macroscopic cross section sublambda, //!< For subcutoff regions - lambda_prim, //!< Cross section scaled by energy + size_ }; From 01b818bc46fd165751bb87eef3dcb4b60c91e5aa Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 31 Jan 2023 15:04:52 -0500 Subject: [PATCH 2/9] Import to MSC model rather than process --- src/celeritas/ext/GeantImporter.cc | 45 +++++++++++++----- src/celeritas/ext/RootInterfaceLinkDef.h | 1 + .../ext/detail/ImportProcessConverter.cc | 2 +- src/celeritas/io/ImportData.hh | 1 + src/celeritas/io/ImportProcess.hh | 22 ++++++++- test/celeritas/data/four-steel-slabs.root | Bin 138843 -> 141444 bytes test/celeritas/ext/GeantImporter.test.cc | 10 ++-- test/celeritas/ext/RootImporter.test.cc | 2 +- 8 files changed, 65 insertions(+), 18 deletions(-) diff --git a/src/celeritas/ext/GeantImporter.cc b/src/celeritas/ext/GeantImporter.cc index 3f8696e573..68084ee713 100644 --- a/src/celeritas/ext/GeantImporter.cc +++ b/src/celeritas/ext/GeantImporter.cc @@ -420,15 +420,17 @@ store_materials(GeantImporter::DataSelection::Flags particle_flags) /*! * Return a populated \c ImportProcess vector. */ -std::vector -store_processes(GeantImporter::DataSelection::Flags process_flags, - std::vector const& particles, - std::vector const& elements, - std::vector const& materials) +auto store_processes(GeantImporter::DataSelection::Flags process_flags, + std::vector const& particles, + std::vector const& elements, + std::vector const& materials) + -> std::pair, std::vector> { ProcessFilter include_process{process_flags}; std::vector processes; + std::vector msc_models; + detail::ImportProcessConverter load_process( detail::TableSelection::minimal, materials, elements); @@ -454,12 +456,30 @@ store_processes(GeantImporter::DataSelection::Flags process_flags, if (ImportProcess ip = load_process(*g4_particle_def, process)) { // Not an empty process, so it was not added in a previous loop - processes.push_back(std::move(ip)); + if (ip.process_class != ImportProcessClass::msc) + { + processes.push_back(std::move(ip)); + } + else + { + // Convert process to MSC + CELER_ASSERT(ip.models.size() == ip.tables.size()); + for (auto i : range(ip.models.size())) + { + CELER_ASSERT(ip.tables[i].table_type + == ImportTableType::lambda); + ImportMscModel imm; + imm.particle_pdg = ip.particle_pdg; + imm.model = std::move(ip.models[i]); + imm.lambda_table = std::move(ip.tables[i]); + msc_models.push_back(std::move(imm)); + } + } } } } CELER_LOG(debug) << "Loaded " << processes.size() << " processes"; - return processes; + return {std::move(processes), std::move(msc_models)}; } //---------------------------------------------------------------------------// @@ -561,10 +581,13 @@ ImportData GeantImporter::operator()(DataSelection const& selected) import_data.particles = store_particles(selected.particles); import_data.elements = store_elements(); import_data.materials = store_materials(selected.particles); - import_data.processes = store_processes(selected.processes, - import_data.particles, - import_data.elements, - import_data.materials); + // TODO: when moving to C++17, use a structured biding + auto processes_and_msc = store_processes(selected.processes, + import_data.particles, + import_data.elements, + import_data.materials); + import_data.processes = std::move(processes_and_msc.first); + import_data.msc_models = std::move(processes_and_msc.second); import_data.volumes = store_volumes(world_); if (selected.processes & DataSelection::em) { diff --git a/src/celeritas/ext/RootInterfaceLinkDef.h b/src/celeritas/ext/RootInterfaceLinkDef.h index cc1f79aa02..cd9c96686b 100644 --- a/src/celeritas/ext/RootInterfaceLinkDef.h +++ b/src/celeritas/ext/RootInterfaceLinkDef.h @@ -11,6 +11,7 @@ // clang-format off #pragma link C++ class celeritas::ImportParticle+; #pragma link C++ class celeritas::ImportProcess+; +#pragma link C++ class celeritas::ImportMscModel+; #pragma link C++ class celeritas::ImportPhysicsTable+; #pragma link C++ class celeritas::ImportPhysicsVector+; #pragma link C++ class celeritas::ImportMaterial+; diff --git a/src/celeritas/ext/detail/ImportProcessConverter.cc b/src/celeritas/ext/detail/ImportProcessConverter.cc index 1694060723..25093d4c5b 100644 --- a/src/celeritas/ext/detail/ImportProcessConverter.cc +++ b/src/celeritas/ext/detail/ImportProcessConverter.cc @@ -409,7 +409,7 @@ ImportProcessConverter::operator()(G4ParticleDefinition const& particle, } CELER_ENSURE(process_); - return process_; + return std::move(process_); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/io/ImportData.hh b/src/celeritas/io/ImportData.hh index f94f465251..9d4306206b 100644 --- a/src/celeritas/io/ImportData.hh +++ b/src/celeritas/io/ImportData.hh @@ -88,6 +88,7 @@ struct ImportData std::vector elements; std::vector materials; std::vector processes; + std::vector msc_models; std::vector volumes; ImportEmParameters em_params; ImportSBMap sb_data; diff --git a/src/celeritas/io/ImportProcess.hh b/src/celeritas/io/ImportProcess.hh index 259ec50cc4..eec2f070cd 100644 --- a/src/celeritas/io/ImportProcess.hh +++ b/src/celeritas/io/ImportProcess.hh @@ -150,11 +150,31 @@ struct ImportProcess explicit operator bool() const { - return process_type != ImportProcessType::size_ + return particle_pdg != 0 && process_type != ImportProcessType::size_ && process_class != ImportProcessClass::size_ && !models.empty(); } }; +//---------------------------------------------------------------------------// +/*! + * Store imported data for multiple scattering. + */ +struct ImportMscModel +{ + static constexpr auto process_type = ImportProcessType::electromagnetic; + static constexpr auto process_class = ImportProcessClass::msc; + + int particle_pdg{0}; + ImportModelClass model{ImportModelClass::size_}; + ImportPhysicsTable lambda_table; + + explicit operator bool() const + { + return particle_pdg != 0 && model != ImportModelClass::size_ + && lambda_table; + } +}; + //---------------------------------------------------------------------------// // FREE FUNCTIONS //---------------------------------------------------------------------------// diff --git a/test/celeritas/data/four-steel-slabs.root b/test/celeritas/data/four-steel-slabs.root index eb5dba87bdb16c30c18c11e37fdcc2732c2abe2a..c0d076e9d1753e6d0bee9b56506e33aa30823f7a 100644 GIT binary patch delta 43321 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 H;!YuKXci_`xZ=6 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 delta 40936 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 Ub1rgkZ*%|v0RRFXTX!{-0A_>qIRF3v diff --git a/test/celeritas/ext/GeantImporter.test.cc b/test/celeritas/ext/GeantImporter.test.cc index 2f7af50c56..387c053d20 100644 --- a/test/celeritas/ext/GeantImporter.test.cc +++ b/test/celeritas/ext/GeantImporter.test.cc @@ -106,6 +106,10 @@ auto GeantImporterTest::summarize(ImportData const& data) const -> ImportSummary pclass.insert(p.process_class); mclass.insert(p.models.begin(), p.models.end()); } + for (auto const& m : data.msc_models) + { + mclass.insert(m.model); + } s.processes = to_vec_string(pclass.begin(), pclass.end()); s.models = to_vec_string(mclass.begin(), mclass.end()); return s; @@ -192,8 +196,7 @@ TEST_F(FourSteelSlabsEmStandard, em_particles) static char const* expected_particles[] = {"e+", "e-", "gamma"}; EXPECT_VEC_EQ(expected_particles, summary.particles); - static char const* expected_processes[] = {"msc", - "e_ioni", + static char const* expected_processes[] = {"e_ioni", "e_brems", "photoelectric", "compton", @@ -225,8 +228,7 @@ TEST_F(FourSteelSlabsEmStandard, em_hadronic) static char const* expected_particles[] = {"e+", "e-", "gamma", "proton"}; EXPECT_VEC_EQ(expected_particles, summary.particles); - static char const* expected_processes[] = {"msc", - "e_ioni", + static char const* expected_processes[] = {"e_ioni", "e_brems", "photoelectric", "compton", diff --git a/test/celeritas/ext/RootImporter.test.cc b/test/celeritas/ext/RootImporter.test.cc index 77821e525e..b9cb5341b6 100644 --- a/test/celeritas/ext/RootImporter.test.cc +++ b/test/celeritas/ext/RootImporter.test.cc @@ -136,7 +136,7 @@ TEST_F(RootImporterTest, materials) TEST_F(RootImporterTest, processes) { auto const& processes = this->imported_data().processes; - EXPECT_EQ(11, processes.size()); + EXPECT_EQ(9, processes.size()); auto find_process = [&processes](PDGNumber pdg, ImportProcessClass ipc) { return std::find_if(processes.begin(), From a0a8542698d9897e81c266fc4b4852e0f0f7199a Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Wed, 1 Feb 2023 12:38:55 -0500 Subject: [PATCH 3/9] Refactor MSC to be params --- .../NoFieldAlongStepFactory.cc | 6 +- app/demo-loop/LDemoIO.cc | 9 +- src/celeritas/CMakeLists.txt | 3 +- src/celeritas/Types.hh | 9 ++ src/celeritas/em/data/UrbanMscData.hh | 11 +- src/celeritas/em/model/UrbanMscModel.hh | 88 ----------- .../alongstep/detail => em/msc}/UrbanMsc.hh | 13 +- .../{distribution => msc}/UrbanMscHelper.hh | 2 +- .../UrbanMscParams.cc} | 137 +++++++++--------- src/celeritas/em/msc/UrbanMscParams.hh | 75 ++++++++++ .../{distribution => msc}/UrbanMscScatter.hh | 2 +- .../UrbanMscStepLimit.hh | 2 +- .../em/process/MultipleScatteringProcess.cc | 69 --------- .../em/process/MultipleScatteringProcess.hh | 59 -------- src/celeritas/ext/GeantPhysicsOptions.hh | 1 + .../ext/GeantPhysicsOptionsIO.json.cc | 1 + src/celeritas/ext/detail/GeantPhysicsList.cc | 6 +- .../ext/detail/ImportProcessConverter.cc | 16 +- src/celeritas/global/alongstep/AlongStep.hh | 10 -- .../alongstep/AlongStepGeneralLinearAction.cc | 19 +-- .../alongstep/AlongStepGeneralLinearAction.hh | 6 +- .../alongstep/AlongStepUniformMscAction.cc | 30 +--- .../alongstep/AlongStepUniformMscAction.hh | 9 +- .../detail/AlongStepGeneralLinear.hh | 2 +- .../alongstep/detail/AlongStepUniformMsc.hh | 2 +- src/celeritas/phys/Model.hh | 6 +- src/celeritas/phys/PhysicsParams.cc | 1 - src/celeritas/phys/ProcessBuilder.cc | 5 +- test/celeritas/GeantTestBase.cc | 5 +- test/celeritas/MockTestBase.cc | 2 +- test/celeritas/em/UrbanMsc.test.cc | 53 +++---- test/celeritas/global/Stepper.test.cc | 16 +- test/celeritas/phys/ProcessBuilder.test.cc | 36 ----- test/celeritas/user/StepCollector.test.cc | 8 +- 34 files changed, 251 insertions(+), 468 deletions(-) delete mode 100644 src/celeritas/em/model/UrbanMscModel.hh rename src/celeritas/{global/alongstep/detail => em/msc}/UrbanMsc.hh (95%) rename src/celeritas/em/{distribution => msc}/UrbanMscHelper.hh (98%) rename src/celeritas/em/{model/UrbanMscModel.cc => msc/UrbanMscParams.cc} (70%) create mode 100644 src/celeritas/em/msc/UrbanMscParams.hh rename src/celeritas/em/{distribution => msc}/UrbanMscScatter.hh (99%) rename src/celeritas/em/{distribution => msc}/UrbanMscStepLimit.hh (99%) delete mode 100644 src/celeritas/em/process/MultipleScatteringProcess.cc delete mode 100644 src/celeritas/em/process/MultipleScatteringProcess.hh diff --git a/app/demo-geant-integration/NoFieldAlongStepFactory.cc b/app/demo-geant-integration/NoFieldAlongStepFactory.cc index 13e1dbb6f6..153965c5cb 100644 --- a/app/demo-geant-integration/NoFieldAlongStepFactory.cc +++ b/app/demo-geant-integration/NoFieldAlongStepFactory.cc @@ -10,8 +10,10 @@ #include #include +#include "celeritas/em/msc/UrbanMscParams.hh" #include "celeritas/global/alongstep/AlongStepGeneralLinearAction.hh" #include "celeritas/io/ImportData.hh" +#include "celeritas/phys/ImportedProcessAdapter.hh" namespace demo_geant { @@ -22,12 +24,12 @@ namespace demo_geant auto NoFieldAlongStepFactory::operator()(argument_type input) const -> result_type { - // Create along-step action return celeritas::AlongStepGeneralLinearAction::from_params( input.action_id, *input.material, *input.particle, - *input.physics, + celeritas::UrbanMscParams::from_import( + *input.particle, *input.material, *input.imported), input.imported->em_params.energy_loss_fluct); } diff --git a/app/demo-loop/LDemoIO.cc b/app/demo-loop/LDemoIO.cc index ee81310a2b..0eae7f2854 100644 --- a/app/demo-loop/LDemoIO.cc +++ b/app/demo-loop/LDemoIO.cc @@ -16,6 +16,7 @@ #include "corecel/io/StringUtils.hh" #include "corecel/sys/Device.hh" #include "celeritas/Units.hh" +#include "celeritas/em/msc/UrbanMscParams.hh" #include "celeritas/ext/GeantImporter.hh" #include "celeritas/ext/GeantPhysicsOptionsIO.json.hh" #include "celeritas/ext/GeantSetup.hh" @@ -272,6 +273,8 @@ TransporterInput load_input(LDemoArgs const& args) } bool eloss = imported_data.em_params.energy_loss_fluct; + auto msc = UrbanMscParams::from_import( + *params.particle, *params.material, imported_data); if (args.mag_field == LDemoArgs::no_field()) { // Create along-step action @@ -279,7 +282,7 @@ TransporterInput load_input(LDemoArgs const& args) params.action_reg->next_id(), *params.material, *params.particle, - *params.physics, + msc, eloss); params.action_reg->insert(along_step); } @@ -298,8 +301,8 @@ TransporterInput load_input(LDemoArgs const& args) f *= units::tesla; } - auto along_step = AlongStepUniformMscAction::from_params( - params.action_reg->next_id(), *params.physics, field_params); + auto along_step = std::make_shared( + params.action_reg->next_id(), field_params, msc); CELER_ASSERT(along_step->field() != LDemoArgs::no_field()); params.action_reg->insert(along_step); } diff --git a/src/celeritas/CMakeLists.txt b/src/celeritas/CMakeLists.txt index 8624ff6010..29bf06e304 100644 --- a/src/celeritas/CMakeLists.txt +++ b/src/celeritas/CMakeLists.txt @@ -40,13 +40,12 @@ list(APPEND SOURCES em/model/RayleighModel.cc em/model/RelativisticBremModel.cc em/model/SeltzerBergerModel.cc - em/model/UrbanMscModel.cc + em/msc/UrbanMscParams.cc em/process/BremsstrahlungProcess.cc em/process/ComptonProcess.cc em/process/EIonizationProcess.cc em/process/EPlusAnnihilationProcess.cc em/process/GammaConversionProcess.cc - em/process/MultipleScatteringProcess.cc em/process/PhotoelectricProcess.cc em/process/RayleighProcess.cc geo/GeoMaterialParams.cc diff --git a/src/celeritas/Types.hh b/src/celeritas/Types.hh index f01f12ef7f..4b272b1942 100644 --- a/src/celeritas/Types.hh +++ b/src/celeritas/Types.hh @@ -144,6 +144,15 @@ struct NoData { }; +//! Within-kernel state for step limits and action +struct AlongStepLocalState +{ + //! Final step limit (true path length) and action + StepLimit step_limit; + //! Smooth (straight/curved) step movement without accounting for MSC + real_type geo_step{}; +}; + //---------------------------------------------------------------------------// // HELPER FUNCTIONS (HOST) //---------------------------------------------------------------------------// diff --git a/src/celeritas/em/data/UrbanMscData.hh b/src/celeritas/em/data/UrbanMscData.hh index 39a617d811..465d839945 100644 --- a/src/celeritas/em/data/UrbanMscData.hh +++ b/src/celeritas/em/data/UrbanMscData.hh @@ -18,7 +18,7 @@ namespace celeritas { //---------------------------------------------------------------------------// /*! - * UrbanMscModel settable parameters and default values. + * Settable parameters and default values for Urban multiple scattering. * * \f$ \tau = t/\lambda \f$ where t is the true path length and \f$ \lambda \f$ * is the mean free path of the multiple scattering. The range and safety @@ -92,19 +92,18 @@ struct UrbanMscMaterialData //---------------------------------------------------------------------------// /*! * Physics IDs for MSC. + * + * TODO these will probably be changed to a map over all particle IDs. */ struct UrbanMscIds { - // TODO: remove when this is no longer a model - ActionId action; - // TODO: change to a bitset based on particle ID when we add muons, hadrons ParticleId electron; ParticleId positron; //! Whether the IDs are assigned explicit CELER_FUNCTION operator bool() const { - return action && electron && positron; + return electron && positron; } }; @@ -151,7 +150,7 @@ struct UrbanMscData //// DATA //// - //! Type-free IDs + //! Particle IDs UrbanMscIds ids; //! Mass of of electron in MeV units::MevMass electron_mass; diff --git a/src/celeritas/em/model/UrbanMscModel.hh b/src/celeritas/em/model/UrbanMscModel.hh deleted file mode 100644 index 51cdd929bf..0000000000 --- a/src/celeritas/em/model/UrbanMscModel.hh +++ /dev/null @@ -1,88 +0,0 @@ -//----------------------------------*-C++-*----------------------------------// -// Copyright 2021-2023 UT-Battelle, LLC, and other Celeritas developers. -// See the top-level COPYRIGHT file for details. -// SPDX-License-Identifier: (Apache-2.0 OR MIT) -//---------------------------------------------------------------------------// -//! \file celeritas/em/model/UrbanMscModel.hh -//---------------------------------------------------------------------------// -#pragma once - -#include "corecel/data/CollectionMirror.hh" -#include "celeritas/em/data/UrbanMscData.hh" -#include "celeritas/phys/Model.hh" - -namespace celeritas -{ -class ParticleParams; -class MaterialParams; -class MaterialView; -class ImportedProcessAdapter; - -//---------------------------------------------------------------------------// -/*! - * Set up and launch UrbanMsc model. - */ -class UrbanMscModel final : public Model -{ - public: - //@{ - //! Type aliases - using HostRef = HostCRef; - using DeviceRef = DeviceCRef; - //@} - - public: - // Construct from model ID and other necessary data - UrbanMscModel(ActionId id, - ParticleParams const& particles, - MaterialParams const& materials, - ImportedProcessAdapter const& pdata); - - // Particle types and energy ranges that this model applies to - SetApplicability applicability() const final; - - // Get the microscopic cross sections for the given particle and material - MicroXsBuilders micro_xs(Applicability) const final; - - // Apply the interaction kernel to host data - void execute(CoreHostRef const&) const final; - - // Apply the interaction kernel to device data - void execute(CoreDeviceRef const&) const final; - - // ID of the model - ActionId action_id() const final; - - //! Short name for the interaction kernel - std::string label() const final { return "msc-urban"; } - - //! Name of the model, for user interaction - std::string description() const final - { - return "Urban multiple scattering"; - } - - //! Access UrbanMsc data on the host - HostRef const& host_ref() const { return mirror_.host(); } - - //! Access UrbanMsc data on the device - DeviceRef const& device_ref() const { return mirror_.device(); } - - private: - //// DATA //// - - // Host/device storage and reference - CollectionMirror mirror_; - - //// TYPES //// - - using HostValue = HostVal; - using MaterialData = UrbanMscMaterialData; - - //// HELPER FUNCTIONS //// - - static MaterialData calc_material_data(MaterialView const& material_view); -}; - -//---------------------------------------------------------------------------// -} // namespace celeritas diff --git a/src/celeritas/global/alongstep/detail/UrbanMsc.hh b/src/celeritas/em/msc/UrbanMsc.hh similarity index 95% rename from src/celeritas/global/alongstep/detail/UrbanMsc.hh rename to src/celeritas/em/msc/UrbanMsc.hh index e4ec666d92..e0baed0995 100644 --- a/src/celeritas/global/alongstep/detail/UrbanMsc.hh +++ b/src/celeritas/em/msc/UrbanMsc.hh @@ -3,7 +3,7 @@ // See the top-level COPYRIGHT file for details. // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/global/alongstep/detail/UrbanMsc.hh +//! \file celeritas/em/msc/UrbanMsc.hh //---------------------------------------------------------------------------// #pragma once @@ -12,9 +12,10 @@ #include "corecel/Types.hh" #include "celeritas/Types.hh" #include "celeritas/em/data/UrbanMscData.hh" -#include "celeritas/em/distribution/UrbanMscScatter.hh" -#include "celeritas/em/distribution/UrbanMscStepLimit.hh" -#include "celeritas/global/alongstep/AlongStep.hh" +#include "celeritas/global/CoreTrackView.hh" + +#include "UrbanMscScatter.hh" +#include "UrbanMscStepLimit.hh" namespace celeritas { @@ -124,7 +125,9 @@ CELER_FUNCTION void UrbanMsc::calc_step(CoreTrackView const& track, // TODO: this is already kinda sorta determined inside the // UrbanMscStepLimit calculation local->step_limit.step = msc_step_result.true_path; - local->step_limit.action = msc_params_.ids.action; + // XXX should we make this a separate "implicit" ID just for marking + // that MSC limited the range? + local->step_limit.action = phys.scalars().range_action(); } } diff --git a/src/celeritas/em/distribution/UrbanMscHelper.hh b/src/celeritas/em/msc/UrbanMscHelper.hh similarity index 98% rename from src/celeritas/em/distribution/UrbanMscHelper.hh rename to src/celeritas/em/msc/UrbanMscHelper.hh index f089172a41..fc9d71b80b 100644 --- a/src/celeritas/em/distribution/UrbanMscHelper.hh +++ b/src/celeritas/em/msc/UrbanMscHelper.hh @@ -3,7 +3,7 @@ // See the top-level COPYRIGHT file for details. // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/em/distribution/UrbanMscHelper.hh +//! \file celeritas/em/msc/UrbanMscHelper.hh //---------------------------------------------------------------------------// #pragma once diff --git a/src/celeritas/em/model/UrbanMscModel.cc b/src/celeritas/em/msc/UrbanMscParams.cc similarity index 70% rename from src/celeritas/em/model/UrbanMscModel.cc rename to src/celeritas/em/msc/UrbanMscParams.cc index 7294149d51..3038cc0bb2 100644 --- a/src/celeritas/em/model/UrbanMscModel.cc +++ b/src/celeritas/em/msc/UrbanMscParams.cc @@ -1,12 +1,13 @@ //----------------------------------*-C++-*----------------------------------// -// Copyright 2020-2023 UT-Battelle, LLC, and other Celeritas developers. +// Copyright 2023 UT-Battelle, LLC, and other Celeritas developers. // See the top-level COPYRIGHT file for details. // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/em/model/UrbanMscModel.cc +//! \file celeritas/em/msc/UrbanMscParams.cc //---------------------------------------------------------------------------// -#include "UrbanMscModel.hh" +#include "UrbanMscParams.hh" +#include #include #include #include @@ -24,6 +25,7 @@ #include "celeritas/grid/ValueGridBuilder.hh" #include "celeritas/grid/ValueGridInserter.hh" #include "celeritas/grid/XsGridData.hh" +#include "celeritas/io/ImportData.hh" #include "celeritas/io/ImportProcess.hh" #include "celeritas/mat/MaterialParams.hh" #include "celeritas/mat/MaterialView.hh" @@ -36,22 +38,43 @@ namespace celeritas { //---------------------------------------------------------------------------// /*! - * Construct from model ID and other necessary data. + * Construct if Urban model is present, or else return nullptr. */ -UrbanMscModel::UrbanMscModel(ActionId id, - ParticleParams const& particles, - MaterialParams const& materials, - ImportedProcessAdapter const& pdata) +std::shared_ptr +UrbanMscParams::from_import(ParticleParams const& particles, + MaterialParams const& materials, + ImportData const& import) { - CELER_EXPECT(id); - HostValue host_data; + auto is_urban = [](ImportMscModel const& imm) { + return imm.model == ImportModelClass::urban_msc; + }; + if (!std::any_of( + import.msc_models.begin(), import.msc_models.end(), is_urban)) + { + // No Urban MSC present + return nullptr; + } + return std::make_shared( + particles, materials, import.msc_models); +} + +//---------------------------------------------------------------------------// +/*! + * Construct from cross section data and material properties. + */ +UrbanMscParams::UrbanMscParams(ParticleParams const& particles, + MaterialParams const& materials, + VecImportMscModel const& mdata_vec) +{ + HostVal host_data; - host_data.ids.action = id; host_data.ids.electron = particles.find(pdg::electron()); host_data.ids.positron = particles.find(pdg::positron()); CELER_VALIDATE(host_data.ids.electron && host_data.ids.positron, - << "missing e-/e+ (required for " << this->description() - << ")"); + << "missing e-/e+ (required for Urban MSC)"); + + // Save electron mass + host_data.electron_mass = particles.get(host_data.ids.electron).mass(); // TODO: change IDs to a vector for all particles. This model should apply // to muons and charged hadrons as well @@ -62,16 +85,44 @@ UrbanMscModel::UrbanMscModel(ActionId id, "particles other than electron and positron"; } - // Save electron mass - host_data.electron_mass = particles.get(host_data.ids.electron).mass(); + // Filter MSC data by model and particle type + std::vector urban_data(particles.size(), nullptr); + for (ImportMscModel const& imm : mdata_vec) + { + // Filter out other MSC models + if (imm.model != ImportModelClass::urban_msc) + continue; + + // Filter out unused particles + PDGNumber pdg{imm.particle_pdg}; + ParticleId pid = pdg ? particles.find(pdg) : ParticleId{}; + if (!pid) + continue; + + // Make sure the model data is unique + CELER_VALIDATE(!urban_data[pid.get()], + << "duplicate " << to_cstring(imm.model) + << " physics data for particle " + << particles.id_to_label(pid)); + urban_data[pid.get()] = &imm; + } + + auto get_lambda = [&urban_data, &particles](ParticleId pid) { + CELER_ASSERT(pid < urban_data.size()); + ImportMscModel const* imm = urban_data[pid.unchecked_get()]; + CELER_VALIDATE(imm, + << "missing Urban MSC physics data for particle " + << particles.id_to_label(pid)); + return &imm->lambda_table; + }; { // Particle-dependent data Array const par_ids{ {host_data.ids.electron, host_data.ids.positron}}; Array const xs_tables{{ - &pdata.get_lambda(par_ids[0]), - &pdata.get_lambda(par_ids[1]), + get_lambda(par_ids[0]), + get_lambda(par_ids[1]), }}; CELER_ASSERT(xs_tables[0]->x_units == ImportUnits::mev); CELER_ASSERT(xs_tables[0]->y_units == ImportUnits::cm_inv); @@ -97,7 +148,7 @@ UrbanMscModel::UrbanMscModel(ActionId id, auto&& mat = materials.get(mat_id); // Build material-dependent data - mdata.push_back(UrbanMscModel::calc_material_data(mat)); + mdata.push_back(UrbanMscParams::calc_material_data(mat)); // Build particle-dependent data const real_type zeff = mat.zeff(); @@ -135,51 +186,6 @@ UrbanMscModel::UrbanMscModel(ActionId id, CELER_ENSURE(this->mirror_); } -//---------------------------------------------------------------------------// -/*! - * Particle types and energy ranges that this model applies to. - */ -auto UrbanMscModel::applicability() const -> SetApplicability -{ - Applicability electron_msc; - electron_msc.particle = this->host_ref().ids.electron; - electron_msc.lower = zero_quantity(); - electron_msc.upper = units::MevEnergy{1e+8}; - - Applicability positron_msc = electron_msc; - positron_msc.particle = this->host_ref().ids.positron; - - return {electron_msc, positron_msc}; -} - -//---------------------------------------------------------------------------// -/*! - * Get the microscopic cross sections for the given particle and material. - */ -auto UrbanMscModel::micro_xs(Applicability) const -> MicroXsBuilders -{ - // No cross sections for multiple scattering - return {}; -} - -//---------------------------------------------------------------------------// -//!@{ -/*! - * No discrete interaction: it's integrated into along_step. - */ -void UrbanMscModel::execute(CoreDeviceRef const&) const {} -void UrbanMscModel::execute(CoreHostRef const&) const {} -//!@} - -//---------------------------------------------------------------------------// -/*! - * Get the model ID for this model. - */ -ActionId UrbanMscModel::action_id() const -{ - return this->host_ref().ids.action; -} - //---------------------------------------------------------------------------// /*! * Build UrbanMsc data per material. @@ -188,11 +194,11 @@ ActionId UrbanMscModel::action_id() const * documented in section 8.1.5 of the Geant4 10.7 Physics Reference Manual. */ UrbanMscMaterialData -UrbanMscModel::calc_material_data(MaterialView const& material_view) +UrbanMscParams::calc_material_data(MaterialView const& material_view) { using PolyQuad = PolyEvaluator; - MaterialData data; + UrbanMscMaterialData data; double zeff = material_view.zeff(); @@ -219,6 +225,5 @@ UrbanMscModel::calc_material_data(MaterialView const& material_view) return data; } - //---------------------------------------------------------------------------// } // namespace celeritas diff --git a/src/celeritas/em/msc/UrbanMscParams.hh b/src/celeritas/em/msc/UrbanMscParams.hh new file mode 100644 index 0000000000..024c45cf1f --- /dev/null +++ b/src/celeritas/em/msc/UrbanMscParams.hh @@ -0,0 +1,75 @@ +//----------------------------------*-C++-*----------------------------------// +// Copyright 2023 UT-Battelle, LLC, and other Celeritas developers. +// See the top-level COPYRIGHT file for details. +// SPDX-License-Identifier: (Apache-2.0 OR MIT) +//---------------------------------------------------------------------------// +//! \file celeritas/em/msc/UrbanMscParams.hh +//---------------------------------------------------------------------------// +#pragma once + +#include +#include + +#include "corecel/data/CollectionMirror.hh" +#include "celeritas/em/data/UrbanMscData.hh" + +namespace celeritas +{ +//---------------------------------------------------------------------------// +class ParticleParams; +class MaterialParams; +class MaterialView; +struct ImportData; +struct ImportMscModel; + +//---------------------------------------------------------------------------// +/*! + * Construct and store data for Urban multiple scattering. + * + * Multiple scattering is used by the along-step kernel(s). + * + * TODO: UrbanMsc is the only MSC model presently in Celeritas, but we should + * extend this to be an interface since it's an interchangeable component of + * the along-step kernel(s). + */ +class UrbanMscParams +{ + public: + //!@{ + //! \name Type aliases + using HostRef = HostCRef; + using DeviceRef = DeviceCRef; + using VecImportMscModel = std::vector; + //!@} + + public: + // Construct if MSC process data is present, else return nullptr + static std::shared_ptr + from_import(ParticleParams const& particles, + MaterialParams const& materials, + ImportData const& import); + + // Construct from process data + inline UrbanMscParams(ParticleParams const& particles, + MaterialParams const& materials, + VecImportMscModel const& mdata); + + // TODO: possible "applicability" interface used for constructing + // along-step kernels? + + //! Access UrbanMsc data on the host + HostRef const& host_ref() const { return mirror_.host(); } + + //! Access UrbanMsc data on the device + DeviceRef const& device_ref() const { return mirror_.device(); } + + private: + // Host/device storage and reference + CollectionMirror mirror_; + + static UrbanMscMaterialData + calc_material_data(MaterialView const& material_view); +}; + +//---------------------------------------------------------------------------// +} // namespace celeritas diff --git a/src/celeritas/em/distribution/UrbanMscScatter.hh b/src/celeritas/em/msc/UrbanMscScatter.hh similarity index 99% rename from src/celeritas/em/distribution/UrbanMscScatter.hh rename to src/celeritas/em/msc/UrbanMscScatter.hh index c4e37dbf90..292140212a 100644 --- a/src/celeritas/em/distribution/UrbanMscScatter.hh +++ b/src/celeritas/em/msc/UrbanMscScatter.hh @@ -2,7 +2,7 @@ // See the top-level COPYRIGHT file for details. // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/em/distribution/UrbanMscScatter.hh +//! \file celeritas/em/msc/UrbanMscScatter.hh //---------------------------------------------------------------------------// #pragma once diff --git a/src/celeritas/em/distribution/UrbanMscStepLimit.hh b/src/celeritas/em/msc/UrbanMscStepLimit.hh similarity index 99% rename from src/celeritas/em/distribution/UrbanMscStepLimit.hh rename to src/celeritas/em/msc/UrbanMscStepLimit.hh index c2dcee666a..2def321c23 100644 --- a/src/celeritas/em/distribution/UrbanMscStepLimit.hh +++ b/src/celeritas/em/msc/UrbanMscStepLimit.hh @@ -3,7 +3,7 @@ // See the top-level COPYRIGHT file for details. // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/em/distribution/UrbanMscStepLimit.hh +//! \file celeritas/em/msc/UrbanMscStepLimit.hh //---------------------------------------------------------------------------// #pragma once diff --git a/src/celeritas/em/process/MultipleScatteringProcess.cc b/src/celeritas/em/process/MultipleScatteringProcess.cc deleted file mode 100644 index 7d4a087bf4..0000000000 --- a/src/celeritas/em/process/MultipleScatteringProcess.cc +++ /dev/null @@ -1,69 +0,0 @@ -//----------------------------------*-C++-*----------------------------------// -// Copyright 2021-2023 UT-Battelle, LLC, and other Celeritas developers. -// See the top-level COPYRIGHT file for details. -// SPDX-License-Identifier: (Apache-2.0 OR MIT) -//---------------------------------------------------------------------------// -//! \file celeritas/em/process/MultipleScatteringProcess.cc -//---------------------------------------------------------------------------// -#include "MultipleScatteringProcess.hh" - -#include - -#include "corecel/Assert.hh" -#include "corecel/cont/Range.hh" -#include "celeritas/em/model/UrbanMscModel.hh" -#include "celeritas/io/ImportProcess.hh" -#include "celeritas/phys/PDGNumber.hh" - -namespace celeritas -{ -//---------------------------------------------------------------------------// -/*! - * Construct process from host data. - */ -MultipleScatteringProcess::MultipleScatteringProcess( - SPConstParticles particles, - SPConstMaterials materials, - SPConstImported process_data) - : particles_(std::move(particles)) - , materials_(std::move(materials)) - , imported_(process_data, - particles_, - ImportProcessClass::msc, - {pdg::electron(), pdg::positron()}) -{ - CELER_EXPECT(particles_); -} - -//---------------------------------------------------------------------------// -/*! - * Construct the models associated with this process. - */ -auto MultipleScatteringProcess::build_models(ActionIdIter start_id) const - -> VecModel -{ - return {std::make_shared( - *start_id++, *particles_, *materials_, imported_)}; -} - -//---------------------------------------------------------------------------// -/*! - * Get cross section values. - */ -auto MultipleScatteringProcess::step_limits(Applicability applicability) const - -> StepLimitBuilders -{ - return imported_.step_limits(std::move(applicability)); -} - -//---------------------------------------------------------------------------// -/*! - * Name of the process. - */ -std::string MultipleScatteringProcess::label() const -{ - return "Multiple scattering"; -} - -//---------------------------------------------------------------------------// -} // namespace celeritas diff --git a/src/celeritas/em/process/MultipleScatteringProcess.hh b/src/celeritas/em/process/MultipleScatteringProcess.hh deleted file mode 100644 index 51250c0f36..0000000000 --- a/src/celeritas/em/process/MultipleScatteringProcess.hh +++ /dev/null @@ -1,59 +0,0 @@ -//----------------------------------*-C++-*----------------------------------// -// Copyright 2021-2023 UT-Battelle, LLC, and other Celeritas developers. -// See the top-level COPYRIGHT file for details. -// SPDX-License-Identifier: (Apache-2.0 OR MIT) -//---------------------------------------------------------------------------// -//! \file celeritas/em/process/MultipleScatteringProcess.hh -//---------------------------------------------------------------------------// -#pragma once - -#include - -#include "celeritas/mat/MaterialParams.hh" -#include "celeritas/phys/Applicability.hh" -#include "celeritas/phys/ImportedProcessAdapter.hh" -#include "celeritas/phys/ParticleParams.hh" -#include "celeritas/phys/Process.hh" - -namespace celeritas -{ -//---------------------------------------------------------------------------// -/*! - * Ionization process for electrons and positrons. - */ -class MultipleScatteringProcess : public Process -{ - public: - //!@{ - //! \name Type aliases - using SPConstParticles = std::shared_ptr; - using SPConstMaterials = std::shared_ptr; - using SPConstImported = std::shared_ptr; - //!@} - - public: - // Construct with imported data - MultipleScatteringProcess(SPConstParticles particles, - SPConstMaterials materials, - SPConstImported process_data); - - // Construct the models associated with this process - VecModel build_models(ActionIdIter start_id) const final; - - // Get the interaction cross sections for the given energy range - StepLimitBuilders step_limits(Applicability applicability) const final; - - //! Whether to use the integral method to sample interaction length - bool use_integral_xs() const final { return false; } - - // Name of the process - std::string label() const final; - - private: - SPConstParticles particles_; - SPConstMaterials materials_; - ImportedProcessAdapter imported_; -}; - -//---------------------------------------------------------------------------// -} // namespace celeritas diff --git a/src/celeritas/ext/GeantPhysicsOptions.hh b/src/celeritas/ext/GeantPhysicsOptions.hh index 302584a06f..6c8e473155 100644 --- a/src/celeritas/ext/GeantPhysicsOptions.hh +++ b/src/celeritas/ext/GeantPhysicsOptions.hh @@ -28,6 +28,7 @@ enum class MscModelSelection none, urban, wentzel_vi, + all, size_ }; diff --git a/src/celeritas/ext/GeantPhysicsOptionsIO.json.cc b/src/celeritas/ext/GeantPhysicsOptionsIO.json.cc index 76d0d755f6..3c449c24f5 100644 --- a/src/celeritas/ext/GeantPhysicsOptionsIO.json.cc +++ b/src/celeritas/ext/GeantPhysicsOptionsIO.json.cc @@ -46,6 +46,7 @@ char const* to_cstring(MscModelSelection value) "none", "urban", "wentzel_vi", + "all", }; return to_cstring_impl(value); } diff --git a/src/celeritas/ext/detail/GeantPhysicsList.cc b/src/celeritas/ext/detail/GeantPhysicsList.cc index 5dd910ad42..e08330b895 100644 --- a/src/celeritas/ext/detail/GeantPhysicsList.cc +++ b/src/celeritas/ext/detail/GeantPhysicsList.cc @@ -256,7 +256,8 @@ void GeantPhysicsList::add_e_processes(G4ParticleDefinition* p) auto process = std::make_unique(); - if (options_.msc == MscModelSelection::urban) + if (options_.msc == MscModelSelection::urban + || options_.msc == MscModelSelection::all) { auto model = std::make_unique(); model->SetHighEnergyLimit(msc_energy_limit); @@ -266,7 +267,8 @@ void GeantPhysicsList::add_e_processes(G4ParticleDefinition* p) "G4UrbanMscModel"; } - if (options_.msc == MscModelSelection::wentzel_vi) + if (options_.msc == MscModelSelection::wentzel_vi + || options_.msc == MscModelSelection::all) { auto model = std::make_unique(); model->SetLowEnergyLimit(msc_energy_limit); diff --git a/src/celeritas/ext/detail/ImportProcessConverter.cc b/src/celeritas/ext/detail/ImportProcessConverter.cc index 25093d4c5b..4a2638175f 100644 --- a/src/celeritas/ext/detail/ImportProcessConverter.cc +++ b/src/celeritas/ext/detail/ImportProcessConverter.cc @@ -354,8 +354,9 @@ ImportProcessConverter::~ImportProcessConverter() = default; //---------------------------------------------------------------------------// /*! - * Add physics tables to this->process_ from a given particle and process and - * return it. If the process was already returned, \c operator() will return an + * Load and return physics tables from a given particle and process. + * + * If the process was already returned, \c operator() will return an * empty object. */ ImportProcess @@ -573,17 +574,6 @@ void ImportProcessConverter::store_msc_process( { if (G4VEmModel* model = process.GetModelByIndex(i)) { - if (i > 0) - { - // Index is beyond the code scope, which only includes one msc - // model. Skipping any further model for now - CELER_LOG(warning) - << "Cannot store multiple scattering table for process " - << process.GetProcessName() << ": skipping model " - << process.GetModelByIndex(i)->GetName(); - continue; - } - process_.models.push_back(to_import_model(*model)); this->add_table(model->GetCrossSectionTable(), ImportTableType::lambda); diff --git a/src/celeritas/global/alongstep/AlongStep.hh b/src/celeritas/global/alongstep/AlongStep.hh index bdb23ef111..d3adc313d7 100644 --- a/src/celeritas/global/alongstep/AlongStep.hh +++ b/src/celeritas/global/alongstep/AlongStep.hh @@ -17,16 +17,6 @@ namespace celeritas { -//---------------------------------------------------------------------------// -//! Within-kernel state for step limits and action -struct AlongStepLocalState -{ - //! Final step limit (true path length) and action - StepLimit step_limit; - //! Smooth (straight/curved) step movement without accounting for MSC - real_type geo_step{}; -}; - //---------------------------------------------------------------------------// /*! * Perform the along-step action using helper functions. diff --git a/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc b/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc index b55bbe04cc..a9015eaead 100644 --- a/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc +++ b/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc @@ -16,7 +16,7 @@ #include "corecel/sys/MultiExceptionHandler.hh" #include "celeritas/Types.hh" #include "celeritas/em/FluctuationParams.hh" -#include "celeritas/em/model/UrbanMscModel.hh" +#include "celeritas/em/msc/UrbanMscParams.hh" #include "celeritas/global/CoreTrackData.hh" #include "celeritas/global/KernelContextException.hh" #include "celeritas/phys/PhysicsParams.hh" @@ -34,7 +34,7 @@ std::shared_ptr AlongStepGeneralLinearAction::from_params(ActionId id, MaterialParams const& materials, ParticleParams const& particles, - PhysicsParams const& physics, + SPConstMsc const& msc, bool eloss_fluctuation) { SPConstFluctuations fluct; @@ -43,21 +43,8 @@ AlongStepGeneralLinearAction::from_params(ActionId id, fluct = std::make_shared(particles, materials); } - // Super hacky!! This will be cleaned up later. - SPConstMsc msc; - for (auto mid : range(ModelId{physics.num_models()})) - { - msc = std::dynamic_pointer_cast( - physics.model(mid)); - if (msc) - { - // Found MSC - break; - } - } - return std::make_shared( - id, std::move(fluct), std::move(msc)); + id, std::move(fluct), msc); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.hh b/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.hh index cbb7db3c9e..9304e1a352 100644 --- a/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.hh +++ b/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.hh @@ -19,7 +19,7 @@ namespace celeritas { -class UrbanMscModel; +class UrbanMscParams; class FluctuationParams; class PhysicsParams; class MaterialParams; @@ -39,7 +39,7 @@ class AlongStepGeneralLinearAction final : public ExplicitActionInterface //!@{ //! \name Type aliases using SPConstFluctuations = std::shared_ptr; - using SPConstMsc = std::shared_ptr; + using SPConstMsc = std::shared_ptr; //!@} public: @@ -47,7 +47,7 @@ class AlongStepGeneralLinearAction final : public ExplicitActionInterface from_params(ActionId id, MaterialParams const& materials, ParticleParams const& particles, - PhysicsParams const& physics, + SPConstMsc const& msc, bool eloss_fluctuation); // Construct with next action ID, and optional EM energy fluctuation diff --git a/src/celeritas/global/alongstep/AlongStepUniformMscAction.cc b/src/celeritas/global/alongstep/AlongStepUniformMscAction.cc index 4e5510dc04..4ad86e86ad 100644 --- a/src/celeritas/global/alongstep/AlongStepUniformMscAction.cc +++ b/src/celeritas/global/alongstep/AlongStepUniformMscAction.cc @@ -14,42 +14,16 @@ #include "corecel/data/Ref.hh" #include "corecel/sys/Device.hh" #include "corecel/sys/MultiExceptionHandler.hh" -#include "celeritas/em/model/UrbanMscModel.hh" +#include "celeritas/em/msc/UrbanMscParams.hh" #include "celeritas/global/CoreTrackData.hh" #include "celeritas/global/KernelContextException.hh" -#include "celeritas/phys/PhysicsParams.hh" +#include "celeritas/global/alongstep/AlongStepLauncher.hh" #include "AlongStepLauncher.hh" #include "detail/AlongStepUniformMsc.hh" namespace celeritas { -//---------------------------------------------------------------------------// -/*! - * Construct the along-step action from input parameters. - */ -std::shared_ptr -AlongStepUniformMscAction::from_params(ActionId id, - PhysicsParams const& physics, - UniformFieldParams const& field_params) -{ - // TODO: Super hacky!! This will be cleaned up later. - SPConstMsc msc; - for (auto mid : range(ModelId{physics.num_models()})) - { - msc = std::dynamic_pointer_cast( - physics.model(mid)); - if (msc) - { - // Found MSC - break; - } - } - - return std::make_shared( - id, field_params, std::move(msc)); -} - //---------------------------------------------------------------------------// /*! * Construct with next action ID and optional energy loss parameters. diff --git a/src/celeritas/global/alongstep/AlongStepUniformMscAction.hh b/src/celeritas/global/alongstep/AlongStepUniformMscAction.hh index f103107857..873c3cbf35 100644 --- a/src/celeritas/global/alongstep/AlongStepUniformMscAction.hh +++ b/src/celeritas/global/alongstep/AlongStepUniformMscAction.hh @@ -18,7 +18,7 @@ namespace celeritas { -class UrbanMscModel; +class UrbanMscParams; class PhysicsParams; class MaterialParams; class ParticleParams; @@ -32,15 +32,10 @@ class AlongStepUniformMscAction final : public ExplicitActionInterface public: //!@{ //! \name Type aliases - using SPConstMsc = std::shared_ptr; + using SPConstMsc = std::shared_ptr; //!@} public: - static std::shared_ptr - from_params(ActionId id, - PhysicsParams const& physics, - UniformFieldParams const& field_params); - // Construct with next action ID, optional MSC, magnetic field AlongStepUniformMscAction(ActionId id, UniformFieldParams const& field_params, diff --git a/src/celeritas/global/alongstep/detail/AlongStepGeneralLinear.hh b/src/celeritas/global/alongstep/detail/AlongStepGeneralLinear.hh index d7c8450d26..3dc2b628ee 100644 --- a/src/celeritas/global/alongstep/detail/AlongStepGeneralLinear.hh +++ b/src/celeritas/global/alongstep/detail/AlongStepGeneralLinear.hh @@ -9,10 +9,10 @@ #include "celeritas/em/data/FluctuationData.hh" #include "celeritas/em/data/UrbanMscData.hh" +#include "celeritas/em/msc/UrbanMsc.hh" #include "AlongStepNeutral.hh" #include "EnergyLossFluctApplier.hh" -#include "UrbanMsc.hh" namespace celeritas { diff --git a/src/celeritas/global/alongstep/detail/AlongStepUniformMsc.hh b/src/celeritas/global/alongstep/detail/AlongStepUniformMsc.hh index c33126e2d9..d47f559868 100644 --- a/src/celeritas/global/alongstep/detail/AlongStepUniformMsc.hh +++ b/src/celeritas/global/alongstep/detail/AlongStepUniformMsc.hh @@ -10,6 +10,7 @@ #include "corecel/Types.hh" #include "celeritas/em/data/FluctuationData.hh" #include "celeritas/em/data/UrbanMscData.hh" +#include "celeritas/em/msc/UrbanMsc.hh" #include "celeritas/field/DormandPrinceStepper.hh" #include "celeritas/field/FieldDriverOptions.hh" #include "celeritas/field/MakeMagFieldPropagator.hh" @@ -17,7 +18,6 @@ #include "AlongStepNeutral.hh" #include "EnergyLossApplier.hh" -#include "UrbanMsc.hh" namespace celeritas { diff --git a/src/celeritas/phys/Model.hh b/src/celeritas/phys/Model.hh index e1c3d6694a..8525cf0864 100644 --- a/src/celeritas/phys/Model.hh +++ b/src/celeritas/phys/Model.hh @@ -24,7 +24,7 @@ namespace celeritas { //---------------------------------------------------------------------------// /*! - * Abstract base class representing a physics model. + * Abstract base class representing a physics model with a discrete action. * * A Model is a representation (often an approximation) to a physics process * such as Compton scattering that is valid for one or more particle types in a @@ -41,8 +41,8 @@ namespace celeritas * - It precalculates macroscopic cross sections for each range of * applicability. * - It precalculates energy loss rates and range limiters for each range. - * - If it has an interaction cross section, it provides an "interact" method - * for undergoing an interaction and possibly emitting secondaries. + * - If it has an interaction cross section, it provides an "execute" method + * for applying the interaction and possibly emitting secondaries. * * This class is similar to Geant4's G4VContinuousDiscrete process, but more * limited. diff --git a/src/celeritas/phys/PhysicsParams.cc b/src/celeritas/phys/PhysicsParams.cc index 970b523526..ea7418e183 100644 --- a/src/celeritas/phys/PhysicsParams.cc +++ b/src/celeritas/phys/PhysicsParams.cc @@ -30,7 +30,6 @@ #include "celeritas/em/model/CombinedBremModel.hh" #include "celeritas/em/model/EPlusGGModel.hh" #include "celeritas/em/model/LivermorePEModel.hh" -#include "celeritas/em/process/MultipleScatteringProcess.hh" #include "celeritas/global/ActionInterface.hh" #include "celeritas/global/ActionRegistry.hh" #include "celeritas/grid/UniformGrid.hh" diff --git a/src/celeritas/phys/ProcessBuilder.cc b/src/celeritas/phys/ProcessBuilder.cc index 0a62cc09b0..dd11fd938f 100644 --- a/src/celeritas/phys/ProcessBuilder.cc +++ b/src/celeritas/phys/ProcessBuilder.cc @@ -18,7 +18,6 @@ #include "celeritas/em/process/EIonizationProcess.hh" #include "celeritas/em/process/EPlusAnnihilationProcess.hh" #include "celeritas/em/process/GammaConversionProcess.hh" -#include "celeritas/em/process/MultipleScatteringProcess.hh" #include "celeritas/em/process/PhotoelectricProcess.hh" #include "celeritas/em/process/RayleighProcess.hh" #include "celeritas/io/ImportData.hh" @@ -100,6 +99,7 @@ ProcessBuilder::~ProcessBuilder() = default; * Construct a \c Process from a given processs class. * * This may return a null process (with a warning) if the user specifically + * requests that the process be omitted. */ auto ProcessBuilder::operator()(IPC ipc) -> SPProcess { @@ -141,8 +141,7 @@ auto ProcessBuilder::operator()(IPC ipc) -> SPProcess //---------------------------------------------------------------------------// auto ProcessBuilder::build_msc() -> SPProcess { - return std::make_shared( - this->particle(), this->material(), this->imported()); + return nullptr; } //---------------------------------------------------------------------------// diff --git a/test/celeritas/GeantTestBase.cc b/test/celeritas/GeantTestBase.cc index 987a77b2ef..2ea72d5072 100644 --- a/test/celeritas/GeantTestBase.cc +++ b/test/celeritas/GeantTestBase.cc @@ -11,6 +11,7 @@ #include "celeritas_cmake_strings.h" #include "corecel/io/Logger.hh" +#include "celeritas/em/msc/UrbanMscParams.hh" #include "celeritas/ext/GeantImporter.hh" #include "celeritas/ext/GeantPhysicsOptions.hh" #include "celeritas/ext/GeantSetup.hh" @@ -117,11 +118,13 @@ auto GeantTestBase::build_init() -> SPConstTrackInit auto GeantTestBase::build_along_step() -> SPConstAction { auto& action_reg = *this->action_reg(); + auto msc = UrbanMscParams::from_import( + *this->particle(), *this->material(), this->imported_data()); auto result = AlongStepGeneralLinearAction::from_params( action_reg.next_id(), *this->material(), *this->particle(), - *this->physics(), + msc, this->imported_data().em_params.energy_loss_fluct); CELER_ASSERT(result); CELER_ASSERT(result->has_fluct() diff --git a/test/celeritas/MockTestBase.cc b/test/celeritas/MockTestBase.cc index af72c9248d..11a40a15af 100644 --- a/test/celeritas/MockTestBase.cc +++ b/test/celeritas/MockTestBase.cc @@ -206,7 +206,7 @@ auto MockTestBase::build_along_step() -> SPConstAction = AlongStepGeneralLinearAction::from_params(action_reg.next_id(), *this->material(), *this->particle(), - *this->physics(), + nullptr, false); CELER_ASSERT(result); CELER_ASSERT(!result->has_fluct()); diff --git a/test/celeritas/em/UrbanMsc.test.cc b/test/celeritas/em/UrbanMsc.test.cc index 4471955135..4e6733579d 100644 --- a/test/celeritas/em/UrbanMsc.test.cc +++ b/test/celeritas/em/UrbanMsc.test.cc @@ -5,22 +5,24 @@ //---------------------------------------------------------------------------// //! \file celeritas/em/UrbanMsc.test.cc //---------------------------------------------------------------------------// +#include "celeritas/em/msc/UrbanMsc.hh" + #include #include "corecel/cont/Range.hh" #include "corecel/data/CollectionStateStore.hh" #include "celeritas/RootTestBase.hh" -#include "celeritas/em/distribution/UrbanMscScatter.hh" -#include "celeritas/em/distribution/UrbanMscStepLimit.hh" -#include "celeritas/em/model/UrbanMscModel.hh" +#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/msc/UrbanMscScatter.hh" +#include "celeritas/em/msc/UrbanMscStepLimit.hh" #include "celeritas/geo/GeoData.hh" #include "celeritas/geo/GeoParams.hh" #include "celeritas/geo/GeoTrackView.hh" #include "celeritas/grid/RangeCalculator.hh" #include "celeritas/mat/MaterialParams.hh" -#include "celeritas/phys/ParticleParams.hh" -#include "celeritas/phys/ParticleData.hh" #include "celeritas/phys/PDGNumber.hh" +#include "celeritas/phys/ParticleData.hh" +#include "celeritas/phys/ParticleParams.hh" #include "celeritas/phys/PhysicsParams.hh" #include "celeritas/phys/PhysicsTrackView.hh" #include "celeritas/track/SimData.hh" @@ -54,6 +56,7 @@ class UrbanMscTest : public RootTestBase { protected: using RandomEngine = DiagnosticRngEngine; + using PhysicsStateStore = CollectionStateStore; using ParticleStateStore @@ -66,24 +69,15 @@ class UrbanMscTest : public RootTestBase void SetUp() override { - const auto& physics = *this->physics(); - // Find MSC model - for (auto mid : range(ModelId{physics.num_models()})) - { - msc_model_ = std::dynamic_pointer_cast( - physics.model(mid)); - if (msc_model_) - { - // Found MSC - break; - } - } - ASSERT_TRUE(msc_model_); + // Load MSC data + msc_params_ = UrbanMscParams::from_import( + *this->particle(), *this->material(), this->imported_data()); + ASSERT_TRUE(msc_params_); // Allocate particle state auto state_size = 1; physics_state_ - = PhysicsStateStore(physics.host_ref(), state_size); + = PhysicsStateStore(this->physics()->host_ref(), state_size); particle_state_ = ParticleStateStore(this->particle()->host_ref(), state_size); geo_state_ = GeoStateStore(this->geometry()->host_ref(), state_size); @@ -131,7 +125,7 @@ class UrbanMscTest : public RootTestBase } protected: - std::shared_ptr msc_model_; + std::shared_ptr msc_params_; PhysicsStateStore physics_state_; ParticleStateStore particle_state_; @@ -149,7 +143,8 @@ TEST_F(UrbanMscTest, coeff_data) ASSERT_TRUE(mid); // Check MscMaterialDara for the current material (G4_STAINLESS-STEEL) - UrbanMscMaterialData const& msc = msc_model_->host_ref().material_data[mid]; + UrbanMscMaterialData const& msc + = msc_params_->host_ref().material_data[mid]; EXPECT_SOFT_EQ(msc.coeffth1, 0.97326969977637379); EXPECT_SOFT_EQ(msc.coeffth2, 0.044188139325421663); @@ -227,17 +222,17 @@ TEST_F(UrbanMscTest, msc_scattering) PhysicsTrackView phys = this->make_track_view( pdg::electron(), mid, inc_energy); - UrbanMscStepLimit calc_limit(msc_model_->host_ref(), - par_track_view, - &phys, - material_view.material_id(), - geo_view.is_on_boundary(), - geo_view.find_safety(), - step[i]); + UrbanMscStepLimit calc_limit(msc_params_->host_ref(), + par_track_view, + &phys, + material_view.material_id(), + geo_view.is_on_boundary(), + geo_view.find_safety(), + step[i]); step_result = calc_limit(rng); - UrbanMscScatter scatter(msc_model_->host_ref(), + UrbanMscScatter scatter(msc_params_->host_ref(), par_track_view, &geo_view, phys, diff --git a/test/celeritas/global/Stepper.test.cc b/test/celeritas/global/Stepper.test.cc index cf914d54d0..d1677fbe14 100644 --- a/test/celeritas/global/Stepper.test.cc +++ b/test/celeritas/global/Stepper.test.cc @@ -12,6 +12,7 @@ #include "corecel/Types.hh" #include "corecel/cont/Range.hh" #include "corecel/cont/Span.hh" +#include "celeritas/em/msc/UrbanMscParams.hh" #include "celeritas/ext/GeantPhysicsOptions.hh" #include "celeritas/field/UniformFieldData.hh" #include "celeritas/global/ActionInterface.hh" @@ -130,10 +131,13 @@ class TestEm15Field : public TestEm15Base, public StepperTestBase auto& action_reg = *this->action_reg(); UniformFieldParams field_params; field_params.field = {0, 0, 1e-3 * units::tesla}; - auto result = AlongStepUniformMscAction::from_params( - action_reg.next_id(), *this->physics(), field_params); - CELER_ASSERT(result); - CELER_ASSERT(result->has_msc() == true); + + auto msc = UrbanMscParams::from_import( + *this->particle(), *this->material(), this->imported_data()); + CELER_ASSERT(msc); + + auto result = std::make_shared( + action_reg.next_id(), field_params, msc); action_reg.insert(result); return result; } @@ -323,7 +327,6 @@ TEST_F(TestEm3Msc, setup) "Positron annihiliation", "Electron/positron ionization", "Bremsstrahlung", - "Multiple scattering", }; EXPECT_VEC_EQ(expected_processes, result.processes); static char const* const expected_actions[] = { @@ -336,7 +339,6 @@ TEST_F(TestEm3Msc, setup) "annihil-2-gamma", "ioni-moller-bhabha", "brems-combined", - "msc-urban", "geo-boundary", "dummy-action", }; @@ -492,7 +494,6 @@ TEST_F(TestEm15Field, setup) "Positron annihiliation", "Electron/positron ionization", "Bremsstrahlung", - "Multiple scattering", }; EXPECT_VEC_EQ(expected_processes, result.processes); static char const* const expected_actions[] = { @@ -506,7 +507,6 @@ TEST_F(TestEm15Field, setup) "ioni-moller-bhabha", "brems-sb", "brems-rel", - "msc-urban", "geo-boundary", "dummy-action", }; diff --git a/test/celeritas/phys/ProcessBuilder.test.cc b/test/celeritas/phys/ProcessBuilder.test.cc index e4d71298d9..add8258d68 100644 --- a/test/celeritas/phys/ProcessBuilder.test.cc +++ b/test/celeritas/phys/ProcessBuilder.test.cc @@ -13,7 +13,6 @@ #include "celeritas/em/process/EIonizationProcess.hh" #include "celeritas/em/process/EPlusAnnihilationProcess.hh" #include "celeritas/em/process/GammaConversionProcess.hh" -#include "celeritas/em/process/MultipleScatteringProcess.hh" #include "celeritas/em/process/PhotoelectricProcess.hh" #include "celeritas/em/process/RayleighProcess.hh" #include "celeritas/ext/RootImporter.hh" @@ -255,41 +254,6 @@ TEST_F(ProcessBuilderTest, gamma_conversion) } } -TEST_F(ProcessBuilderTest, msc) -{ - ProcessBuilder build_process( - this->import_data(), this->particle(), this->material(), Options{}); - // Create process - auto process = build_process(IPC::msc); - EXPECT_PROCESS_TYPE(MultipleScatteringProcess, process.get()); - - // Test model - auto models = process->build_models(ActionIdIter{}); - ASSERT_EQ(1, models.size()); - ASSERT_TRUE(models.front()); - EXPECT_EQ("msc-urban", models.front()->label()); - auto all_applic = models.front()->applicability(); - ASSERT_EQ(2, all_applic.size()); - Applicability applic = *all_applic.begin(); - - for (auto mat_id : range(MaterialId{this->material()->num_materials()})) - { - // Test step limits - { - applic.material = mat_id; - auto builders = process->step_limits(applic); - EXPECT_FALSE(builders[VGT::macro_xs]); - } - - // Test micro xs - for (auto const& model : models) - { - auto builders = model->micro_xs(applic); - EXPECT_TRUE(builders.empty()); - } - } -} - TEST_F(ProcessBuilderTest, photoelectric) { if (!this->has_le_data()) diff --git a/test/celeritas/user/StepCollector.test.cc b/test/celeritas/user/StepCollector.test.cc index 2d055ca17e..c2bcc3d9ea 100644 --- a/test/celeritas/user/StepCollector.test.cc +++ b/test/celeritas/user/StepCollector.test.cc @@ -8,6 +8,7 @@ #include "celeritas/user/StepCollector.hh" #include "corecel/cont/Span.hh" +#include "celeritas/em/msc/UrbanMscParams.hh" #include "celeritas/global/ActionRegistry.hh" #include "celeritas/global/Stepper.hh" #include "celeritas/global/alongstep/AlongStepUniformMscAction.hh" @@ -77,8 +78,11 @@ class TestEm3CollectorTestBase : public TestEm3Base, auto& action_reg = *this->action_reg(); UniformFieldParams field_params; field_params.field = {0, 0, 1 * units::tesla}; - auto result = AlongStepUniformMscAction::from_params( - action_reg.next_id(), *this->physics(), field_params); + auto msc = UrbanMscParams::from_import( + *this->particle(), *this->material(), this->imported_data()); + + auto result = std::make_shared( + action_reg.next_id(), field_params, msc); CELER_ASSERT(result); CELER_ASSERT(result->has_msc()); action_reg.insert(result); From 3b20542aa16d6d8b5b9ab4d2eaaab54ff552e461 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Thu, 2 Feb 2023 14:46:59 -0500 Subject: [PATCH 4/9] Add MSC range implicit action to physics --- src/celeritas/em/msc/UrbanMsc.hh | 4 +- src/celeritas/phys/PhysicsData.hh | 8 +++- src/celeritas/phys/PhysicsParams.cc | 12 ++++-- src/celeritas/phys/PhysicsParams.hh | 1 + test/celeritas/global/AlongStep.test.cc | 2 +- test/celeritas/phys/MockModel.cc | 4 +- test/celeritas/phys/Physics.test.cc | 51 +++++++++++++------------ 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/celeritas/em/msc/UrbanMsc.hh b/src/celeritas/em/msc/UrbanMsc.hh index e0baed0995..6312c695a0 100644 --- a/src/celeritas/em/msc/UrbanMsc.hh +++ b/src/celeritas/em/msc/UrbanMsc.hh @@ -125,9 +125,7 @@ CELER_FUNCTION void UrbanMsc::calc_step(CoreTrackView const& track, // TODO: this is already kinda sorta determined inside the // UrbanMscStepLimit calculation local->step_limit.step = msc_step_result.true_path; - // XXX should we make this a separate "implicit" ID just for marking - // that MSC limited the range? - local->step_limit.action = phys.scalars().range_action(); + local->step_limit.action = phys.scalars().msc_action(); } } diff --git a/src/celeritas/phys/PhysicsData.hh b/src/celeritas/phys/PhysicsData.hh index 8d86c3d5c3..4863e425ab 100644 --- a/src/celeritas/phys/PhysicsData.hh +++ b/src/celeritas/phys/PhysicsData.hh @@ -235,7 +235,7 @@ struct PhysicsParamsScalars //! True if assigned explicit CELER_FUNCTION operator bool() const { - return max_particle_processes > 0 && model_to_action >= 3 + return max_particle_processes > 0 && model_to_action >= 4 && num_models > 0 && min_range > 0 && max_step_over_range > 0 && min_eprime_over_e > 0 && value_as(eloss_calc_limit) > 0 @@ -244,6 +244,12 @@ struct PhysicsParamsScalars == static_cast(fixed_step_action)); } + //! Stop early due to MSC limitation + CELER_FORCEINLINE_FUNCTION ActionId msc_action() const + { + return ActionId{model_to_action - 4}; + } + //! Stop early due to range limitation CELER_FORCEINLINE_FUNCTION ActionId range_action() const { diff --git a/src/celeritas/phys/PhysicsParams.cc b/src/celeritas/phys/PhysicsParams.cc index ea7418e183..4ee4a4d4ca 100644 --- a/src/celeritas/phys/PhysicsParams.cc +++ b/src/celeritas/phys/PhysicsParams.cc @@ -89,6 +89,13 @@ PhysicsParams::PhysicsParams(Input inp) inp.action_registry->insert(pre_step_action); pre_step_action_ = std::move(pre_step_action); + auto msc_action = make_shared( + action_reg.next_id(), + "msc-range", + "range limitation due to multiple scattering"); + action_reg.insert(msc_action); + msc_action_ = std::move(msc_action); + auto range_action = make_shared( action_reg.next_id(), "eloss-range", @@ -473,10 +480,7 @@ void PhysicsParams::build_xs(Options const& opts, CELER_VALIDATE( std::any_of(builders.begin(), builders.end(), - [](UPGridBuilder const& p) { return bool(p); }) - // TODO: super hack since MSC doesn't have any sampled - // or along-step interaction: fix while refactoring - || proc.label() == "Multiple scattering", + [](UPGridBuilder const& p) { return bool(p); }), << "process '" << proc.label() << "' has neither interaction nor energy loss (it must " "have at least one)"); diff --git a/src/celeritas/phys/PhysicsParams.hh b/src/celeritas/phys/PhysicsParams.hh index e8745aef6d..d861fd4a8b 100644 --- a/src/celeritas/phys/PhysicsParams.hh +++ b/src/celeritas/phys/PhysicsParams.hh @@ -185,6 +185,7 @@ class PhysicsParams // Kernels/actions SPAction pre_step_action_; + SPAction msc_action_; SPAction range_action_; SPAction discrete_action_; SPAction integral_rejection_action_; diff --git a/test/celeritas/global/AlongStep.test.cc b/test/celeritas/global/AlongStep.test.cc index dff73ed304..506a826820 100644 --- a/test/celeritas/global/AlongStep.test.cc +++ b/test/celeritas/global/AlongStep.test.cc @@ -157,7 +157,7 @@ TEST_F(Em3AlongStepTest, msc_nofluct) EXPECT_SOFT_NEAR(0.42060290539404, result.angle, 1e-3); EXPECT_SOFT_EQ(5.3240431819014e-12, result.time); EXPECT_SOFT_EQ(0.1502064087009, result.step); - EXPECT_EQ("msc-urban", result.action); + EXPECT_EQ("msc-range", result.action); } { SCOPED_TRACE("electron very near (1um) boundary"); diff --git a/test/celeritas/phys/MockModel.cc b/test/celeritas/phys/MockModel.cc index f04e7b9949..a6bdb4cca3 100644 --- a/test/celeritas/phys/MockModel.cc +++ b/test/celeritas/phys/MockModel.cc @@ -68,13 +68,13 @@ void MockModel::execute(CoreDeviceRef const&) const std::string MockModel::label() const { - return std::string("mock-model-") + std::to_string(data_.id.get()); + return std::string("mock-model-") + std::to_string(data_.id.get() - 4); } std::string MockModel::description() const { std::ostringstream os; - os << "MockModel(" << data_.id.get() + os << "MockModel(" << (data_.id.get() - 4) << ", p=" << data_.applic.particle.get() << ", emin=" << data_.applic.lower.value() << ", emax=" << data_.applic.upper.value() << ")"; diff --git a/test/celeritas/phys/Physics.test.cc b/test/celeritas/phys/Physics.test.cc index f33e4ea14c..e42685dfa3 100644 --- a/test/celeritas/phys/Physics.test.cc +++ b/test/celeritas/phys/Physics.test.cc @@ -70,31 +70,33 @@ TEST_F(PhysicsParamsTest, accessors) model_desc.push_back(m.description()); } - static const std::string expected_model_names[] = {"mock-model-4", - "mock-model-5", - "mock-model-6", - "mock-model-7", - "mock-model-8", - "mock-model-9", - "mock-model-10", - "mock-model-11", - "mock-model-12", - "mock-model-13", - "mock-model-14"}; + static const std::string expected_model_names[] = { + "mock-model-1", + "mock-model-2", + "mock-model-3", + "mock-model-4", + "mock-model-5", + "mock-model-6", + "mock-model-7", + "mock-model-8", + "mock-model-9", + "mock-model-10", + "mock-model-11", + }; EXPECT_VEC_EQ(expected_model_names, model_names); static const std::string expected_model_desc[] - = {"MockModel(4, p=0, emin=1e-06, emax=100)", - "MockModel(5, p=1, emin=1, emax=100)", - "MockModel(6, p=0, emin=1e-06, emax=100)", - "MockModel(7, p=1, emin=0.001, emax=1)", - "MockModel(8, p=1, emin=1, emax=10)", - "MockModel(9, p=1, emin=10, emax=100)", - "MockModel(10, p=2, emin=0.001, emax=1)", - "MockModel(11, p=2, emin=1, emax=100)", - "MockModel(12, p=1, emin=0.001, emax=10)", - "MockModel(13, p=2, emin=0.001, emax=10)", - "MockModel(14, p=3, emin=1e-05, emax=10)"}; + = {"MockModel(1, p=0, emin=1e-06, emax=100)", + "MockModel(2, p=1, emin=1, emax=100)", + "MockModel(3, p=0, emin=1e-06, emax=100)", + "MockModel(4, p=1, emin=0.001, emax=1)", + "MockModel(5, p=1, emin=1, emax=10)", + "MockModel(6, p=1, emin=10, emax=100)", + "MockModel(7, p=2, emin=0.001, emax=1)", + "MockModel(8, p=2, emin=1, emax=100)", + "MockModel(9, p=1, emin=0.001, emax=10)", + "MockModel(10, p=2, emin=0.001, emax=10)", + "MockModel(11, p=3, emin=1e-05, emax=10)"}; EXPECT_VEC_EQ(expected_model_desc, model_desc); // Test host-accessible process map @@ -127,8 +129,9 @@ TEST_F(PhysicsParamsTest, output) if (CELERITAS_USE_JSON) { EXPECT_EQ( - R"json({"models":[{"label":"mock-model-4","process":0},{"label":"mock-model-5","process":0},{"label":"mock-model-6","process":1},{"label":"mock-model-7","process":2},{"label":"mock-model-8","process":2},{"label":"mock-model-9","process":2},{"label":"mock-model-10","process":3},{"label":"mock-model-11","process":3},{"label":"mock-model-12","process":4},{"label":"mock-model-13","process":4},{"label":"mock-model-14","process":5}],"options":{"eloss_calc_limit":[0.001,"MeV"],"fixed_step_limiter":0.0,"linear_loss_limit":0.01,"max_step_over_range":0.2,"min_eprime_over_e":0.8,"min_range":0.1},"processes":[{"label":"scattering"},{"label":"absorption"},{"label":"purrs"},{"label":"hisses"},{"label":"meows"},{"label":"barks"}],"sizes":{"integral_xs":8,"model_groups":8,"model_ids":11,"process_groups":4,"process_ids":8,"reals":196,"value_grid_ids":75,"value_grids":75,"value_tables":35}})json", - to_string(out)); + R"json({"models":[{"label":"mock-model-1","process":0},{"label":"mock-model-2","process":0},{"label":"mock-model-3","process":1},{"label":"mock-model-4","process":2},{"label":"mock-model-5","process":2},{"label":"mock-model-6","process":2},{"label":"mock-model-7","process":3},{"label":"mock-model-8","process":3},{"label":"mock-model-9","process":4},{"label":"mock-model-10","process":4},{"label":"mock-model-11","process":5}],"options":{"eloss_calc_limit":[0.001,"MeV"],"fixed_step_limiter":0.0,"linear_loss_limit":0.01,"max_step_over_range":0.2,"min_eprime_over_e":0.8,"min_range":0.1},"processes":[{"label":"scattering"},{"label":"absorption"},{"label":"purrs"},{"label":"hisses"},{"label":"meows"},{"label":"barks"}],"sizes":{"integral_xs":8,"model_groups":8,"model_ids":11,"process_groups":4,"process_ids":8,"reals":196,"value_grid_ids":75,"value_grids":75,"value_tables":35}})json", + to_string(out)) + << "R\"json(" << to_string(out) << ")json"; } } From 683b45a19efb4b7dba903593e3056e370f87163c Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Thu, 2 Feb 2023 22:42:01 -0500 Subject: [PATCH 5/9] Fix SWIG :( --- src/celeritas/io/ImportProcess.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/celeritas/io/ImportProcess.hh b/src/celeritas/io/ImportProcess.hh index eec2f070cd..abd2389369 100644 --- a/src/celeritas/io/ImportProcess.hh +++ b/src/celeritas/io/ImportProcess.hh @@ -161,8 +161,10 @@ struct ImportProcess */ struct ImportMscModel { +#ifndef SWIG static constexpr auto process_type = ImportProcessType::electromagnetic; static constexpr auto process_class = ImportProcessClass::msc; +#endif int particle_pdg{0}; ImportModelClass model{ImportModelClass::size_}; From 3431fe6750e949f987ffe37878743642fb5719d0 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Thu, 2 Feb 2023 22:51:00 -0500 Subject: [PATCH 6/9] Remove unused MSC process emitter --- src/celeritas/phys/ProcessBuilder.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/celeritas/phys/ProcessBuilder.cc b/src/celeritas/phys/ProcessBuilder.cc index dd11fd938f..a3957f5b7f 100644 --- a/src/celeritas/phys/ProcessBuilder.cc +++ b/src/celeritas/phys/ProcessBuilder.cc @@ -119,7 +119,6 @@ auto ProcessBuilder::operator()(IPC ipc) -> SPProcess {IPC::conversion, &ProcessBuilder::build_conversion}, {IPC::e_brems, &ProcessBuilder::build_ebrems}, {IPC::e_ioni, &ProcessBuilder::build_eioni}, - {IPC::msc, &ProcessBuilder::build_msc}, {IPC::photoelectric, &ProcessBuilder::build_photoelectric}, {IPC::rayleigh, &ProcessBuilder::build_rayleigh}, }; @@ -138,12 +137,6 @@ auto ProcessBuilder::operator()(IPC ipc) -> SPProcess } } -//---------------------------------------------------------------------------// -auto ProcessBuilder::build_msc() -> SPProcess -{ - return nullptr; -} - //---------------------------------------------------------------------------// auto ProcessBuilder::build_eioni() -> SPProcess { From 6880880b51860f90a59ad6a702f865075e565fc1 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Thu, 2 Feb 2023 22:58:28 -0500 Subject: [PATCH 7/9] Fix typos --- src/celeritas/ext/GeantImporter.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/celeritas/ext/GeantImporter.cc b/src/celeritas/ext/GeantImporter.cc index 68084ee713..db79682f89 100644 --- a/src/celeritas/ext/GeantImporter.cc +++ b/src/celeritas/ext/GeantImporter.cc @@ -462,7 +462,7 @@ auto store_processes(GeantImporter::DataSelection::Flags process_flags, } else { - // Convert process to MSC + // Unfold process to MSC models CELER_ASSERT(ip.models.size() == ip.tables.size()); for (auto i : range(ip.models.size())) { @@ -581,7 +581,7 @@ ImportData GeantImporter::operator()(DataSelection const& selected) import_data.particles = store_particles(selected.particles); import_data.elements = store_elements(); import_data.materials = store_materials(selected.particles); - // TODO: when moving to C++17, use a structured biding + // TODO: when moving to C++17, use a structured binding auto processes_and_msc = store_processes(selected.processes, import_data.particles, import_data.elements, From 088c393a77ac167e76cdf7c7bcad4d633589b4c9 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Fri, 3 Feb 2023 16:45:12 -0500 Subject: [PATCH 8/9] Fix example --- example/accel/accel.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/example/accel/accel.cc b/example/accel/accel.cc index eb873cffa8..748cdfe559 100644 --- a/example/accel/accel.cc +++ b/example/accel/accel.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +65,8 @@ make_nofield_along_step(celeritas::AlongStepFactoryInput const& input) input.action_id, *input.material, *input.particle, - *input.physics, + celeritas::UrbanMscParams::from_import( + *input.particle, *input.material, *input.imported), input.imported->em_params.energy_loss_fluct); } From c91d7a780dfecd3de473aa589dc9872f4ad30288 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Fri, 3 Feb 2023 16:50:36 -0500 Subject: [PATCH 9/9] Move UrbanMscParams to top-level em directory --- app/demo-geant-integration/NoFieldAlongStepFactory.cc | 2 +- app/demo-loop/LDemoIO.cc | 2 +- example/accel/accel.cc | 2 +- src/celeritas/CMakeLists.txt | 2 +- src/celeritas/em/{msc => }/UrbanMscParams.cc | 2 +- src/celeritas/em/{msc => }/UrbanMscParams.hh | 2 +- src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc | 2 +- src/celeritas/global/alongstep/AlongStepUniformMscAction.cc | 2 +- test/celeritas/GeantTestBase.cc | 2 +- test/celeritas/em/UrbanMsc.test.cc | 2 +- test/celeritas/global/Stepper.test.cc | 2 +- test/celeritas/user/StepCollector.test.cc | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) rename src/celeritas/em/{msc => }/UrbanMscParams.cc (99%) rename src/celeritas/em/{msc => }/UrbanMscParams.hh (98%) diff --git a/app/demo-geant-integration/NoFieldAlongStepFactory.cc b/app/demo-geant-integration/NoFieldAlongStepFactory.cc index 153965c5cb..c750fcc354 100644 --- a/app/demo-geant-integration/NoFieldAlongStepFactory.cc +++ b/app/demo-geant-integration/NoFieldAlongStepFactory.cc @@ -10,7 +10,7 @@ #include #include -#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/UrbanMscParams.hh" #include "celeritas/global/alongstep/AlongStepGeneralLinearAction.hh" #include "celeritas/io/ImportData.hh" #include "celeritas/phys/ImportedProcessAdapter.hh" diff --git a/app/demo-loop/LDemoIO.cc b/app/demo-loop/LDemoIO.cc index 0eae7f2854..440c1e8f28 100644 --- a/app/demo-loop/LDemoIO.cc +++ b/app/demo-loop/LDemoIO.cc @@ -16,7 +16,7 @@ #include "corecel/io/StringUtils.hh" #include "corecel/sys/Device.hh" #include "celeritas/Units.hh" -#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/UrbanMscParams.hh" #include "celeritas/ext/GeantImporter.hh" #include "celeritas/ext/GeantPhysicsOptionsIO.json.hh" #include "celeritas/ext/GeantSetup.hh" diff --git a/example/accel/accel.cc b/example/accel/accel.cc index 748cdfe559..524d2fde58 100644 --- a/example/accel/accel.cc +++ b/example/accel/accel.cc @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/celeritas/CMakeLists.txt b/src/celeritas/CMakeLists.txt index 29bf06e304..c825d24522 100644 --- a/src/celeritas/CMakeLists.txt +++ b/src/celeritas/CMakeLists.txt @@ -29,6 +29,7 @@ list(APPEND SOURCES Types.cc em/AtomicRelaxationParams.cc em/FluctuationParams.cc + em/UrbanMscParams.cc em/detail/Utils.cc em/model/BetheHeitlerModel.cc em/model/CombinedBremModel.cc @@ -40,7 +41,6 @@ list(APPEND SOURCES em/model/RayleighModel.cc em/model/RelativisticBremModel.cc em/model/SeltzerBergerModel.cc - em/msc/UrbanMscParams.cc em/process/BremsstrahlungProcess.cc em/process/ComptonProcess.cc em/process/EIonizationProcess.cc diff --git a/src/celeritas/em/msc/UrbanMscParams.cc b/src/celeritas/em/UrbanMscParams.cc similarity index 99% rename from src/celeritas/em/msc/UrbanMscParams.cc rename to src/celeritas/em/UrbanMscParams.cc index 3038cc0bb2..8474d19f18 100644 --- a/src/celeritas/em/msc/UrbanMscParams.cc +++ b/src/celeritas/em/UrbanMscParams.cc @@ -3,7 +3,7 @@ // See the top-level COPYRIGHT file for details. // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/em/msc/UrbanMscParams.cc +//! \file celeritas/em/UrbanMscParams.cc //---------------------------------------------------------------------------// #include "UrbanMscParams.hh" diff --git a/src/celeritas/em/msc/UrbanMscParams.hh b/src/celeritas/em/UrbanMscParams.hh similarity index 98% rename from src/celeritas/em/msc/UrbanMscParams.hh rename to src/celeritas/em/UrbanMscParams.hh index 024c45cf1f..dd81fe7ad4 100644 --- a/src/celeritas/em/msc/UrbanMscParams.hh +++ b/src/celeritas/em/UrbanMscParams.hh @@ -3,7 +3,7 @@ // See the top-level COPYRIGHT file for details. // SPDX-License-Identifier: (Apache-2.0 OR MIT) //---------------------------------------------------------------------------// -//! \file celeritas/em/msc/UrbanMscParams.hh +//! \file celeritas/em/UrbanMscParams.hh //---------------------------------------------------------------------------// #pragma once diff --git a/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc b/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc index a9015eaead..a0cee732fb 100644 --- a/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc +++ b/src/celeritas/global/alongstep/AlongStepGeneralLinearAction.cc @@ -16,7 +16,7 @@ #include "corecel/sys/MultiExceptionHandler.hh" #include "celeritas/Types.hh" #include "celeritas/em/FluctuationParams.hh" -#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/UrbanMscParams.hh" #include "celeritas/global/CoreTrackData.hh" #include "celeritas/global/KernelContextException.hh" #include "celeritas/phys/PhysicsParams.hh" diff --git a/src/celeritas/global/alongstep/AlongStepUniformMscAction.cc b/src/celeritas/global/alongstep/AlongStepUniformMscAction.cc index 4ad86e86ad..4fcda7eef6 100644 --- a/src/celeritas/global/alongstep/AlongStepUniformMscAction.cc +++ b/src/celeritas/global/alongstep/AlongStepUniformMscAction.cc @@ -14,7 +14,7 @@ #include "corecel/data/Ref.hh" #include "corecel/sys/Device.hh" #include "corecel/sys/MultiExceptionHandler.hh" -#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/UrbanMscParams.hh" #include "celeritas/global/CoreTrackData.hh" #include "celeritas/global/KernelContextException.hh" #include "celeritas/global/alongstep/AlongStepLauncher.hh" diff --git a/test/celeritas/GeantTestBase.cc b/test/celeritas/GeantTestBase.cc index 2ea72d5072..6f7ae9becc 100644 --- a/test/celeritas/GeantTestBase.cc +++ b/test/celeritas/GeantTestBase.cc @@ -11,7 +11,7 @@ #include "celeritas_cmake_strings.h" #include "corecel/io/Logger.hh" -#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/UrbanMscParams.hh" #include "celeritas/ext/GeantImporter.hh" #include "celeritas/ext/GeantPhysicsOptions.hh" #include "celeritas/ext/GeantSetup.hh" diff --git a/test/celeritas/em/UrbanMsc.test.cc b/test/celeritas/em/UrbanMsc.test.cc index 4e6733579d..f12297b741 100644 --- a/test/celeritas/em/UrbanMsc.test.cc +++ b/test/celeritas/em/UrbanMsc.test.cc @@ -12,7 +12,7 @@ #include "corecel/cont/Range.hh" #include "corecel/data/CollectionStateStore.hh" #include "celeritas/RootTestBase.hh" -#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/UrbanMscParams.hh" #include "celeritas/em/msc/UrbanMscScatter.hh" #include "celeritas/em/msc/UrbanMscStepLimit.hh" #include "celeritas/geo/GeoData.hh" diff --git a/test/celeritas/global/Stepper.test.cc b/test/celeritas/global/Stepper.test.cc index d1677fbe14..c9b12fd81e 100644 --- a/test/celeritas/global/Stepper.test.cc +++ b/test/celeritas/global/Stepper.test.cc @@ -12,7 +12,7 @@ #include "corecel/Types.hh" #include "corecel/cont/Range.hh" #include "corecel/cont/Span.hh" -#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/UrbanMscParams.hh" #include "celeritas/ext/GeantPhysicsOptions.hh" #include "celeritas/field/UniformFieldData.hh" #include "celeritas/global/ActionInterface.hh" diff --git a/test/celeritas/user/StepCollector.test.cc b/test/celeritas/user/StepCollector.test.cc index c2bcc3d9ea..770d2f3929 100644 --- a/test/celeritas/user/StepCollector.test.cc +++ b/test/celeritas/user/StepCollector.test.cc @@ -8,7 +8,7 @@ #include "celeritas/user/StepCollector.hh" #include "corecel/cont/Span.hh" -#include "celeritas/em/msc/UrbanMscParams.hh" +#include "celeritas/em/UrbanMscParams.hh" #include "celeritas/global/ActionRegistry.hh" #include "celeritas/global/Stepper.hh" #include "celeritas/global/alongstep/AlongStepUniformMscAction.hh"