File indexing completed on 2026-05-27 07:24:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "detray/definitions/units.hpp"
0011 #include "detray/geometry/mask.hpp"
0012 #include "detray/geometry/shapes/line.hpp"
0013 #include "detray/geometry/surface_descriptor.hpp"
0014 #include "detray/material/concepts.hpp"
0015 #include "detray/material/material.hpp"
0016 #include "detray/material/material_rod.hpp"
0017 #include "detray/material/material_slab.hpp"
0018 #include "detray/material/mixture.hpp"
0019 #include "detray/material/predefined_materials.hpp"
0020 #include "detray/navigation/intersection/ray_intersector.hpp"
0021
0022
0023 #include "detray/test/framework/types.hpp"
0024
0025
0026 #include <gtest/gtest.h>
0027
0028
0029 #include <limits>
0030
0031 using namespace detray;
0032
0033 using test_algebra = test::algebra;
0034 using scalar = test::scalar;
0035 using point2 = test::point2;
0036 using point3 = test::point3;
0037 using transform3 = test::transform3;
0038 using vector3 = test::vector3;
0039
0040 namespace {
0041
0042 constexpr scalar tol{1e-7f};
0043 constexpr auto max_val{std::numeric_limits<scalar>::max()};
0044
0045 }
0046
0047
0048 GTEST_TEST(detray_material, materials) {
0049
0050 constexpr vacuum<scalar> vac;
0051
0052 static_assert(concepts::material_params<decltype(vac)>);
0053 static_assert(concepts::homogeneous_material<decltype(vac)>);
0054 static_assert(!concepts::surface_material<decltype(vac)>);
0055 static_assert(concepts::volume_material<decltype(vac)>);
0056 static_assert(!concepts::material_map<decltype(vac)>);
0057
0058 EXPECT_EQ(vac.X0(), max_val);
0059 EXPECT_EQ(vac.L0(), max_val);
0060 EXPECT_EQ(vac.Ar(), scalar{0});
0061 EXPECT_EQ(vac.Z(), scalar{0});
0062 EXPECT_EQ(vac.molar_density(), scalar{0});
0063 EXPECT_EQ(vac.molar_electron_density(), scalar{0});
0064
0065
0066 constexpr beryllium_tml<scalar> beryll;
0067
0068 static_assert(concepts::material_params<decltype(beryll)>);
0069 static_assert(concepts::homogeneous_material<decltype(beryll)>);
0070 static_assert(!concepts::surface_material<decltype(beryll)>);
0071 static_assert(concepts::volume_material<decltype(beryll)>);
0072 static_assert(!concepts::material_map<decltype(beryll)>);
0073
0074 EXPECT_NEAR(beryll.X0(), static_cast<scalar>(352.8 * unit<double>::mm), 1e-4);
0075 EXPECT_NEAR(beryll.L0(), static_cast<scalar>(407.0 * unit<double>::mm), tol);
0076 EXPECT_NEAR(beryll.Ar(), 9.012f, tol);
0077 EXPECT_NEAR(beryll.Z(), 4.0f, tol);
0078
0079
0080
0081 EXPECT_NEAR(beryll.molar_density(),
0082 static_cast<scalar>(1.848 / beryllium_tml<double>().Ar() *
0083 unit<double>::mol / unit<double>::cm3),
0084 tol);
0085
0086
0087 constexpr silicon_tml<scalar> silicon;
0088
0089 static_assert(concepts::material_params<decltype(silicon)>);
0090 static_assert(concepts::homogeneous_material<decltype(silicon)>);
0091 static_assert(!concepts::surface_material<decltype(silicon)>);
0092 static_assert(concepts::volume_material<decltype(silicon)>);
0093 static_assert(!concepts::material_map<decltype(silicon)>);
0094
0095 EXPECT_NEAR(silicon.X0(), static_cast<scalar>(95.7 * unit<double>::mm), 1e-5);
0096 EXPECT_NEAR(silicon.L0(), static_cast<scalar>(465.2 * unit<double>::mm),
0097 1e-4);
0098 EXPECT_NEAR(silicon.Ar(), 28.03f, tol);
0099 EXPECT_NEAR(silicon.Z(), 14.f, tol);
0100 EXPECT_NEAR(silicon.molar_density(),
0101 static_cast<scalar>(2.32 / silicon_tml<double>().Ar() *
0102 unit<double>::mol / unit<double>::cm3),
0103 tol);
0104 }
0105
0106 GTEST_TEST(detray_material, mixture) {
0107
0108
0109 constexpr oxygen_gas<scalar> pure_oxygen;
0110 constexpr mixture<scalar, oxygen_gas<scalar>,
0111 aluminium<scalar, std::ratio<0, 1>>>
0112 oxygen_mix;
0113
0114 static_assert(concepts::material_params<decltype(oxygen_mix)>);
0115 static_assert(concepts::homogeneous_material<decltype(oxygen_mix)>);
0116 static_assert(!concepts::surface_material<decltype(oxygen_mix)>);
0117 static_assert(concepts::volume_material<decltype(oxygen_mix)>);
0118 static_assert(!concepts::material_map<decltype(oxygen_mix)>);
0119
0120 EXPECT_NEAR(pure_oxygen.X0(), oxygen_mix.X0(), 0.02f);
0121 EXPECT_NEAR(pure_oxygen.L0(), oxygen_mix.L0(), tol);
0122 EXPECT_NEAR(pure_oxygen.Ar(), oxygen_mix.Ar(), tol);
0123 EXPECT_NEAR(pure_oxygen.Z(), oxygen_mix.Z(), tol);
0124 EXPECT_NEAR(pure_oxygen.mass_density(), oxygen_mix.mass_density(), tol);
0125 EXPECT_NEAR(pure_oxygen.molar_density(), oxygen_mix.molar_density(), tol);
0126
0127
0128 constexpr mixture<scalar, carbon_gas<scalar, std::ratio<0, 100>>,
0129 nitrogen_gas<scalar, std::ratio<76, 100>>,
0130 oxygen_gas<scalar, std::ratio<23, 100>>,
0131 argon_gas<scalar, std::ratio<1, 100>>>
0132 air_mix;
0133 constexpr air<scalar> pure_air;
0134
0135 static_assert(concepts::material_params<decltype(pure_air)>);
0136 static_assert(concepts::homogeneous_material<decltype(pure_air)>);
0137 static_assert(!concepts::surface_material<decltype(pure_air)>);
0138 static_assert(concepts::volume_material<decltype(pure_air)>);
0139 static_assert(!concepts::material_map<decltype(pure_air)>);
0140
0141 EXPECT_TRUE(std::abs(air_mix.X0() - pure_air.X0()) / pure_air.X0() < 0.01f);
0142 EXPECT_TRUE(std::abs(air_mix.L0() - pure_air.L0()) / pure_air.L0() < 0.01f);
0143 EXPECT_TRUE(std::abs(air_mix.Ar() - pure_air.Ar()) / pure_air.Ar() < 0.01f);
0144 EXPECT_TRUE(std::abs(air_mix.Z() - pure_air.Z()) / pure_air.Z() < 0.01f);
0145 EXPECT_TRUE(std::abs(air_mix.mass_density() - pure_air.mass_density()) /
0146 pure_air.mass_density() <
0147 0.01f);
0148
0149
0150 material_slab<scalar> slab1(air_mix, 5.5f);
0151 material_slab<scalar> slab2(pure_air, 2.3f);
0152 material_slab<scalar> slab3(oxygen_gas<scalar>(), 2.f);
0153
0154 std::vector<material_slab<scalar>> slab_vec;
0155
0156 slab_vec.push_back(slab1);
0157 slab_vec.push_back(slab2);
0158 slab_vec.push_back(slab3);
0159
0160 EXPECT_NEAR(slab_vec[0].thickness_in_X0(),
0161 slab1.thickness() / slab1.get_material().X0(), tol);
0162 EXPECT_NEAR(slab_vec[1].thickness_in_X0(),
0163 slab2.thickness() / slab2.get_material().X0(), tol);
0164 EXPECT_NEAR(slab_vec[2].thickness_in_X0(),
0165 slab3.thickness() / slab3.get_material().X0(), tol);
0166 }
0167
0168 GTEST_TEST(detray_material, mixture2) {
0169 constexpr mixture<scalar, silicon_with_ded<scalar, std::ratio<1, 3>>,
0170 cesium_iodide_with_ded<scalar, std::ratio<2, 3>>>
0171 mix;
0172
0173 static_assert(concepts::material_params<decltype(mix)>);
0174 static_assert(concepts::homogeneous_material<decltype(mix)>);
0175 static_assert(!concepts::surface_material<decltype(mix)>);
0176 static_assert(concepts::volume_material<decltype(mix)>);
0177 static_assert(!concepts::material_map<decltype(mix)>);
0178
0179
0180
0181 EXPECT_EQ(mix.has_density_effect_data(), false);
0182 EXPECT_EQ(mix.Ar(), silicon<scalar>().Ar() * 1.f / 3.f +
0183 cesium_iodide<scalar>().Ar() * 2.f / 3.f);
0184 EXPECT_EQ(mix.Z(), silicon<scalar>().Z() * 1.f / 3.f +
0185 cesium_iodide<scalar>().Z() * 2.f / 3.f);
0186 }
0187
0188
0189 GTEST_TEST(detray_material, material_slab) {
0190 constexpr material_slab<scalar> slab(oxygen_gas<scalar>(),
0191 2.f * unit<scalar>::mm);
0192
0193 static_assert(concepts::material_slab<decltype(slab)>);
0194 static_assert(concepts::homogeneous_material<decltype(slab)>);
0195 static_assert(concepts::surface_material<decltype(slab)>);
0196 static_assert(!concepts::volume_material<decltype(slab)>);
0197 static_assert(!concepts::material_map<decltype(slab)>);
0198
0199 const scalar cos_inc_ang{0.3f};
0200
0201 EXPECT_NEAR(slab.path_segment(cos_inc_ang), 2.f * unit<scalar>::mm / 0.3f,
0202 tol);
0203 EXPECT_NEAR(slab.path_segment_in_X0(cos_inc_ang),
0204 slab.path_segment(cos_inc_ang) / slab.get_material().X0(), tol);
0205 EXPECT_NEAR(slab.path_segment_in_L0(cos_inc_ang),
0206 slab.path_segment(cos_inc_ang) / slab.get_material().L0(), tol);
0207 }
0208
0209
0210 GTEST_TEST(detray_material, material_rod) {
0211
0212 constexpr material_rod<scalar> rod(oxygen_gas<scalar>(),
0213 1.f * unit<scalar>::mm);
0214
0215 static_assert(concepts::material_rod<decltype(rod)>);
0216 static_assert(concepts::homogeneous_material<decltype(rod)>);
0217 static_assert(concepts::surface_material<decltype(rod)>);
0218 static_assert(!concepts::volume_material<decltype(rod)>);
0219 static_assert(!concepts::material_map<decltype(rod)>);
0220
0221
0222 const vector3 x{1.f, 0.f, 0.f};
0223 const vector3 z{0.f, 0.f, 1.f};
0224 const vector3 t{0.f, 0.f, 0.f};
0225 const transform3 tf{t, vector::normalize(z), vector::normalize(x)};
0226
0227
0228 const point3 pos{-1.f / 6.f, -10.f, 0.f};
0229 const vector3 dir{0.f, 1.f, 3.f};
0230 const free_track_parameters<test_algebra> trk(pos, 0.f, dir, -1.f);
0231
0232
0233 const mask<line_circular, test_algebra> ln{
0234 0u, 1.f * unit<scalar>::mm, std::numeric_limits<scalar>::infinity()};
0235
0236 auto is = ray_intersector<line_circular, test_algebra, true>{}(
0237 detail::ray<test_algebra>(trk), surface_descriptor<>{}, ln, tf);
0238
0239 const scalar cos_inc_ang{std::abs(vector::dot(
0240 line2D<test_algebra>::normal(tf, is.local()), vector::normalize(dir)))};
0241 const scalar approach{is.local()[0]};
0242
0243 EXPECT_NEAR(rod.path_segment(cos_inc_ang, approach),
0244 2.f * std::sqrt(10.f - 10.f / 36.f), 1e-5f);
0245 EXPECT_NEAR(rod.path_segment_in_X0(cos_inc_ang, approach),
0246 rod.path_segment(cos_inc_ang, approach) / rod.get_material().X0(),
0247 tol);
0248 EXPECT_NEAR(rod.path_segment_in_L0(cos_inc_ang, approach),
0249 rod.path_segment(cos_inc_ang, approach) / rod.get_material().L0(),
0250 tol);
0251 }