Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:31:31

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2020-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file celeritas/track/SimData.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <vector>
0011 
0012 #include "corecel/Macros.hh"
0013 #include "corecel/Types.hh"
0014 #include "corecel/data/Collection.hh"
0015 #include "corecel/data/CollectionAlgorithms.hh"
0016 #include "corecel/data/CollectionBuilder.hh"
0017 #include "corecel/sys/ThreadId.hh"
0018 #include "celeritas/Quantities.hh"
0019 #include "celeritas/Types.hh"
0020 
0021 namespace celeritas
0022 {
0023 //---------------------------------------------------------------------------//
0024 /*!
0025  * Particle-dependent parameters for killing looping tracks.
0026  *
0027  * These threshold values are used to determine when tracks that are flagged as
0028  * looping (i.e., taking a large number of substeps in the field propagator)
0029  * should be killed.
0030  *
0031  * In Geant4, tracks are killed immediately if their energy is below the
0032  * "important energy" (equivalent to \c threshold_energy here) or after some
0033  * number of step iterations if their energy is above the threshold.
0034  *
0035  * In Celeritas, the default \c max_substeps in the field propagator is set to
0036  * a smaller value than in Geant4. Therefore, an additional parameter \c
0037  * max_subthreshold_steps is added to approximate Geant4's policy for killing
0038  * looping tracks: a track flagged as looping will be killed if its energy is
0039  * below \c threshold_energy and it has taken more then \c
0040  * max_subthreshold_steps steps, or after \c max_steps steps if its energy is
0041  * above the threshold.
0042  */
0043 struct LoopingThreshold
0044 {
0045     using Energy = units::MevEnergy;
0046 
0047     size_type max_subthreshold_steps{10};
0048     size_type max_steps{100};
0049     Energy threshold_energy{250};
0050 
0051     //! Whether the data are assigned
0052     explicit CELER_FUNCTION operator bool() const
0053     {
0054         return max_subthreshold_steps > 0 && max_steps > 0
0055                && threshold_energy >= zero_quantity();
0056     }
0057 };
0058 
0059 //---------------------------------------------------------------------------//
0060 /*!
0061  * Persistent simulation data.
0062  */
0063 template<Ownership W, MemSpace M>
0064 struct SimParamsData
0065 {
0066     //// TYPES ////
0067 
0068     template<class T>
0069     using ParticleItems = Collection<T, W, M, ParticleId>;
0070 
0071     //// DATA ////
0072 
0073     ParticleItems<LoopingThreshold> looping;
0074 
0075     //// METHODS ////
0076 
0077     //! Whether the data are assigned
0078     explicit CELER_FUNCTION operator bool() const { return true; }
0079 
0080     //! Assign from another set of data
0081     template<Ownership W2, MemSpace M2>
0082     SimParamsData& operator=(SimParamsData<W2, M2> const& other)
0083     {
0084         CELER_EXPECT(other);
0085         looping = other.looping;
0086         return *this;
0087     }
0088 };
0089 
0090 //---------------------------------------------------------------------------//
0091 /*!
0092  * Simulation state of a track.
0093  */
0094 struct SimTrackInitializer
0095 {
0096     TrackId track_id;  //!< Unique ID for this track
0097     TrackId parent_id;  //!< ID of parent that created it
0098     EventId event_id;  //!< ID of originating event
0099     real_type time{0};  //!< Time elapsed in lab frame since start of event
0100 
0101     //! True if assigned and valid
0102     explicit CELER_FUNCTION operator bool() const
0103     {
0104         return track_id && event_id;
0105     }
0106 };
0107 
0108 //---------------------------------------------------------------------------//
0109 /*!
0110  * Data storage/access for simulation states.
0111  *
0112  * Unless otherwise specified, units are in the native system (time = s for
0113  * CGS, step length = cm).
0114  *
0115  * \c num_looping_steps will be empty if params doesn't specify any looping
0116  * threshold.
0117  */
0118 template<Ownership W, MemSpace M>
0119 struct SimStateData
0120 {
0121     //// TYPES ////
0122 
0123     template<class T>
0124     using Items = celeritas::StateCollection<T, W, M>;
0125 
0126     //// DATA ////
0127 
0128     Items<TrackId> track_ids;  //!< Unique ID for this track
0129     Items<TrackId> parent_ids;  //!< ID of parent that created it
0130     Items<EventId> event_ids;  //!< ID of originating event
0131     Items<size_type> num_steps;  //!< Total number of steps taken
0132     Items<size_type> num_looping_steps;  //!< Number of steps taken since the
0133                                          //!< track was flagged as looping
0134     Items<real_type> time;  //!< Time elapsed in lab frame since start of event
0135 
0136     Items<TrackStatus> status;
0137     Items<real_type> step_length;
0138     Items<ActionId> post_step_action;
0139     Items<ActionId> along_step_action;
0140 
0141     //// METHODS ////
0142 
0143     //! Check whether the interface is assigned
0144     explicit CELER_FUNCTION operator bool() const
0145     {
0146         return !track_ids.empty() && !parent_ids.empty() && !event_ids.empty()
0147                && !num_steps.empty() && !time.empty() && !status.empty()
0148                && !step_length.empty() && !post_step_action.empty()
0149                && !along_step_action.empty();
0150     }
0151 
0152     //! State size
0153     CELER_FUNCTION TrackSlotId::size_type size() const
0154     {
0155         return track_ids.size();
0156     }
0157 
0158     //! Assign from another set of data
0159     template<Ownership W2, MemSpace M2>
0160     SimStateData& operator=(SimStateData<W2, M2>& other)
0161     {
0162         CELER_EXPECT(other);
0163         track_ids = other.track_ids;
0164         parent_ids = other.parent_ids;
0165         event_ids = other.event_ids;
0166         num_steps = other.num_steps;
0167         num_looping_steps = other.num_looping_steps;
0168         time = other.time;
0169         status = other.status;
0170         step_length = other.step_length;
0171         post_step_action = other.post_step_action;
0172         along_step_action = other.along_step_action;
0173         return *this;
0174     }
0175 };
0176 
0177 //---------------------------------------------------------------------------//
0178 /*!
0179  * Resize simulation states and set \c alive to be false.
0180  */
0181 template<MemSpace M>
0182 void resize(SimStateData<Ownership::value, M>* data,
0183             HostCRef<SimParamsData> const& params,
0184             size_type size)
0185 {
0186     CELER_EXPECT(size > 0);
0187 
0188     resize(&data->track_ids, size);
0189     resize(&data->parent_ids, size);
0190     resize(&data->event_ids, size);
0191     resize(&data->num_steps, size);
0192     if (!params.looping.empty())
0193     {
0194         resize(&data->num_looping_steps, size);
0195     }
0196     resize(&data->time, size);
0197 
0198     resize(&data->status, size);
0199     fill(TrackStatus::inactive, &data->status);
0200 
0201     resize(&data->step_length, size);
0202     resize(&data->post_step_action, size);
0203     resize(&data->along_step_action, size);
0204 
0205     CELER_ENSURE(*data);
0206 }
0207 
0208 //---------------------------------------------------------------------------//
0209 }  // namespace celeritas