Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 10:20:32

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file larceler/LarStandaloneRunner.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <memory>
0010 #include <vector>
0011 #include <lardataobj/Simulation/OpDetBacktrackerRecord.h>
0012 #include <lardataobj/Simulation/SimPhotons.h>
0013 #include <lardataobj/Simulation/sim.h>
0014 
0015 #include "corecel/Macros.hh"
0016 #include "corecel/cont/Span.hh"
0017 #include "geocel/Types.hh"
0018 #include "celeritas/optical/DetectorData.hh"
0019 
0020 #include "detail/LarRunnerDiagnostics.hh"
0021 
0022 namespace sim
0023 {
0024 class SimEnergyDeposit;
0025 class OBTRHelper;
0026 }  // namespace sim
0027 
0028 namespace celeritas
0029 {
0030 class OutputRegistry;
0031 namespace inp
0032 {
0033 struct OpticalStandaloneInput;
0034 }
0035 namespace optical
0036 {
0037 class Runner;
0038 }  // namespace optical
0039 
0040 //---------------------------------------------------------------------------//
0041 /*!
0042  * Setup and run a standalone optical simulation.
0043  *
0044  * This class manages the interface between LArSoft data objects and Celeritas.
0045  * It is separated from the \c PDFullSimCeler plugin to allow testing
0046  * and extension to future plugin frameworks (e.g., Phlex).
0047  * Instantiating the class sets up Celeritas shared and state objects using an
0048  * input configuration, and each call take a set of energy deposition steps and
0049  * returns a vector of detector hits.
0050  *
0051  * The implementation of this class sets up a standalone Celeritas optical
0052  * simulation using internal code to extract hits and "backtracker"
0053  * metadata. Conversion between Celeritas objects and the LArSoft data model
0054  * happens in this class inside the "call" operator.
0055  *
0056  * Since LArSoft is single-threaded, this runner uses only a single "stream".
0057  * We can in theory enable OpenMP to support parallelism across multiple CPUs
0058  * in a single-process execution. The class is also \em stateful because it
0059  * stores the backtracker record helpers and particle metadata.
0060 
0061  * Requirements for PDFastSimPar run:
0062  * - IncludePropTime: true
0063  * - UseLitePhotons: true
0064  * - GeoPropTimeOnly: false
0065  * Differences:
0066  * - Reflected and unreflected light are combined
0067  * TODO:
0068  * - OnlyActiveVolume: check ISTPC::isScintInActiveVolume
0069  *
0070  * \par Construction
0071  * See \c celeritas::inp::OpticalStandaloneInput .
0072  */
0073 class LarStandaloneRunner
0074 {
0075   public:
0076     //!@{
0077     //! \name Type aliases
0078     using VecSED = std::vector<sim::SimEnergyDeposit>;
0079     using VecBTR = std::vector<sim::OpDetBacktrackerRecord>;
0080     using VecSPL = std::vector<sim::SimPhotonsLite>;
0081     using Input = inp::OpticalStandaloneInput;
0082     using VecReal3 = std::vector<Real3>;
0083     //!@}
0084 
0085     //! Calculated output from an event
0086     struct result_type
0087     {
0088         VecSPL sim_photons;
0089         VecBTR backtrack;
0090     };
0091 
0092   public:
0093     // Set up the problem, including detector ID coordinates
0094     LarStandaloneRunner(Input&&, VecReal3 const& det_coords);
0095     // Don't allow copies of this class
0096     CELER_DEFAULT_MOVE_DELETE_COPY(LarStandaloneRunner);
0097 
0098     // Run optical photons from a single set of energy steps
0099     result_type operator()(VecSED const& edep);
0100 
0101     //! Access output registry for testing
0102     OutputRegistry const& output_reg() const { return *output_; }
0103 
0104   private:
0105     //// TYPES ////
0106     using SpanCelerHits = Span<optical::DetectorHit const>;
0107     using MapIntInt = std::unordered_map<int, int>;
0108 
0109     struct StepMetadata
0110     {
0111         //! Unique LArG4 track ID
0112         //! see ParticleListActionService::preUserTrackingAction
0113         int track_id = sim::NoParticleId;
0114         //! Energy deposit per emitted photon
0115         double avg_edep{};
0116         //! Midpoint of step (nativeLArSoft units)
0117         Array<double, 3> midpoint{};
0118     };
0119 
0120     //// DATA ////
0121 
0122     //!@{
0123     //! \name Problem setup
0124 
0125     std::shared_ptr<optical::Runner> runner_;
0126     // Celeritas volume instance ID for each LArSoft detector channel
0127     std::unordered_map<VolumeInstanceId, unsigned int> geo_to_channel_;
0128     // Diagnostics written at every step
0129     std::shared_ptr<OutputRegistry> output_;
0130     std::shared_ptr<detail::LarRunnerDiagnostics> diagnostics_;
0131 
0132     //!@}
0133     //!@{
0134     //! \name Temporary state
0135 
0136     // Energy deposits
0137     std::vector<StepMetadata> step_md_;
0138     // Hit recorders for each celeritas volume instance ID
0139     std::vector<std::unique_ptr<sim::OBTRHelper>> btr_helpers_;
0140     //! Photon hit count, by detector and rounded ns
0141     std::vector<MapIntInt> lite_hits_;
0142 
0143     //!@}
0144 
0145     //// HELPERS ////
0146 
0147     std::size_t num_channels() const { return geo_to_channel_.size(); }
0148     void hit(SpanCelerHits);
0149 };
0150 
0151 //---------------------------------------------------------------------------//
0152 }  // namespace celeritas