Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-10 10:11:50

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/SurfaceData.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Assert.hh"
0010 #include "corecel/data/Collection.hh"
0011 #include "corecel/data/CollectionBuilder.hh"
0012 #include "geocel/Types.hh"
0013 
0014 namespace celeritas
0015 {
0016 //---------------------------------------------------------------------------//
0017 /*!
0018  * Store surface data corresponding to a volume.
0019  *
0020  * This stores information about the surfaces (both boundary and interface)
0021  * of a volume. The \em boundary is a single optional surface ID, and the
0022  * \em interface is an unzipped map \code (pre, post) -> surface \endcode.
0023  *
0024  * If \c interface_pre and \c interface_post are zipped, the result is \em
0025  * sorted.  In other words, the pre-step surface can be searched with
0026  * bisection, and the resulting subrange can also be searched with bisection to
0027  * find the post-step surface. This then corresponds to the \c SurfaceId of
0028  * that interface.
0029  */
0030 struct VolumeSurfaceRecord
0031 {
0032     //! Surface identifier for the volume boundary
0033     SurfaceId boundary;
0034 
0035     //! Sorted range of exiting volume instances (from this volume)
0036     ItemRange<VolumeInstanceId> interface_pre;
0037 
0038     //! Corresponding range of entering volume instances (to other volumes)
0039     ItemRange<VolumeInstanceId> interface_post;
0040 
0041     //! Surface IDs for the pre->post mapping
0042     ItemRange<SurfaceId> surface;
0043 
0044     //! True if valid data is present
0045     explicit CELER_FUNCTION operator bool() const
0046     {
0047         return boundary
0048                || (!interface_pre.empty()
0049                    && interface_pre.size() == interface_post.size()
0050                    && interface_pre.size() == surface.size());
0051     }
0052 };
0053 
0054 //---------------------------------------------------------------------------//
0055 /*!
0056  * Persistent data for mapping between volumes and their surfaces.
0057  *
0058  * This structure stores device-compatible data relating volumes and their
0059  * surfaces, primarily for optical physics at material interfaces. If \c
0060  * SurfaceParams is constructed with an empty surface input (no user-provided
0061  * surfaces for an optical physics run) it will be correctly sized but have no
0062  * surfaces. It can also be constructed in a "not very useful" but valid state
0063  * for EM-only physics: the volume surfaces array can be empty.
0064  *
0065  * If no "interface" surfaces are present then the backend storage arrays will
0066  * be empty.
0067  */
0068 template<Ownership W, MemSpace M>
0069 struct SurfaceParamsData
0070 {
0071     //// TYPES ////
0072 
0073     template<class T>
0074     using VolumeItems = Collection<T, W, M, VolumeId>;
0075     template<class T>
0076     using Items = Collection<T, W, M>;
0077 
0078     //// DATA ////
0079 
0080     //! Number of surfaces
0081     SurfaceId::size_type num_surfaces{0};
0082 
0083     //! Surface properties for logical volumes
0084     VolumeItems<VolumeSurfaceRecord> volume_surfaces;
0085 
0086     //!@{
0087     //! Backend storage for surface interfaces
0088     Items<VolumeInstanceId> volume_instance_ids;
0089     Items<SurfaceId> surface_ids;
0090     //!@}
0091 
0092     //// METHODS ////
0093 
0094     //! True if data is consistent
0095     explicit CELER_FUNCTION operator bool() const
0096     {
0097         if (volume_surfaces.empty())
0098         {
0099             // No surface data is present (no optical physics)
0100             return num_surfaces == 0 && volume_surfaces.empty()
0101                    && volume_instance_ids.empty() && surface_ids.empty();
0102         }
0103         // Surface volume data is present but there may still be no surfaces
0104         return !volume_surfaces.empty()
0105                && (volume_instance_ids.size() == 2 * surface_ids.size());
0106     }
0107 
0108     //! Assign from another set of data
0109     template<Ownership W2, MemSpace M2>
0110     SurfaceParamsData& operator=(SurfaceParamsData<W2, M2> const& other)
0111     {
0112         CELER_EXPECT(other);
0113 
0114         num_surfaces = other.num_surfaces;
0115         volume_surfaces = other.volume_surfaces;
0116         volume_instance_ids = other.volume_instance_ids;
0117         surface_ids = other.surface_ids;
0118 
0119         CELER_ENSURE(*this);
0120         return *this;
0121     }
0122 };
0123 
0124 //---------------------------------------------------------------------------//
0125 }  // namespace celeritas