diff --git a/src/celeritas/CMakeLists.txt b/src/celeritas/CMakeLists.txt index 6b8a7f9f56..bc68e3e0cf 100644 --- a/src/celeritas/CMakeLists.txt +++ b/src/celeritas/CMakeLists.txt @@ -292,10 +292,12 @@ celeritas_polysource(neutron/model/ChipsNeutronElasticModel) celeritas_polysource(neutron/model/NeutronInelasticModel) celeritas_polysource(optical/model/AbsorptionModel) celeritas_polysource(optical/model/RayleighModel) +celeritas_polysource(optical/action/AlongStepAction) celeritas_polysource(optical/action/BoundaryAction) -celeritas_polysource(optical/action/detail/TrackInitAlgorithms) celeritas_polysource(optical/action/InitializeTracksAction) celeritas_polysource(optical/action/PreStepAction) +celeritas_polysource(optical/action/TrackingCutAction) +celeritas_polysource(optical/action/detail/TrackInitAlgorithms) celeritas_polysource(optical/detail/CherenkovGeneratorAction) celeritas_polysource(optical/detail/CherenkovOffloadAction) celeritas_polysource(optical/detail/OpticalGenAlgorithms) diff --git a/src/celeritas/optical/CoreParams.cc b/src/celeritas/optical/CoreParams.cc index 292f2a8187..db0d7a00d2 100644 --- a/src/celeritas/optical/CoreParams.cc +++ b/src/celeritas/optical/CoreParams.cc @@ -19,10 +19,12 @@ #include "CoreState.hh" #include "MaterialParams.hh" #include "TrackInitParams.hh" +#include "action/AlongStepAction.hh" #include "action/BoundaryAction.hh" #include "action/InitializeTracksAction.hh" #include "action/LocateVacanciesAction.hh" #include "action/PreStepAction.hh" +#include "action/TrackingCutAction.hh" namespace celeritas { @@ -71,15 +73,23 @@ CoreScalars build_actions(ActionRegistry* reg) reg->insert(make_shared(reg->next_id())); + //// ALONG-STEP ACTIONS //// + + reg->insert(make_shared(reg->next_id())); + //// POST-STEP ACTIONS //// - // Construct geometry boundary action - // TODO: it might make more sense to build these actions right before - // making the action group: re-examine once we add a surface physics - // manager + // TODO: process selection action (or constructed by physics?) + + // TODO: it might make more sense to build the surface crossing action + // right before making the action group: re-examine once we add a surface + // physics manager scalars.boundary_action = reg->next_id(); reg->insert(make_shared(scalars.boundary_action)); + scalars.tracking_cut_action = reg->next_id(); + reg->insert(make_shared(scalars.tracking_cut_action)); + //// END ACTIONS //// reg->insert(make_shared(reg->next_id())); diff --git a/src/celeritas/optical/CoreTrackData.hh b/src/celeritas/optical/CoreTrackData.hh index 0a70d8b9e2..913d894b53 100644 --- a/src/celeritas/optical/CoreTrackData.hh +++ b/src/celeritas/optical/CoreTrackData.hh @@ -63,6 +63,7 @@ struct CoreScalars // TODO: maybe replace with a surface crossing manager to handle boundary // conditions (see CoreParams.cc) ActionId boundary_action; + ActionId tracking_cut_action; StreamId::size_type max_streams{0}; diff --git a/src/celeritas/optical/OffloadData.hh b/src/celeritas/optical/OffloadData.hh index e97b4a1fbf..9b21f5ebdb 100644 --- a/src/celeritas/optical/OffloadData.hh +++ b/src/celeritas/optical/OffloadData.hh @@ -24,7 +24,7 @@ namespace celeritas /*! * Current sizes of the buffers of distribution data. * - * These sizes are updated by value on the host at each step. + * These sizes are updated by value on the host at each core step. */ struct OffloadBufferSize { diff --git a/src/celeritas/optical/ParticleTrackView.hh b/src/celeritas/optical/ParticleTrackView.hh index 6925f424dd..4b480df36f 100644 --- a/src/celeritas/optical/ParticleTrackView.hh +++ b/src/celeritas/optical/ParticleTrackView.hh @@ -19,7 +19,7 @@ namespace optical { //---------------------------------------------------------------------------// /*! - * Properties of a single particle track. + * Properties of a single optical photon. */ class ParticleTrackView { @@ -49,10 +49,10 @@ class ParticleTrackView // Access the polarization CELER_FORCEINLINE_FUNCTION Real3 const& polarization() const; - // Change the particle's energy [MeV] + // Change the photon's energy [MeV] inline CELER_FUNCTION void energy(Energy); - // Change the particle's polarization + // Change the photon's polarization inline CELER_FUNCTION void polarization(Real3 const&); private: diff --git a/src/celeritas/optical/action/AlongStepAction.cc b/src/celeritas/optical/action/AlongStepAction.cc new file mode 100644 index 0000000000..617f53bb0f --- /dev/null +++ b/src/celeritas/optical/action/AlongStepAction.cc @@ -0,0 +1,56 @@ +//----------------------------------*-C++-*----------------------------------// +// Copyright 2024 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/optical/action/AlongStepAction.cc +//---------------------------------------------------------------------------// +#include "AlongStepAction.hh" + +#include "celeritas/optical/CoreParams.hh" +#include "celeritas/optical/CoreState.hh" + +#include "ActionLauncher.hh" +#include "TrackSlotExecutor.hh" + +#include "detail/AlongStepExecutor.hh" +#include "detail/PropagateExecutor.hh" + +namespace celeritas +{ +namespace optical +{ +//---------------------------------------------------------------------------// +/*! + * Construct with action ID. + */ +AlongStepAction::AlongStepAction(ActionId aid) + : StaticConcreteAction(aid, "along-step", "move to interaction or boundary") +{ +} + +//---------------------------------------------------------------------------// +/*! + * Launch the boundary action on host. + */ +void AlongStepAction::step(CoreParams const& params, CoreStateHost& state) const +{ + auto propagate_and_update = [](CoreTrackView& track) { + detail::PropagateExecutor{}(track); + detail::AlongStepExecutor{}(track); + }; + auto execute = make_active_thread_executor( + params.ptr(), state.ptr(), propagate_and_update); + return launch_action(state, execute); +} + +#if !CELER_USE_DEVICE +void AlongStepAction::step(CoreParams const&, CoreStateDevice&) const +{ + CELER_NOT_CONFIGURED("CUDA OR HIP"); +} +#endif + +//---------------------------------------------------------------------------// +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/action/AlongStepAction.cu b/src/celeritas/optical/action/AlongStepAction.cu new file mode 100644 index 0000000000..eef49c0ddc --- /dev/null +++ b/src/celeritas/optical/action/AlongStepAction.cu @@ -0,0 +1,56 @@ +//---------------------------------*-CUDA-*----------------------------------// +// Copyright 2024 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/optical/action/AlongStepAction.cu +//---------------------------------------------------------------------------// +#include "AlongStepAction.hh" + +#include "corecel/io/Logger.hh" +#include "celeritas/optical/CoreParams.hh" +#include "celeritas/optical/CoreState.hh" + +#include "ActionLauncher.device.hh" +#include "TrackSlotExecutor.hh" + +#include "detail/AlongStepExecutor.hh" +#include "detail/PropagateExecutor.hh" + +namespace celeritas +{ +namespace optical +{ +//---------------------------------------------------------------------------// +/*! + * Launch the along-step action on device. + */ +void AlongStepAction::step(CoreParams const& params, + CoreStateDevice& state) const +{ + { + // Propagate + auto execute + = make_active_thread_executor(params.ptr(), + state.ptr(), + detail::PropagateExecutor{}); + + static ActionLauncher const launch_kernel( + *this, "propagate"); + launch_kernel(state, execute); + } + { + // Update state + auto execute + = make_active_thread_executor(params.ptr(), + state.ptr(), + detail::AlongStepExecutor{}); + + static ActionLauncher const launch_kernel(*this); + launch_kernel(state, execute); + } +} + +//---------------------------------------------------------------------------// +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/action/AlongStepAction.hh b/src/celeritas/optical/action/AlongStepAction.hh new file mode 100644 index 0000000000..a75962f89c --- /dev/null +++ b/src/celeritas/optical/action/AlongStepAction.hh @@ -0,0 +1,39 @@ +//----------------------------------*-C++-*----------------------------------// +// Copyright 2024 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/optical/action/AlongStepAction.hh +//---------------------------------------------------------------------------// +#pragma once + +#include "ActionInterface.hh" + +namespace celeritas +{ +namespace optical +{ +//---------------------------------------------------------------------------// +/*! + * Move a track to the next boundary or interaction. + */ +class AlongStepAction final : public OpticalStepActionInterface, + public StaticConcreteAction +{ + public: + // Construct with ID + explicit AlongStepAction(ActionId); + + // Launch kernel with host data + void step(CoreParams const&, CoreStateHost&) const final; + + // Launch kernel with device data + void step(CoreParams const&, CoreStateDevice&) const final; + + //! Dependency ordering of the action + StepActionOrder order() const final { return StepActionOrder::along; } +}; + +//---------------------------------------------------------------------------// +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/action/TrackingCutAction.cc b/src/celeritas/optical/action/TrackingCutAction.cc new file mode 100644 index 0000000000..b5521a1d4c --- /dev/null +++ b/src/celeritas/optical/action/TrackingCutAction.cc @@ -0,0 +1,56 @@ +//----------------------------------*-C++-*----------------------------------// +// Copyright 2024 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/optical/action/TrackingCutAction.cc +//---------------------------------------------------------------------------// +#include "TrackingCutAction.hh" + +#include "corecel/io/Logger.hh" +#include "celeritas/optical/CoreParams.hh" +#include "celeritas/optical/CoreState.hh" + +#include "ActionLauncher.hh" +#include "TrackSlotExecutor.hh" + +#include "detail/TrackingCutExecutor.hh" + +namespace celeritas +{ +namespace optical +{ +//---------------------------------------------------------------------------// +/*! + * Construct with action ID. + */ +TrackingCutAction::TrackingCutAction(ActionId aid) + : StaticConcreteAction( + aid, "tracking-cut", "kill a track and deposit its energy") +{ +} + +//---------------------------------------------------------------------------// +/*! + * Launch the boundary action on host. + */ +void TrackingCutAction::step(CoreParams const& params, + CoreStateHost& state) const +{ + auto execute = make_action_thread_executor(params.ptr(), + state.ptr(), + this->action_id(), + detail::TrackingCutExecutor{}); + return launch_action(state, execute); +} + +#if !CELER_USE_DEVICE +void TrackingCutAction::step(CoreParams const&, CoreStateDevice&) const +{ + CELER_NOT_CONFIGURED("CUDA OR HIP"); +} +#endif + +//---------------------------------------------------------------------------// +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/action/TrackingCutAction.cu b/src/celeritas/optical/action/TrackingCutAction.cu new file mode 100644 index 0000000000..e81b4a395f --- /dev/null +++ b/src/celeritas/optical/action/TrackingCutAction.cu @@ -0,0 +1,41 @@ +//---------------------------------*-CUDA-*----------------------------------// +// Copyright 2024 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/optical/action/TrackingCutAction.cu +//---------------------------------------------------------------------------// +#include "TrackingCutAction.hh" + +#include "corecel/io/Logger.hh" +#include "celeritas/optical/CoreParams.hh" +#include "celeritas/optical/CoreState.hh" + +#include "ActionLauncher.device.hh" +#include "TrackSlotExecutor.hh" + +#include "detail/TrackingCutExecutor.hh" + +namespace celeritas +{ +namespace optical +{ +//---------------------------------------------------------------------------// +/*! + * Launch the tracking cut action on device. + */ +void TrackingCutAction::step(CoreParams const& params, + CoreStateDevice& state) const +{ + auto execute = make_action_thread_executor(params.ptr(), + state.ptr(), + this->action_id(), + detail::TrackingCutExecutor{}); + + static ActionLauncher const launch_kernel(*this); + launch_kernel(state, execute); +} + +//---------------------------------------------------------------------------// +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/action/TrackingCutAction.hh b/src/celeritas/optical/action/TrackingCutAction.hh new file mode 100644 index 0000000000..57f46ee6a8 --- /dev/null +++ b/src/celeritas/optical/action/TrackingCutAction.hh @@ -0,0 +1,39 @@ +//----------------------------------*-C++-*----------------------------------// +// Copyright 2024 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/optical/action/TrackingCutAction.hh +//---------------------------------------------------------------------------// +#pragma once + +#include "ActionInterface.hh" + +namespace celeritas +{ +namespace optical +{ +//---------------------------------------------------------------------------// +/*! + * Kill misbehaving photons and deposit energy locally. + */ +class TrackingCutAction final : public OpticalStepActionInterface, + public StaticConcreteAction +{ + public: + // Construct with ID + explicit TrackingCutAction(ActionId); + + // Launch kernel with host data + void step(CoreParams const&, CoreStateHost&) const final; + + // Launch kernel with device data + void step(CoreParams const&, CoreStateDevice&) const final; + + //! Dependency ordering of the action + StepActionOrder order() const final { return StepActionOrder::post; } +}; + +//---------------------------------------------------------------------------// +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/action/detail/AlongStepExecutor.hh b/src/celeritas/optical/action/detail/AlongStepExecutor.hh new file mode 100644 index 0000000000..62d26379e0 --- /dev/null +++ b/src/celeritas/optical/action/detail/AlongStepExecutor.hh @@ -0,0 +1,54 @@ +//----------------------------------*-C++-*----------------------------------// +// Copyright 2024 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/optical/action/detail/AlongStepExecutor.hh +//---------------------------------------------------------------------------// +#pragma once + +#include "corecel/Assert.hh" +#include "corecel/Macros.hh" +#include "celeritas/Types.hh" +#include "celeritas/optical/CoreTrackView.hh" +#include "celeritas/optical/SimTrackView.hh" + +namespace celeritas +{ +namespace optical +{ +namespace detail +{ +//---------------------------------------------------------------------------// +/*! + * Complete end-of-step activity for a track. + * + * - Update track time + * - Update number of steps + * - Update remaining MFPs to interaction + */ +struct AlongStepExecutor +{ + inline CELER_FUNCTION void operator()(CoreTrackView& track); +}; + +//---------------------------------------------------------------------------// +CELER_FUNCTION void AlongStepExecutor::operator()(CoreTrackView& track) +{ + auto sim = track.sim(); + + // Update time + sim.add_time(sim.step_length() / constants::c_light); + + CELER_ASSERT(sim.status() == TrackStatus::alive); + CELER_ASSERT(sim.step_length() > 0); + CELER_ASSERT(sim.post_step_action()); + + // TODO: update step count and check max step cut + // TODO: reduce MFP by step * xs +} + +//---------------------------------------------------------------------------// +} // namespace detail +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/action/detail/PreStepExecutor.hh b/src/celeritas/optical/action/detail/PreStepExecutor.hh index d4f8a4cc86..99aa229915 100644 --- a/src/celeritas/optical/action/detail/PreStepExecutor.hh +++ b/src/celeritas/optical/action/detail/PreStepExecutor.hh @@ -47,8 +47,16 @@ CELER_FUNCTION void PreStepExecutor::operator()(CoreTrackView const& track) CELER_ASSERT(sim.status() == TrackStatus::initializing || sim.status() == TrackStatus::alive); - //! \todo Set to alive when loop is implemented; for now just kill tracks - sim.status(TrackStatus::inactive); + + if (sim.status() == TrackStatus::initializing) + { + sim.reset_step_limit(); + sim.status(TrackStatus::alive); + } + + // TODO: reset secondaries + // TODO: calculate step limit + CELER_ENSURE(sim.step_length() > 0); } //---------------------------------------------------------------------------// diff --git a/src/celeritas/optical/action/detail/PropagateExecutor.hh b/src/celeritas/optical/action/detail/PropagateExecutor.hh new file mode 100644 index 0000000000..d0b9591dcd --- /dev/null +++ b/src/celeritas/optical/action/detail/PropagateExecutor.hh @@ -0,0 +1,61 @@ +//----------------------------------*-C++-*----------------------------------// +// Copyright 2024 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/optical/action/detail/PropagateExecutor.hh +//---------------------------------------------------------------------------// +#pragma once + +#include "corecel/Assert.hh" +#include "corecel/Macros.hh" +#include "celeritas/Types.hh" +#include "celeritas/optical/CoreTrackView.hh" +#include "celeritas/optical/SimTrackView.hh" + +namespace celeritas +{ +namespace optical +{ +namespace detail +{ +//---------------------------------------------------------------------------// +/*! + * Move a track to the next interaction or geometry boundary. + * + * This should only apply to alive tracks. + */ +struct PropagateExecutor +{ + inline CELER_FUNCTION void operator()(CoreTrackView& track); +}; + +//---------------------------------------------------------------------------// +CELER_FUNCTION void PropagateExecutor::operator()(CoreTrackView& track) +{ + auto&& sim = track.sim(); + CELER_ASSERT(sim.status() == TrackStatus::alive); + + // Propagate up to the physics distance + real_type step = sim.step_length(); + CELER_ASSERT(step > 0); + + auto&& geo = track.geometry(); + Propagation p = geo.find_next_step(step); + if (p.boundary) + { + geo.move_to_boundary(); + sim.step_length(p.distance); + sim.post_step_action(track.boundary_action()); + } + else + { + CELER_ASSERT(step == p.distance); + geo.move_internal(step); + } +} + +//---------------------------------------------------------------------------// +} // namespace detail +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/action/detail/TrackingCutExecutor.hh b/src/celeritas/optical/action/detail/TrackingCutExecutor.hh new file mode 100644 index 0000000000..8f413b7afc --- /dev/null +++ b/src/celeritas/optical/action/detail/TrackingCutExecutor.hh @@ -0,0 +1,59 @@ +//----------------------------------*-C++-*----------------------------------// +// Copyright 2024 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/optical/action/detail/TrackingCutExecutor.hh +//---------------------------------------------------------------------------// +#pragma once + +#include "corecel/Assert.hh" +#include "corecel/Macros.hh" +#include "celeritas/Types.hh" +#include "celeritas/optical/CoreTrackView.hh" +#include "celeritas/optical/ParticleTrackView.hh" +#include "celeritas/optical/SimTrackView.hh" + +namespace celeritas +{ +namespace optical +{ +namespace detail +{ +//---------------------------------------------------------------------------// +/*! + * Kill a malfunctioning photon. + */ +struct TrackingCutExecutor +{ + inline CELER_FUNCTION void operator()(CoreTrackView& track); +}; + +//---------------------------------------------------------------------------// +CELER_FUNCTION void TrackingCutExecutor::operator()(CoreTrackView& track) +{ + using Energy = ParticleTrackView::Energy; + + auto deposited = track.particle().energy().value(); + + auto&& sim = track.sim(); +#if !CELER_DEVICE_COMPILE + { + // Print a debug message if track is just being cut; error message if + // an error occurred + auto msg = self_logger()(CELER_CODE_PROVENANCE, + sim.status() == TrackStatus::errored + ? LogLevel::error + : LogLevel::debug); + msg << "Killing optical photon: lost " << deposited << ' ' + << Energy::unit_type::label(); + } +#endif + + sim.status(TrackStatus::killed); +} + +//---------------------------------------------------------------------------// +} // namespace detail +} // namespace optical +} // namespace celeritas diff --git a/src/celeritas/optical/detail/CherenkovGeneratorAction.cc b/src/celeritas/optical/detail/CherenkovGeneratorAction.cc index 8a2358ae5c..d0c2f1474c 100644 --- a/src/celeritas/optical/detail/CherenkovGeneratorAction.cc +++ b/src/celeritas/optical/detail/CherenkovGeneratorAction.cc @@ -113,13 +113,19 @@ void CherenkovGeneratorAction::step_impl(CoreParams const& core_params, auto& offload = offload_state.store.ref(); auto& buffer_size = offload_state.buffer_size.cherenkov; - CELER_ASSERT(buffer_size > 0); + if (buffer_size == 0) + { + // No new cherenkov photons: perhaps tracks are all subluminal + CELER_LOG_LOCAL(debug) << "No Cherenkov photons to generate"; + return; + } // Calculate the cumulative sum of the number of photons in the buffered // distributions. These values are used to determine which thread will // generate initializers from which distribution auto count = inclusive_scan_photons( offload.cherenkov, offload.offsets, buffer_size, core_state.stream_id()); + optical_state.counters().num_generated += count; // Generate the optical photon initializers from the distribution data this->generate(core_params, core_state); diff --git a/src/celeritas/optical/detail/OpticalLaunchAction.cc b/src/celeritas/optical/detail/OpticalLaunchAction.cc index 5aa2ac6f5c..c1987e9cb9 100644 --- a/src/celeritas/optical/detail/OpticalLaunchAction.cc +++ b/src/celeritas/optical/detail/OpticalLaunchAction.cc @@ -151,31 +151,26 @@ void OpticalLaunchAction::execute_impl(CoreParams const&, CELER_ASSERT(offload_state); CELER_ASSERT(optical_state.size() > 0); - constexpr size_type max_steps{1}; - size_type remaining_steps = max_steps; + constexpr size_type max_step_iters{1}; + size_type num_step_iters{0}; + size_type num_steps{0}; // Loop while photons are yet to be tracked auto& counters = optical_state.counters(); auto const& step_actions = optical_actions_->step(); while (counters.num_initializers > 0 || counters.num_alive > 0) { - // TODO: generation is done *outside* of the optical tracking loop; - // once we move it inside, update the generation count in the - // generators - counters.num_generated = 0; - // Loop through actions for (auto const& action : step_actions) { action->step(*optical_params_, optical_state); } - CELER_LOG(debug) << "Stepped " << counters.num_active - << " optical tracks"; - if (CELER_UNLIKELY(--remaining_steps == 0)) + num_steps += counters.num_active; + if (CELER_UNLIKELY(++num_step_iters == max_step_iters)) { CELER_LOG_LOCAL(error) - << "Exceeded step count of " << max_steps + << "Exceeded step count of " << max_step_iters << ": aborting optical transport loop with " << counters.num_active << " active tracks, " << counters.num_alive << " alive tracks, " @@ -184,6 +179,15 @@ void OpticalLaunchAction::execute_impl(CoreParams const&, break; } } + + CELER_LOG_LOCAL(debug) << "Generated " << counters.num_generated + << " optical photons which completed " << num_steps + << " total steps over " << num_step_iters + << " iterations"; + + // TODO: generation is done *outside* of the optical tracking loop; + // once we move it inside, update the generation count in the loop here + counters.num_generated = 0; } //---------------------------------------------------------------------------// diff --git a/src/celeritas/optical/detail/ScintGeneratorAction.cc b/src/celeritas/optical/detail/ScintGeneratorAction.cc index 49c96d5369..c47a1f6118 100644 --- a/src/celeritas/optical/detail/ScintGeneratorAction.cc +++ b/src/celeritas/optical/detail/ScintGeneratorAction.cc @@ -118,6 +118,7 @@ void ScintGeneratorAction::step_impl(CoreParams const& core_params, offload.offsets, buffer_size, core_state.stream_id()); + optical_state.counters().num_generated += count; // Generate the optical photon initializers from the distribution data this->generate(core_params, core_state); diff --git a/src/celeritas/phys/PhysicsStepUtils.hh b/src/celeritas/phys/PhysicsStepUtils.hh index ce7d583a1b..9db8c9f30f 100644 --- a/src/celeritas/phys/PhysicsStepUtils.hh +++ b/src/celeritas/phys/PhysicsStepUtils.hh @@ -44,6 +44,9 @@ calc_physics_step_limit(MaterialTrackView const& material, /*! \todo For particles with decay, macro XS calculation will incorporate * decay probability, dividing decay constant by speed to become 1/len to * compete with interactions. + * + * \todo For neutral particles that haven't changed material since the last + * step, we can reuse the previously calculated cross section. */ // Loop over all processes that apply to this track (based on particle diff --git a/test/celeritas/optical/OpticalCollector.test.cc b/test/celeritas/optical/OpticalCollector.test.cc index 52b1ccf02d..03e0edc8c6 100644 --- a/test/celeritas/optical/OpticalCollector.test.cc +++ b/test/celeritas/optical/OpticalCollector.test.cc @@ -97,6 +97,7 @@ class LArSphereOffloadTest : public LArSphereBase size_type buffer_capacity_{256}; size_type initializer_capacity_{8192}; size_type auto_flush_{4096}; + units::MevEnergy primary_energy_{10.0}; std::shared_ptr collector_; StreamId stream_{0}; @@ -198,7 +199,7 @@ auto LArSphereOffloadTest::make_primaries(size_type count) -> VecPrimary { celeritas::Primary p; p.event_id = EventId{0}; - p.energy = units::MevEnergy{10.0}; + p.energy = primary_energy_; p.position = from_cm(Real3{0, 0, 0}); p.time = 0; @@ -365,7 +366,10 @@ TEST_F(LArSphereOffloadTest, host_distributions) EXPECT_EQ(21572, result.cherenkov.total_num_photons); EXPECT_EQ(52, result.cherenkov.num_photons.size()); - EXPECT_EQ(2104145, result.scintillation.total_num_photons); + EXPECT_SOFT_EQ( + 2104145.0f, + static_cast(result.scintillation.total_num_photons)); + EXPECT_EQ(130, result.scintillation.num_photons.size()); } } @@ -489,34 +493,70 @@ TEST_F(LArSphereOffloadTest, scintillation_distributions) } else { - EXPECT_EQ(1656334, result.scintillation.total_num_photons); + EXPECT_SOFT_EQ( + 1656334.0f, + static_cast(result.scintillation.total_num_photons)); EXPECT_EQ(52, result.scintillation.num_photons.size()); } } +TEST_F(LArSphereOffloadTest, host_generate_small) +{ + primary_energy_ = units::MevEnergy{0.01}; + num_track_slots_ = 32; + buffer_capacity_ = 4096; + initializer_capacity_ = 4096; + auto_flush_ = 1; + this->build_optical_collector(); + + // Run with 2 core track slots and 32 optical track slots + ScopedLogStorer scoped_log_{&celeritas::self_logger(), LogLevel::debug}; + auto result = this->run(4, 2, 2); + + static char const* const expected_log_messages[] = { + "Celeritas optical state initialization complete", + "Celeritas core state initialization complete", + "No Cherenkov photons to generate", + "Generated 964 Scintillation photons from 2 distributions", + R"(Exceeded step count of 1: aborting optical transport loop with 32 active tracks, 0 alive tracks, 32 vacancies, and 932 queued)", + R"(Generated 964 optical photons which completed 32 total steps over 1 iterations)", + "Deallocating host core state (stream 0)", + }; + if (CELERITAS_REAL_TYPE == CELERITAS_REAL_TYPE_DOUBLE) + { + EXPECT_VEC_EQ(expected_log_messages, scoped_log_.messages()); + } + static char const* const expected_log_levels[] + = {"status", "status", "debug", "debug", "error", "debug", "debug"}; + EXPECT_VEC_EQ(expected_log_levels, scoped_log_.levels()); +} + TEST_F(LArSphereOffloadTest, host_generate) { - num_track_slots_ = 1 << 18; + num_track_slots_ = 262144; buffer_capacity_ = 1024; initializer_capacity_ = 524288; auto_flush_ = 16384; this->build_optical_collector(); // Run with 512 core track slots and 2^18 optical track slots - ScopedLogStorer scoped_log_{&celeritas::self_logger()}; + ScopedLogStorer scoped_log_{&celeritas::self_logger(), LogLevel::debug}; auto result = this->run(4, 512, 16); static char const* const expected_log_messages[] = { "Celeritas optical state initialization complete", "Celeritas core state initialization complete", + "Generated 4258 Cherenkov photons from 4 distributions", + "Generated 319935 Scintillation photons from 4 distributions", R"(Exceeded step count of 1: aborting optical transport loop with 262144 active tracks, 0 alive tracks, 262144 vacancies, and 62049 queued)", - }; + R"(Generated 324193 optical photons which completed 262144 total steps over 1 iterations)", + "Deallocating host core state (stream 0)"}; if (CELERITAS_REAL_TYPE == CELERITAS_REAL_TYPE_DOUBLE) { EXPECT_VEC_EQ(expected_log_messages, scoped_log_.messages()); } static char const* const expected_log_levels[] - = {"status", "status", "error"}; + = {"status", "status", "debug", "debug", "error", "debug", "debug"}; EXPECT_VEC_EQ(expected_log_levels, scoped_log_.levels()); EXPECT_EQ(2, result.optical_launch_step); diff --git a/test/corecel/ScopedLogStorer.cc b/test/corecel/ScopedLogStorer.cc index e61e983776..4bc06da1ea 100644 --- a/test/corecel/ScopedLogStorer.cc +++ b/test/corecel/ScopedLogStorer.cc @@ -65,7 +65,7 @@ void ScopedLogStorer::operator()(LogProvenance, LogLevel lev, std::string msg) if (lev >= debug_level) { std::clog << color_code('x') << to_cstring(lev) << ": " << msg - << std::endl; + << color_code(' ') << std::endl; } if (lev < min_level_) {