Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:09:07

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 celeritas/mat/MaterialData.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Types.hh"
0010 #include "corecel/cont/Range.hh"
0011 #include "corecel/data/Collection.hh"
0012 #include "corecel/data/CollectionBuilder.hh"
0013 #include "celeritas/Quantities.hh"
0014 #include "celeritas/Types.hh"
0015 #include "celeritas/phys/AtomicNumber.hh"
0016 
0017 namespace celeritas
0018 {
0019 //---------------------------------------------------------------------------//
0020 // PARAMS
0021 //---------------------------------------------------------------------------//
0022 /*!
0023  * Fundamental, invariant properties of a nuclide.
0024  *
0025  * A nuclide is a single isotope of an element.
0026  *
0027  * \todo Rename NuclideRecord?
0028  */
0029 struct IsotopeRecord
0030 {
0031     //!@{
0032     //! \name Type aliases
0033     using AtomicMassNumber = AtomicNumber;
0034     //!@}
0035 
0036     AtomicNumber atomic_number;  //!< Atomic number Z
0037     AtomicMassNumber atomic_mass_number;  //!< Atomic number A
0038     units::MevEnergy binding_energy;  //!< Nuclear binding energy (BE)
0039     units::MevEnergy proton_loss_energy;  //!< BE(A, Z) - BE(A-1, Z-1)
0040     units::MevEnergy neutron_loss_energy;  //!< BE(A, Z) - BE(A-1, Z)
0041     units::MevMass nuclear_mass;  //!< Nucleons' mass + binding energy
0042 };
0043 
0044 //---------------------------------------------------------------------------//
0045 /*!
0046  * Fractional isotope component of an element.
0047  *
0048  * This represents, e.g., the fraction of 2H (deuterium) in element H.
0049  */
0050 struct ElIsotopeComponent
0051 {
0052     IsotopeId isotope;  //!< Index in MaterialParams isotopes
0053     real_type fraction;  //!< Fraction of number density
0054 };
0055 
0056 //---------------------------------------------------------------------------//
0057 /*!
0058  * Fundamental, invariant properties of an element.
0059  *
0060  * Add elemental properties as needed if they apply to more than one physics
0061  * model.
0062  *
0063  * Note that more than one "element def" can exist for a single atomic number:
0064  * there might be different enrichments of an element in the problem.
0065  */
0066 struct ElementRecord
0067 {
0068     AtomicNumber atomic_number;  //!< Z number
0069     units::AmuMass atomic_mass;  //!< Isotope-weighted average atomic mass
0070     ItemRange<ElIsotopeComponent> isotopes;  //!< Isotopes for this element
0071 
0072     // COMPUTED PROPERTIES
0073 
0074     real_type cbrt_z = 0;  //!< Z^{1/3}
0075     real_type cbrt_zzp = 0;  //!< (Z (Z + 1))^{1/3}
0076     real_type log_z = 0;  //!< log Z
0077 
0078     real_type coulomb_correction = 0;  //!< f(Z)
0079     real_type mass_radiation_coeff = 0;  //!< 1/X_0 (bremsstrahlung)
0080 };
0081 
0082 //---------------------------------------------------------------------------//
0083 /*!
0084  * Fractional element component of a material.
0085  *
0086  * This represents, e.g., the fraction of hydrogen in water.
0087  */
0088 struct MatElementComponent
0089 {
0090     ElementId element;  //!< Index in MaterialParams elements
0091     real_type fraction;  //!< Fraction of number density
0092 };
0093 
0094 //---------------------------------------------------------------------------//
0095 /*!
0096  * Fundamental (static) properties of a material.
0097  *
0098  * Multiple material definitions are allowed to reuse a single element
0099  * definition vector (memory management from the params store should handle
0100  * this). Derivative properties such as electron_density are calculated from
0101  * the elemental components.
0102  */
0103 struct MaterialRecord
0104 {
0105     real_type number_density;  //!< Atomic number density [1/length^3]
0106     real_type temperature;  //!< Temperature [K]
0107     MatterState matter_state;  //!< Solid, liquid, gas
0108     ItemRange<MatElementComponent> elements;  //!< Element components
0109 
0110     // COMPUTED PROPERTIES
0111 
0112     real_type zeff;  //!< Weighted atomic number
0113     real_type density;  //!< Density [mass/length^3]
0114     real_type electron_density;  //!< Electron number density [1/length^3]
0115     real_type rad_length;  //!< Radiation length [length]
0116     units::MevEnergy mean_exc_energy;  //!< Mean excitation energy [MeV]
0117     units::LogMevEnergy log_mean_exc_energy;  //!< Log mean excitation energy
0118 };
0119 
0120 //---------------------------------------------------------------------------//
0121 /*!
0122  * Access material properties on the device.
0123  *
0124  * This view is created from \c MaterialParams.
0125  *
0126  * If a material has optical properties defined, \c optical_id will give the
0127  * index into the optical properties data. Otherwise, it will be an invalid ID,
0128  * or empty if no optical properties are present for any material.
0129  *
0130  * \sa MaterialParams (owns the pointed-to data)
0131  * \sa ElementView (uses the pointed-to element data in a kernel)
0132  * \sa IsotopeView (uses the pointed-to isotope data in a kernel)
0133  * \sa MaterialView (uses the pointed-to material data in a kernel)
0134  */
0135 template<Ownership W, MemSpace M>
0136 struct MaterialParamsData
0137 {
0138     template<class T>
0139     using Items = Collection<T, W, M>;
0140     template<class T>
0141     using MaterialItems = Collection<T, W, M, PhysMatId>;
0142 
0143     Items<IsotopeRecord> isotopes;
0144     Items<ElementRecord> elements;
0145     Items<ElIsotopeComponent> isocomponents;
0146     Items<MatElementComponent> elcomponents;
0147     Collection<MaterialRecord, W, M, PhysMatId> materials;
0148     IsotopeComponentId::size_type max_isotope_components{};
0149     ElementComponentId::size_type max_element_components{};
0150     MaterialItems<OptMatId> optical_id;
0151 
0152     //// MEMBER FUNCTIONS ////
0153 
0154     //! Whether the data is assigned
0155     explicit CELER_FUNCTION operator bool() const
0156     {
0157         return !materials.empty();
0158     }
0159 
0160     //! Assign from another set of data
0161     template<Ownership W2, MemSpace M2>
0162     MaterialParamsData& operator=(MaterialParamsData<W2, M2> const& other)
0163     {
0164         CELER_EXPECT(other);
0165         isotopes = other.isotopes;
0166         elements = other.elements;
0167         isocomponents = other.isocomponents;
0168         elcomponents = other.elcomponents;
0169         materials = other.materials;
0170         max_isotope_components = other.max_isotope_components;
0171         max_element_components = other.max_element_components;
0172         optical_id = other.optical_id;
0173         return *this;
0174     }
0175 };
0176 
0177 //---------------------------------------------------------------------------//
0178 // STATE
0179 //---------------------------------------------------------------------------//
0180 /*!
0181  * Dynamic material state of a particle track.
0182  */
0183 struct MaterialTrackState
0184 {
0185     PhysMatId material_id;  //!< Current material being tracked
0186 };
0187 
0188 //---------------------------------------------------------------------------//
0189 /*!
0190  * Store dynamic states of multiple physical particles.
0191  *
0192  * The "element scratch space" is a 2D array of reals, indexed with
0193  * [trackslot_id][el_component_id], where the fast-moving dimension has the
0194  * greatest number of element components of any material in the problem. This
0195  * can be used for the physics to calculate microscopic cross sections.
0196  *
0197  * \sa MaterialStateStore (owns the pointed-to data)
0198  * \sa MaterialTrackView (uses the pointed-to data in a kernel)
0199  */
0200 template<Ownership W, MemSpace M>
0201 struct MaterialStateData
0202 {
0203     template<class T>
0204     using Items = StateCollection<T, W, M>;
0205 
0206     Items<MaterialTrackState> state;
0207     Items<real_type> element_scratch;  // 2D array: [num states][max
0208                                        // components]
0209 
0210     //! Whether the interface is assigned
0211     explicit CELER_FUNCTION operator bool() const { return !state.empty(); }
0212 
0213     //! State size
0214     CELER_FUNCTION size_type size() const { return state.size(); }
0215 
0216     //! Assign from another set of data
0217     template<Ownership W2, MemSpace M2>
0218     MaterialStateData& operator=(MaterialStateData<W2, M2>& other)
0219     {
0220         CELER_EXPECT(other);
0221         state = other.state;
0222         element_scratch = other.element_scratch;
0223         return *this;
0224     }
0225 };
0226 
0227 //---------------------------------------------------------------------------//
0228 /*!
0229  * Resize a material state in host code.
0230  */
0231 template<MemSpace M>
0232 inline void resize(MaterialStateData<Ownership::value, M>* data,
0233                    HostCRef<MaterialParamsData> const& params,
0234                    size_type size)
0235 {
0236     CELER_EXPECT(size > 0);
0237     resize(&data->state, size);
0238     resize(&data->element_scratch, size * params.max_element_components);
0239 }
0240 
0241 //---------------------------------------------------------------------------//
0242 }  // namespace celeritas