Back to home page

EIC code displayed by LXR

 
 

    


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

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