Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:53:43

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/optical/model/RayleighMfpCalculator.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Macros.hh"
0010 #include "corecel/Types.hh"
0011 #include "celeritas/Constants.hh"
0012 #include "celeritas/Quantities.hh"
0013 #include "celeritas/grid/NonuniformGridCalculator.hh"
0014 #include "celeritas/io/ImportOpticalMaterial.hh"
0015 #include "celeritas/mat/MaterialView.hh"
0016 #include "celeritas/optical/MaterialView.hh"
0017 #include "celeritas/optical/detail/OpticalUtils.hh"
0018 
0019 namespace celeritas
0020 {
0021 namespace optical
0022 {
0023 //---------------------------------------------------------------------------//
0024 /*!
0025  * Calculate the Rayleigh MFP for a given set of material properties.
0026  *
0027  * Uses the Einstein-Smoluchowski formula to calculate the mean free path
0028  * at a given energy. In Landau and Lifshitz Electrodynamics of Continuous
0029  * Media, the mean free path is given by equation (120.2):
0030  * \f[
0031     l^{-1} = \frac{1}{6\pi} k^4 \rho k_B T \left(\frac{\partial \rho}{\partial
0032  P}\right)_T \left(\frac{\partial \varepsilon}{\partial \rho}\right)_T^2
0033  * \f]
0034  * where we only consider density fluctations at constant temperature. The
0035  * first partial derivative may be rewritten in terms of the isothermal
0036  * compressibility \f$ \beta_T \f$:
0037  * \f[
0038     \left(\frac{\partial \rho}{\partial P}\right)_T = \rho \beta_T.
0039  * \f]
0040  * The latter partial derivative may be calculated via the Clausius-Mossetti
0041  * equation
0042  * \f[
0043     \frac{\varepsilon - 1}{\varepsilon + 2} = A \rho
0044  * \f]
0045  * for constant \f$ A \f$, giving
0046  * \f[
0047     \left(\frac{\partial \varepsilon}{\partial \rho}\right)_T =
0048  \frac{(\varepsilon - 1)(\varepsilon + 2)}{3\rho}.
0049  * \f]
0050  * The final equation for the MFP in terms of energy:
0051  * \f[
0052     l^{-1} = \frac{k_B T \beta_T}{6\pi} \left(\frac{E}{\hbar c}\right)^4 \left[
0053  \frac{(\varepsilon - 1)(\varepsilon + 2)}{3} \right]^2.
0054  * \f]
0055  *
0056  * The scale factor is a unitless user customizable factor that's multiplied
0057  * to the inverse MFP.
0058  */
0059 class RayleighMfpCalculator
0060 {
0061   public:
0062     //!@{
0063     //! \name Type aliases
0064     using Energy = units::MevEnergy;
0065     using Grid = typename NonuniformGridCalculator::Grid;
0066     //!@}
0067 
0068   public:
0069     // Construct from material and Rayleigh properties
0070     inline CELER_FUNCTION
0071     RayleighMfpCalculator(MaterialView const& material,
0072                           ImportOpticalRayleigh const& rayleigh,
0073                           ::celeritas::MaterialView const& core_material);
0074 
0075     // Calculate the MFP for the given energy
0076     inline CELER_FUNCTION real_type operator()(Energy) const;
0077 
0078     //! Retrieve the underlying energy grid used to calculate the MFP
0079     inline CELER_FUNCTION Grid const& grid() const
0080     {
0081         return calc_rindex_.grid();
0082     }
0083 
0084   private:
0085     // Calculate refractive index [MeV -> unitless]
0086     NonuniformGridCalculator calc_rindex_;
0087 
0088     // Constant prefactor at all energies
0089     real_type density_fluctuation_;
0090 };
0091 
0092 //---------------------------------------------------------------------------//
0093 // INLINE DEFINITIONS
0094 //---------------------------------------------------------------------------//
0095 /*!
0096  * Construct with defaults.
0097  */
0098 RayleighMfpCalculator::RayleighMfpCalculator(
0099     MaterialView const& material,
0100     ImportOpticalRayleigh const& rayleigh,
0101     ::celeritas::MaterialView const& core_material)
0102     : calc_rindex_(material.make_refractive_index_calculator())
0103     , density_fluctuation_(rayleigh.scale_factor * rayleigh.compressibility
0104                            * core_material.temperature()
0105                            * celeritas::constants::k_boltzmann
0106                            / (6 * celeritas::constants::pi))
0107 {
0108     CELER_EXPECT(rayleigh);
0109     CELER_EXPECT(material.material_id() == core_material.optical_material_id());
0110     CELER_EXPECT(density_fluctuation_ > 0);
0111 }
0112 
0113 //---------------------------------------------------------------------------//
0114 /*!
0115  * Calculate the optical Rayleigh mean free path at the given energy.
0116  */
0117 CELER_FUNCTION real_type RayleighMfpCalculator::operator()(Energy energy) const
0118 {
0119     CELER_EXPECT(energy > zero_quantity());
0120 
0121     real_type rindex = calc_rindex_(value_as<Energy>(energy));
0122     CELER_ASSERT(rindex > 1);
0123 
0124     real_type wave_number = 2 * celeritas::constants::pi
0125                             / detail::energy_to_wavelength(energy);
0126     real_type permitivity_fluctuation = (ipow<2>(rindex) - 1)
0127                                         * (ipow<2>(rindex) + 2) / 3;
0128 
0129     return 1
0130            / (density_fluctuation_ * ipow<4>(wave_number)
0131               * ipow<2>(permitivity_fluctuation));
0132 }
0133 
0134 //---------------------------------------------------------------------------//
0135 }  // namespace optical
0136 }  // namespace celeritas