Skip to content

Commit

Permalink
Add action to generate optical primaries from scintillation distribut…
Browse files Browse the repository at this point in the history
…ions (#1414)
  • Loading branch information
amandalund authored Sep 19, 2024
1 parent a7dc59d commit c4806e3
Show file tree
Hide file tree
Showing 10 changed files with 461 additions and 38 deletions.
1 change: 1 addition & 0 deletions src/celeritas/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ celeritas_polysource(optical/detail/CerenkovGeneratorAction)
celeritas_polysource(optical/detail/CerenkovOffloadAction)
celeritas_polysource(optical/detail/OpticalGenAlgorithms)
celeritas_polysource(optical/detail/OffloadGatherAction)
celeritas_polysource(optical/detail/ScintGeneratorAction)
celeritas_polysource(optical/detail/ScintOffloadAction)
celeritas_polysource(phys/detail/DiscreteSelectAction)
celeritas_polysource(phys/detail/PreStepAction)
Expand Down
22 changes: 19 additions & 3 deletions src/celeritas/optical/OpticalCollector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "detail/OffloadGatherAction.hh"
#include "detail/OffloadParams.hh"
#include "detail/OpticalLaunchAction.hh"
#include "detail/ScintGeneratorAction.hh"
#include "detail/ScintOffloadAction.hh"

namespace celeritas
Expand Down Expand Up @@ -70,9 +71,7 @@ OpticalCollector::OpticalCollector(CoreParams const& core, Input&& inp)
{
// Action to generate scintillation optical distributions
scint_action_ = std::make_shared<detail::ScintOffloadAction>(
actions.next_id(),
offload_params_->aux_id(),
std::move(inp.scintillation));
actions.next_id(), offload_params_->aux_id(), inp.scintillation);
actions.insert(scint_action_);
}

Expand All @@ -92,6 +91,20 @@ OpticalCollector::OpticalCollector(CoreParams const& core, Input&& inp)
actions.insert(cerenkov_gen_action_);
}

if (setup.scintillation)
{
// Action to generate scintillation primaries
scint_gen_action_ = std::make_shared<detail::ScintGeneratorAction>(
actions.next_id(),
offload_params_->aux_id(),
// TODO: Hack: generator action must be before launch action
// but needs optical state aux ID
core.aux_reg()->next_id(),
std::move(inp.scintillation),
inp.auto_flush);
actions.insert(scint_gen_action_);
}

// Create launch action with optical params+state and access to gen data
launch_action_ = detail::OpticalLaunchAction::make_and_insert(
core, inp.material, offload_params_, inp.primary_capacity);
Expand All @@ -105,6 +118,9 @@ OpticalCollector::OpticalCollector(CoreParams const& core, Input&& inp)
CELER_ENSURE(!cerenkov_gen_action_
|| launch_action_->action_id()
> cerenkov_gen_action_->action_id());
CELER_ENSURE(!scint_gen_action_
|| launch_action_->action_id()
> scint_gen_action_->action_id());
}

//---------------------------------------------------------------------------//
Expand Down
3 changes: 3 additions & 0 deletions src/celeritas/optical/OpticalCollector.hh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class OffloadGatherAction;
class OpticalLaunchAction;
class OffloadParams;
class ScintOffloadAction;
class ScintGeneratorAction;
} // namespace detail

//---------------------------------------------------------------------------//
Expand Down Expand Up @@ -111,6 +112,7 @@ class OpticalCollector
using SPGatherAction = std::shared_ptr<detail::OffloadGatherAction>;
using SPCerenkovGenAction
= std::shared_ptr<detail::CerenkovGeneratorAction>;
using SPScintGenAction = std::shared_ptr<detail::ScintGeneratorAction>;
using SPLaunchAction = std::shared_ptr<detail::OpticalLaunchAction>;

//// DATA ////
Expand All @@ -121,6 +123,7 @@ class OpticalCollector
SPCerenkovAction cerenkov_action_;
SPScintAction scint_action_;
SPCerenkovGenAction cerenkov_gen_action_;
SPScintGenAction scint_gen_action_;
SPLaunchAction launch_action_;

// TODO: tracking loop launch action
Expand Down
8 changes: 4 additions & 4 deletions src/celeritas/optical/ScintillationGenerator.hh
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class ScintillationGenerator
public:
// Construct from scintillation data and distribution parameters
inline CELER_FUNCTION
ScintillationGenerator(GeneratorDistributionData const& dist,
NativeCRef<ScintillationData> const& shared);
ScintillationGenerator(NativeCRef<ScintillationData> const& shared,
GeneratorDistributionData const& dist);

// Sample a single photon from the distribution
template<class Generator>
Expand Down Expand Up @@ -94,8 +94,8 @@ class ScintillationGenerator
*/
CELER_FUNCTION
ScintillationGenerator::ScintillationGenerator(
GeneratorDistributionData const& dist,
NativeCRef<ScintillationData> const& shared)
NativeCRef<ScintillationData> const& shared,
GeneratorDistributionData const& dist)
: dist_(dist)
, shared_(shared)
, sample_cost_(-1, 1)
Expand Down
161 changes: 161 additions & 0 deletions src/celeritas/optical/detail/ScintGeneratorAction.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
//----------------------------------*-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/detail/ScintGeneratorAction.cc
//---------------------------------------------------------------------------//
#include "ScintGeneratorAction.hh"

#include <algorithm>

#include "corecel/Assert.hh"
#include "corecel/data/AuxStateVec.hh"
#include "celeritas/global/ActionLauncher.hh"
#include "celeritas/global/CoreParams.hh"
#include "celeritas/global/CoreState.hh"
#include "celeritas/global/TrackExecutor.hh"
#include "celeritas/optical/CoreParams.hh"
#include "celeritas/optical/CoreState.hh"
#include "celeritas/optical/ScintillationParams.hh"
#include "celeritas/optical/TrackData.hh"

#include "OffloadParams.hh"
#include "OpticalGenAlgorithms.hh"
#include "ScintGeneratorExecutor.hh"

namespace celeritas
{
namespace detail
{
//---------------------------------------------------------------------------//
/*!
* Construct with action ID, data IDs, and optical properties.
*/
ScintGeneratorAction::ScintGeneratorAction(ActionId id,
AuxId offload_id,
AuxId optical_id,
SPConstScintillation scintillation,
size_type auto_flush)
: id_(id)
, offload_id_{offload_id}
, optical_id_{optical_id}
, scintillation_(std::move(scintillation))
, auto_flush_(auto_flush)
{
CELER_EXPECT(id_);
CELER_EXPECT(offload_id_);
CELER_EXPECT(optical_id_);
CELER_EXPECT(scintillation_);
CELER_EXPECT(auto_flush_ > 0);
}

//---------------------------------------------------------------------------//
/*!
* Descriptive name of the action.
*/
std::string_view ScintGeneratorAction::description() const
{
return "generate scintillation photons from optical distribution data";
}

//---------------------------------------------------------------------------//
/*!
* Execute the action with host data.
*/
void ScintGeneratorAction::step(CoreParams const& params,
CoreStateHost& state) const
{
this->step_impl(params, state);
}

//---------------------------------------------------------------------------//
/*!
* Execute the action with device data.
*/
void ScintGeneratorAction::step(CoreParams const& params,
CoreStateDevice& state) const
{
this->step_impl(params, state);
}

//---------------------------------------------------------------------------//
/*!
* Generate optical track initializers from scintillation distribution data.
*/
template<MemSpace M>
void ScintGeneratorAction::step_impl(CoreParams const& core_params,
CoreState<M>& core_state) const
{
auto& offload_state
= get<OpticalOffloadState<M>>(core_state.aux(), offload_id_);
auto& optical_state
= get<optical::CoreState<M>>(core_state.aux(), optical_id_);

auto& num_photons = optical_state.counters().num_initializers;
auto& num_new_photons = offload_state.buffer_size.num_photons;

if (num_photons + num_new_photons < auto_flush_)
return;

auto initializers_size = optical_state.ref().init.initializers.size();
CELER_VALIDATE(num_photons + num_new_photons <= initializers_size,
<< "insufficient capacity (" << initializers_size
<< ") for optical photon initializers (total capacity "
"requirement of "
<< num_photons + num_new_photons << ")");

auto& offload = offload_state.store.ref();
auto& buffer_size = offload_state.buffer_size.scintillation;
CELER_ASSERT(buffer_size > 0);

// 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.scintillation,
offload.offsets,
buffer_size,
core_state.stream_id());

// Generate the optical photon initializers from the distribution data
this->generate(core_params, core_state);

num_photons += count;
num_new_photons -= count;
buffer_size = 0;
}

//---------------------------------------------------------------------------//
/*!
* Launch a (host) kernel to generate optical photon initializers.
*/
void ScintGeneratorAction::generate(CoreParams const& core_params,
CoreStateHost& core_state) const
{
auto& offload_state = get<OpticalOffloadState<MemSpace::native>>(
core_state.aux(), offload_id_);
auto& optical_state = get<optical::CoreState<MemSpace::native>>(
core_state.aux(), optical_id_);

TrackExecutor execute{
core_params.ptr<MemSpace::native>(),
core_state.ptr(),
detail::ScintGeneratorExecutor{core_state.ptr(),
scintillation_->host_ref(),
offload_state.store.ref(),
optical_state.ptr(),
offload_state.buffer_size}};
launch_action(*this, core_params, core_state, execute);
}

//---------------------------------------------------------------------------//
#if !CELER_USE_DEVICE
void ScintGeneratorAction::generate(CoreParams const&, CoreStateDevice&) const
{
CELER_NOT_CONFIGURED("CUDA OR HIP");
}
#endif

//---------------------------------------------------------------------------//
} // namespace detail
} // namespace celeritas
52 changes: 52 additions & 0 deletions src/celeritas/optical/detail/ScintGeneratorAction.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//---------------------------------*-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/detail/ScintGeneratorAction.cu
//---------------------------------------------------------------------------//
#include "ScintGeneratorAction.hh"

#include "corecel/Assert.hh"
#include "corecel/sys/ScopedProfiling.hh"
#include "celeritas/global/ActionLauncher.device.hh"
#include "celeritas/global/TrackExecutor.hh"
#include "celeritas/optical/CoreParams.hh"
#include "celeritas/optical/CoreState.hh"
#include "celeritas/optical/ScintillationParams.hh"

#include "OffloadParams.hh"
#include "OpticalGenAlgorithms.hh"
#include "ScintGeneratorExecutor.hh"

namespace celeritas
{
namespace detail
{
//---------------------------------------------------------------------------//
/*!
* Launch a kernel to generate optical photon initializers.
*/
void ScintGeneratorAction::generate(CoreParams const& core_params,
CoreStateDevice& core_state) const
{
auto& offload_state = get<OpticalOffloadState<MemSpace::native>>(
core_state.aux(), offload_id_);
auto& optical_state = get<optical::CoreState<MemSpace::native>>(
core_state.aux(), optical_id_);

TrackExecutor execute{
core_params.ptr<MemSpace::native>(),
core_state.ptr(),
detail::ScintGeneratorExecutor{core_state.ptr(),
scintillation_->device_ref(),
offload_state.store.ref(),
optical_state.ptr(),
offload_state.buffer_size}};
static ActionLauncher<decltype(execute)> const launch_kernel(*this);
launch_kernel(core_state, execute);
}

//---------------------------------------------------------------------------//
} // namespace detail
} // namespace celeritas
Loading

0 comments on commit c4806e3

Please sign in to comment.