Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-29 09:13:54

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 geocel/VolumeData.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Macros.hh"
0010 #include "corecel/Types.hh"
0011 #include "corecel/data/Collection.hh"
0012 #include "geocel/Types.hh"
0013 
0014 namespace celeritas
0015 {
0016 //---------------------------------------------------------------------------//
0017 //! Unique instance ID of the "world" volume (root of the volume graph)
0018 inline constexpr VolumeUniqueInstanceId world_unique_instance{0};
0019 
0020 //---------------------------------------------------------------------------//
0021 /*!
0022  * Per-volume data: material assignment and parent/child instance edges.
0023  *
0024  * Parents and children are stored as ranges into the \c vi_storage backend of
0025  * \c VolumeParamsData.
0026  */
0027 struct VolumeRecord
0028 {
0029     //! Material assignment for this volume
0030     GeoMatId material;
0031     //! Incoming edges: volume instances that instantiate this volume
0032     ItemRange<VolumeInstanceId> parents;
0033     //! Outgoing edges: child volume instances placed inside this volume
0034     ItemRange<VolumeInstanceId> children;
0035 };
0036 
0037 //---------------------------------------------------------------------------//
0038 /*!
0039  * Scalar values for the volume hierarchy graph.
0040  */
0041 struct VolumeParamsScalars
0042 {
0043     //! Root volume of the geometry graph
0044     VolumeId world;
0045     //! Enclosing instance of the world volume (null if world is a true root)
0046     VolumeInstanceId world_instance;
0047     //! Number of logical volumes (nodes)
0048     VolumeId::size_type num_volumes{0};
0049     //! Number of volume instances (edges)
0050     VolumeInstanceId::size_type num_volume_instances{0};
0051     //! Total number of unique root-to-node paths (= num_desc of world volume)
0052     VolumeUniqueInstanceId::size_type num_unique_instances{0};
0053     //! Depth of the volume graph (1 for a world with no children)
0054     VolumeLevelId::size_type num_volume_levels{0};
0055 
0056     //! True if scalars are in a consistent populated state
0057     explicit CELER_FUNCTION operator bool() const
0058     {
0059         return num_volume_levels > 0 && num_unique_instances > 0
0060                && static_cast<bool>(world);
0061     }
0062 };
0063 
0064 //---------------------------------------------------------------------------//
0065 /*!
0066  * Persistent data for the volume hierarchy graph.
0067  *
0068  * This stores the volume DAG (directed acyclic graph) in Collection-based
0069  * storage for host and device compatibility. Volumes are nodes and volume
0070  * instances are edges.
0071  *
0072  * See \c VolumeParams for construction details and label-based lookup.
0073  */
0074 template<Ownership W, MemSpace M>
0075 struct VolumeParamsData
0076 {
0077     //// TYPES ////
0078 
0079     template<class T>
0080     using VolumeItems = Collection<T, W, M, VolumeId>;
0081     template<class T>
0082     using VolInstItems = Collection<T, W, M, VolumeInstanceId>;
0083     template<class T>
0084     using Items = Collection<T, W, M>;
0085 
0086     //// DATA ////
0087 
0088     //! Per-volume records (material, parent/child ranges into vi_storage)
0089     VolumeItems<VolumeRecord> volumes;
0090     //! Logical volume for each volume instance (vi -> v)
0091     VolInstItems<VolumeId> volume_ids;
0092     //! Flat backing storage for per-volume parent and child instance lists
0093     Items<VolumeInstanceId> vi_storage;
0094     //! Pre-computed per-sibling offset (see \c VolumePathAccumulator)
0095     VolInstItems<VolumeUniqueInstanceId::size_type> unique_instance_offsets;
0096 
0097     //! Scalar values (world ID, world instance, depths, etc.)
0098     VolumeParamsScalars scalars;
0099 
0100     //// METHODS ////
0101 
0102     //! True if data is consistent (empty and fully-populated states are valid)
0103     explicit CELER_FUNCTION operator bool() const
0104     {
0105         if (volumes.empty())
0106         {
0107             // Valid empty state (e.g., for testing or ORANGE debugging)
0108             return volume_ids.empty() && vi_storage.empty()
0109                    && unique_instance_offsets.empty() && !scalars;
0110         }
0111         return static_cast<bool>(scalars)
0112                && unique_instance_offsets.size() == volume_ids.size();
0113     }
0114 
0115     //! Assign from another set of data
0116     template<Ownership W2, MemSpace M2>
0117     VolumeParamsData& operator=(VolumeParamsData<W2, M2> const& other)
0118     {
0119         CELER_EXPECT(other);
0120         volumes = other.volumes;
0121         volume_ids = other.volume_ids;
0122         vi_storage = other.vi_storage;
0123         unique_instance_offsets = other.unique_instance_offsets;
0124         scalars = other.scalars;
0125         CELER_ENSURE(*this);
0126         return *this;
0127     }
0128 };
0129 
0130 //---------------------------------------------------------------------------//
0131 }  // namespace celeritas