File indexing completed on 2026-05-27 07:23:59
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/algebra.hpp"
0013 #include "detray/definitions/detail/qualifiers.hpp"
0014 #include "detray/definitions/math.hpp"
0015 #include "detray/definitions/units.hpp"
0016 #include "detray/material/detail/density_effect_data.hpp"
0017 #include "detray/utils/invalid_values.hpp"
0018 #include "detray/utils/type_traits.hpp"
0019
0020
0021 #include <ratio>
0022 #include <sstream>
0023
0024 namespace detray {
0025
0026
0027 enum class material_state {
0028 e_solid = 0,
0029 e_liquid = 1,
0030 e_gas = 2,
0031 e_unknown = 3
0032 };
0033
0034 template <concepts::scalar scalar_t, typename R = std::ratio<1, 1>>
0035 struct material {
0036 using ratio = R;
0037 using scalar_type = scalar_t;
0038
0039 constexpr material() = default;
0040
0041
0042 DETRAY_HOST_DEVICE
0043 constexpr material(const scalar_type x0, const scalar_type l0,
0044 const scalar_type ar, const scalar_type z,
0045 const scalar_type mass_rho, const material_state state)
0046 : m_x0(x0),
0047 m_l0(l0),
0048 m_ar(ar),
0049 m_z(z),
0050 m_mass_rho(mass_rho),
0051 m_state(state) {
0052 m_molar_rho = mass_to_molar_density(ar, mass_rho);
0053 }
0054
0055
0056 DETRAY_HOST_DEVICE
0057 constexpr material(const scalar_type x0, const scalar_type l0,
0058 const scalar_type ar, const scalar_type z,
0059 const scalar_type mass_rho, const material_state state,
0060 const scalar_type d_a, const scalar_type d_m,
0061 const scalar_type d_X0, const scalar_type d_X1,
0062 const scalar_type d_I, const scalar_type d_nC,
0063 const scalar_type d_delta0)
0064 : m_x0(x0),
0065 m_l0(l0),
0066 m_ar(ar),
0067 m_z(z),
0068 m_mass_rho(mass_rho),
0069 m_state(state),
0070 m_density(d_a, d_m, d_X0, d_X1, d_I, d_nC, d_delta0),
0071 m_has_density_effect_data(true) {
0072 m_molar_rho = mass_to_molar_density(ar, mass_rho);
0073 }
0074
0075
0076
0077
0078 DETRAY_HOST_DEVICE
0079 constexpr bool operator==(const material<scalar_type> &rhs) const {
0080 return (m_x0 == rhs.X0() && m_l0 == rhs.L0() && m_ar == rhs.Ar() &&
0081 m_z == rhs.Z());
0082 }
0083
0084
0085
0086
0087 DETRAY_HOST_DEVICE
0088 constexpr bool operator!=(const material<scalar_type> &rhs) const {
0089 return !(*this == rhs);
0090 }
0091
0092
0093 DETRAY_HOST_DEVICE
0094 constexpr scalar_type X0() const { return m_x0; }
0095
0096 DETRAY_HOST_DEVICE
0097 constexpr scalar_type L0() const { return m_l0; }
0098
0099 DETRAY_HOST_DEVICE
0100 constexpr scalar_type Ar() const { return m_ar; }
0101
0102 DETRAY_HOST_DEVICE
0103 constexpr scalar_type Z() const { return m_z; }
0104
0105 DETRAY_HOST_DEVICE
0106 constexpr scalar_type mass_density() const { return m_mass_rho; }
0107
0108
0109 DETRAY_HOST_DEVICE
0110 constexpr scalar_type molar_density() const { return m_molar_rho; }
0111
0112 DETRAY_HOST_DEVICE
0113 constexpr material_state state() const { return m_state; }
0114
0115
0116 DETRAY_HOST_DEVICE
0117 constexpr scalar_type molar_electron_density() const {
0118 return m_z * m_molar_rho;
0119 }
0120
0121
0122 DETRAY_HOST_DEVICE
0123 constexpr const detail::density_effect_data<scalar_type> &
0124 density_effect_data() const {
0125 return m_density;
0126 }
0127
0128
0129 DETRAY_HOST_DEVICE
0130 scalar_type mean_excitation_energy() const {
0131 if (!m_has_density_effect_data) {
0132
0133 return 16.f * unit<scalar_type>::eV *
0134 math::pow(m_z, static_cast<scalar_type>(0.9));
0135 } else {
0136 return m_density.get_mean_excitation_energy();
0137 }
0138 }
0139
0140 DETRAY_HOST_DEVICE
0141 constexpr scalar_type fraction() const {
0142 if constexpr (ratio::num == 0) {
0143 return 0.f;
0144 } else if constexpr (ratio::den == 0) {
0145 return detail::invalid_value<scalar_type>();
0146 } else {
0147 return static_cast<scalar_type>(ratio::num) /
0148 static_cast<scalar_type>(ratio::den);
0149 }
0150 }
0151
0152
0153 DETRAY_HOST
0154 std::string to_string() const {
0155 std::stringstream strm;
0156 if (m_ar <= 0.f) {
0157 strm << "vacuum";
0158 return strm.str();
0159 }
0160 strm << "material: ";
0161 strm << " X0 = " << m_x0;
0162 strm << " | L0 = " << m_l0;
0163 strm << " | Z = " << m_z;
0164
0165 strm << " | state = ";
0166 switch (m_state) {
0167 using enum material_state;
0168 case e_solid: {
0169 strm << "solid";
0170 break;
0171 }
0172 case e_liquid: {
0173 strm << "liquid";
0174 break;
0175 }
0176 case e_gas: {
0177 strm << "gaseous";
0178 break;
0179 }
0180 default: {
0181 strm << "unknown";
0182 break;
0183 }
0184 }
0185
0186 return strm.str();
0187 }
0188
0189
0190 DETRAY_HOST
0191 friend std::ostream &operator<<(std::ostream &os, const material &mat) {
0192 os << mat.to_string();
0193 return os;
0194 }
0195
0196
0197 DETRAY_HOST_DEVICE
0198 bool has_density_effect_data() const { return m_has_density_effect_data; }
0199
0200 protected:
0201
0202 DETRAY_HOST_DEVICE
0203 constexpr void set_X0(scalar_type x0) { m_x0 = x0; }
0204
0205 DETRAY_HOST_DEVICE
0206 constexpr void set_L0(scalar_type l0) { m_l0 = l0; }
0207
0208 DETRAY_HOST_DEVICE
0209 constexpr void set_Ar(scalar_type ar) { m_ar = ar; }
0210
0211 DETRAY_HOST_DEVICE
0212 constexpr void set_Z(scalar_type z) { m_z = z; }
0213
0214 DETRAY_HOST_DEVICE
0215 constexpr void set_mass_density(scalar_type mass_rho) {
0216 m_mass_rho = mass_rho;
0217 }
0218
0219 DETRAY_HOST_DEVICE
0220 constexpr void set_molar_density(scalar_type molar_rho) {
0221 m_molar_rho = molar_rho;
0222 }
0223 DETRAY_HOST_DEVICE
0224
0225 constexpr scalar_type mass_to_molar_density(double ar, double mass_rho) {
0226 if (mass_rho == 0.) {
0227 return 0.f;
0228 }
0229
0230 const double molar_mass{ar * unit<double>::g / unit<double>::mol};
0231
0232 return static_cast<scalar_type>(mass_rho / molar_mass);
0233 }
0234
0235 private:
0236
0237 scalar_type m_x0 = detail::invalid_value<scalar_type>();
0238 scalar_type m_l0 = detail::invalid_value<scalar_type>();
0239 scalar_type m_ar = 0.f;
0240 scalar_type m_z = 0.f;
0241 scalar_type m_mass_rho = 0.f;
0242 scalar_type m_molar_rho = 0.f;
0243 material_state m_state = material_state::e_unknown;
0244 detail::density_effect_data<scalar_type> m_density = {};
0245 bool m_has_density_effect_data = false;
0246 };
0247
0248
0249 #define DETRAY_DECLARE_MATERIAL(MATERIAL_NAME, X0, L0, Ar, Z, Rho, State) \
0250 template <concepts::scalar scalar_t, typename R = std::ratio<1, 1>> \
0251 struct MATERIAL_NAME final : public material<scalar_t, R> { \
0252 using base_type = material<scalar_t, R>; \
0253 using base_type::base_type; \
0254 DETRAY_HOST_DEVICE \
0255 constexpr MATERIAL_NAME() : base_type(X0, L0, Ar, Z, Rho, State) {} \
0256 }
0257
0258
0259
0260 #define DETRAY_DECLARE_MATERIAL_WITH_DED( \
0261 MATERIAL_NAME, X0, L0, Ar, Z, Rho, State, Density0, Density1, Density2, \
0262 Density3, Density4, Density5, Density6) \
0263 template <concepts::scalar scalar_t, typename R = std::ratio<1, 1>> \
0264 struct MATERIAL_NAME final : public material<scalar_t, R> { \
0265 using base_type = material<scalar_t, R>; \
0266 using base_type::base_type; \
0267 DETRAY_HOST_DEVICE \
0268 constexpr MATERIAL_NAME() \
0269 : base_type(X0, L0, Ar, Z, Rho, State, Density0, Density1, Density2, \
0270 Density3, Density4, Density5, Density6) {} \
0271 }
0272
0273 }