/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus * * MAUS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MAUS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MAUS. If not, see . * */ #include "Geant4/G4Material.hh" #include "gtest/gtest.h" #include "src/legacy/Config/MiceModule.hh" #include "src/common_cpp/Globals/GlobalsManager.hh" #include "src/common_cpp/Recon/Global/MaterialModelDynamic.hh" #include "src/common_cpp/Recon/Global/MaterialModelAxialLookup.hh" namespace MAUS { class MaterialModelTest : public ::testing::Test { protected: MaterialModelTest() { std::string mod_path = getenv("MAUS_ROOT_DIR"); if (!is_setup) { // looks like there is no class setup mod_path += "/tests/cpp_unit/Recon/Global/TestGeometries/"; MiceModule* materials = new MiceModule(mod_path+"MaterialModelTest.dat"); GlobalsManager::SetMonteCarloMiceModules(materials); is_setup = true; } auto nist_t = {60., 70., 80., 90., 100., 120., 140., 170., 200.}; _nist_energy = std::vector(nist_t); MaterialModel::EnableMaterial("Galactic"); MaterialModel::EnableMaterial("lH2"); MaterialModel::EnableMaterial("POLYSTYRENE"); MaterialModel::EnableMaterial("LITHIUM_HYDRIDE"); MaterialModel::EnableMaterial("MICE_LITHIUM_HYDRIDE"); MaterialModelAxialLookup::SetZTolerance(0.1); } virtual ~MaterialModelTest() {} virtual void SetUp() {} virtual void TearDown() {} double _mass = 105.658; std::vector _nist_energy; static bool is_setup; }; bool MaterialModelTest::is_setup = false; TEST_F(MaterialModelTest, d2EdEdxTest) { std::cerr << "Need test here" << std::endl; } TEST_F(MaterialModelTest, estrag2Test) { std::cerr << "Need test here" << std::endl; } TEST_F(MaterialModelTest, scatPolystyrene) { MaterialModelDynamic material(0., 0., 6000.); auto p_auto = {172., 200., 240.}; // MICE LiH, PDG results from Table 1 MICE Note 497 auto scat_auto = {23.2, 19.3, 15.5}; std::vector mice_scat(scat_auto); std::vector mice_p(p_auto); std::cerr << "p calc theta ref theta" << std::endl; for (size_t i = 0; i < mice_p.size(); ++i) { double energy = sqrt(_mass*_mass+mice_p[i]*mice_p[i]); double scat = sqrt(material.dtheta2dx(energy, _mass, 1.)*65.)*1e3; std::cerr << mice_p[i] << " " << scat << " " << mice_scat[i] << std::endl; EXPECT_LT(fabs(scat-mice_scat[i]), scat/10.); // good to 10 %? } } TEST_F(MaterialModelTest, dEdxHydrogen) { MaterialModelDynamic material(0., 0., 0.); auto dedx_auto = {5.409, 5.097, 4.870, 4.699, 4.568, 4.385, 4.267, 4.161, 4.104}; // MeV cm^2/g std::vector pdg_dedx(dedx_auto); double pdg_density = 0.0708; // g/cm^3 std::cerr << "E calc dEdx ref dEdx" << std::endl; for (size_t i = 0; i < _nist_energy.size(); ++i) { double energy = _nist_energy[i] + _mass; double dedx = material.dEdx(energy, _mass, 1.); double ref_dedx = -pdg_dedx[i]*pdg_density/cm; std::cerr << _nist_energy[i] << " " << dedx << " " << ref_dedx << std::endl; EXPECT_LT(fabs(dedx-ref_dedx), fabs(dedx)/10.); // good to 10 %? } } TEST_F(MaterialModelTest, dEdxPolystyrene) { MaterialModelDynamic material(0., 0., 2000.); auto dedx_auto = {2.612, 2.466, 2.359, 2.276, 2.211, 2.118, 2.058, 2.003, 1.971}; // MeV cm^2/g std::vector pdg_dedx(dedx_auto); double pdg_density = 1.060; // g/cm^3 std::cerr << "E calc dEdx ref dEdx" << std::endl; for (size_t i = 0; i < _nist_energy.size(); ++i) { double energy = _nist_energy[i] + _mass; double dedx = material.dEdx(energy, _mass, 1.); double ref_dedx = -pdg_dedx[i]*pdg_density/cm; std::cerr << _nist_energy[i] << " " << dedx << " " << ref_dedx << std::endl; EXPECT_LT(fabs(dedx-ref_dedx), fabs(dedx)/10.); // good to 10 %? } } TEST_F(MaterialModelTest, dEdxDisabled) { MaterialModel::DisableMaterial("lH2"); MaterialModelDynamic material(0., 0., 0.); EXPECT_NEAR(material.dEdx(226., _mass, 1.), 0., 1e-9); MaterialModel::EnableMaterial("lH2"); } ////////////////////////////// DYNAMIC /////////////////////////////// TEST_F(MaterialModelTest, DynamicConstructorsEtc) { MaterialModelDynamic test; G4Material* null = NULL; // default ctor EXPECT_EQ(test.GetMaterial(), null); test.SetMaterial(1000., 0., 2000.); // galactic (horizontally displaced from lih) // ctor with position MaterialModelDynamic test2(1000., 0., 2000.); // galactic (horizontally displaced from lih) EXPECT_EQ(test2.GetMaterial(), test.GetMaterial()); // copy ctor MaterialModelDynamic test3(test); EXPECT_EQ(test3.GetMaterial(), test.GetMaterial()); // clone function Not implemented // MaterialModelDynamic* test4 = test.Clone(); // EXPECT_EQ(test4->GetMaterial(), test.GetMaterial()); // delete test4; // assignment operator MaterialModelDynamic test5; EXPECT_EQ(test5.GetMaterial(), null); test5 = test; EXPECT_EQ(test5.GetMaterial(), test.GetMaterial()); } TEST_F(MaterialModelTest, DynamicSetMaterial) { MaterialModelDynamic test; G4Material* null = NULL; // boundaries of polystyrene test.SetMaterial(0., 0., 1749.998); ASSERT_NE(test.GetMaterial(), null); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_Galactic"); test.SetMaterial(0., 0., 1750.002); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_POLYSTYRENE"); test.SetMaterial(251., 0., 1751); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_Galactic"); test.SetMaterial(0., 251., 1751.); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_Galactic"); test.SetMaterial(249., 0., 1751.); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_POLYSTYRENE"); test.SetMaterial(0., 249., 1751.); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_POLYSTYRENE"); } ////////////////////////////// AXIAL /////////////////////////////// TEST_F(MaterialModelTest, GetSetTolerance) { MaterialModelAxialLookup::SetZTolerance(0.1); EXPECT_NEAR(MaterialModelAxialLookup::GetZTolerance(), 0.1, 1e-9); MaterialModelAxialLookup::SetZTolerance(0.01); EXPECT_NEAR(MaterialModelAxialLookup::GetZTolerance(), 0.01, 1e-9); MaterialModelAxialLookup::SetZTolerance(0.001); EXPECT_NEAR(MaterialModelAxialLookup::GetZTolerance(), 0.001, 1e-9); } TEST_F(MaterialModelTest, AxialLookupGetBounds) { MaterialModelAxialLookup::BuildLookupTable(-1000., 4000.); EXPECT_TRUE(MaterialModelAxialLookup::IsReady()); MaterialModelAxialLookup::PrintLookupTable(std::cerr); double lower, upper; MaterialModelAxialLookup::GetBounds(-1200., lower, upper); EXPECT_LT(lower, -1e9); // <-- std::numeric_limits::lowest() EXPECT_NEAR(upper, -1000., 0.1); MaterialModelAxialLookup::GetBounds(-500., lower, upper); EXPECT_NEAR(lower, -1000., 0.1); EXPECT_NEAR(upper, -250., 0.1); MaterialModelAxialLookup::GetBounds(3500., lower, upper); EXPECT_NEAR(lower, 2250., 0.1); EXPECT_NEAR(upper, 3750., 0.1); MaterialModelAxialLookup::GetBounds(3900., lower, upper); EXPECT_NEAR(lower, 3750., 0.1); EXPECT_GT(upper, 1e9); // <-- std::numeric_limits::max() } TEST_F(MaterialModelTest, AxialConstructorsEtc) { MaterialModelAxialLookup test; G4Material* null = NULL; // default ctor EXPECT_EQ(test.GetMaterial(), null); test.SetMaterial(0., 0., 1749.998); // ctor with position MaterialModelAxialLookup test2(0., 0., 1749.998); EXPECT_EQ(test2.GetMaterial(), test.GetMaterial()); // copy ctor MaterialModelAxialLookup test3(test); EXPECT_EQ(test3.GetMaterial(), test.GetMaterial()); // clone function Not implemented // MaterialModelAxialLookup* test4 = test.Clone(); // EXPECT_EQ(test4->GetMaterial(), test.GetMaterial()); // delete test4; // assignment operator MaterialModelAxialLookup test5; EXPECT_EQ(test5.GetMaterial(), null); test5 = test; EXPECT_EQ(test5.GetMaterial(), test.GetMaterial()); } TEST_F(MaterialModelTest, EnableDisableMaterial) { MaterialModelAxialLookup::BuildLookupTable(-1000., 4000.); MaterialModelAxialLookup test_axial; MaterialModelDynamic test_dyn; G4Material* null = NULL; // before lower bound; should default to first material (G4_Galactic) test_dyn.SetMaterial(0., 0., 0.); test_axial.SetMaterial(0., 0., 0.); EXPECT_NE(test_dyn.GetMaterial(), null); EXPECT_NE(test_axial.GetMaterial(), null); MaterialModel::DisableMaterial("lH2"); test_dyn.SetMaterial(0., 0., 0.); test_axial.SetMaterial(0., 0., 0.); EXPECT_EQ(test_dyn.GetMaterial(), null); EXPECT_EQ(test_axial.GetMaterial(), null); MaterialModel::EnableMaterial("lH2"); test_dyn.SetMaterial(0., 0., 0.); test_axial.SetMaterial(0., 0., 0.); EXPECT_NE(test_dyn.GetMaterial(), null); EXPECT_NE(test_axial.GetMaterial(), null); } TEST_F(MaterialModelTest, AxialLookupSetMaterial) { MaterialModelAxialLookup::BuildLookupTable(1000., 4000.); MaterialModelAxialLookup test; G4Material* null = NULL; // before lower bound; should default to first material (G4_Galactic) test.SetMaterial(0., 0., 0.); ASSERT_NE(test.GetMaterial(), null); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_Galactic"); // boundary to polystyrene; nb tolerance is set to 0.1 mm test.SetMaterial(0., 0., 1749.8); ASSERT_NE(test.GetMaterial(), null); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_Galactic"); test.SetMaterial(0., 0., 1750.2); ASSERT_NE(test.GetMaterial(), null); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_POLYSTYRENE"); // boundary to LiH test.SetMaterial(0., 0., 3749.8); ASSERT_NE(test.GetMaterial(), null); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_Galactic"); test.SetMaterial(0., 0., 3750.2); ASSERT_NE(test.GetMaterial(), null); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_LITHIUM_HYDRIDE"); // after upper bound; should default to last material (LiH) test.SetMaterial(0., 0., 5000.); ASSERT_NE(test.GetMaterial(), null); EXPECT_EQ(test.GetMaterial()->GetName(), "G4_LITHIUM_HYDRIDE"); } }