// Copyright 2011 Chris Rogers // // This file is a part of 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 in the doc folder. If not, see // . #include "gtest/gtest.h" #include "Geant4/G4RunManager.hh" #include "Geant4/G4SDManager.hh" #include "src/common_cpp/Utils/Globals.hh" #include "src/common_cpp/Utils/JsonWrapper.hh" #include "src/common_cpp/Simulation/MAUSPhysicsList.hh" #include "src/common_cpp/Simulation/MAUSGeant4Manager.hh" using namespace MAUS; namespace { // I think all I can do here is test that members were initialised to something TEST(MAUSGeant4ManagerTest, GetSetTest) { MAUSGeant4Manager* g4man = MAUSGeant4Manager::GetInstance(); ASSERT_TRUE(g4man != NULL); ASSERT_TRUE(g4man->GetRunManager() != NULL); ASSERT_TRUE(g4man->GetStepping() != NULL); ASSERT_TRUE(g4man->GetPrimaryGenerator() != NULL); ASSERT_TRUE(g4man->GetGeometry() != NULL); ASSERT_TRUE(g4man->GetTracking() != NULL); ASSERT_TRUE(g4man->GetPhysicsList() != NULL); ASSERT_TRUE(g4man->GetVirtualPlanes() != NULL); ASSERT_TRUE(g4man->GetEventAction() != NULL); } TEST(MAUSGeant4ManagerTest, GetReferenceParticleTest) { Json::Value* conf = MAUS::Globals::GetInstance()->GetConfigurationCards(); Json::Value pos(Json::objectValue); pos["x"] = pos["y"] = pos["z"] = 1.; // read of json value is dealt with elsewhere (*conf)["simulation_reference_particle"]["particle_id"] = Json::Value(13); (*conf)["simulation_reference_particle"]["position"] = pos; (*conf)["simulation_reference_particle"]["momentum"] = pos; (*conf)["simulation_reference_particle"]["energy"] = 200.; (*conf)["simulation_reference_particle"]["time"] = -2.; (*conf)["simulation_reference_particle"]["random_seed"] = Json::Int(2); EXPECT_EQ(MAUSGeant4Manager::GetInstance()->GetReferenceParticle().pid, 13); // check that we set mass shell condition (details elsewhere) EXPECT_EQ(MAUSGeant4Manager::GetInstance()->GetReferenceParticle().px, MAUSGeant4Manager::GetInstance()->GetReferenceParticle().pz); EXPECT_GT(MAUSGeant4Manager::GetInstance()->GetReferenceParticle().px, MAUSGeant4Manager::GetInstance()->GetReferenceParticle().x); } TEST(MAUSGeant4ManagerTest, SetPhasesTest) { MAUSGeant4Manager::GetInstance()->SetPhases(); // just check it runs } TEST(MAUSGeant4ManagerTest, RunParticlePGTest) { MAUS::MAUSPrimaryGeneratorAction::PGParticle part_in; part_in.x = 1.; part_in.y = 2.; part_in.z = 3.; part_in.time = 4.; part_in.px = 5.; part_in.py = 6.; part_in.pz = 100.; part_in.energy = 200.; part_in.seed = 10; part_in.pid = -11; // e- so no decays etc // test that track is set ok Json::Value val = MAUSGeant4Manager::GetInstance()->RunParticle(part_in); ASSERT_TRUE(val["tracks"].isArray()); ASSERT_TRUE(val["tracks"][Json::Value::UInt(0)].isObject()); Json::Value track = val["tracks"][Json::Value::UInt(0)]; EXPECT_NEAR(track["initial_position"]["x"].asDouble(), 1., 1e-9); EXPECT_NEAR(track["initial_position"]["y"].asDouble(), 2., 1e-9); EXPECT_NEAR(track["initial_position"]["z"].asDouble(), 3., 1e-9); // test that tracks can be switched on and off MAUSGeant4Manager::GetInstance()->GetTracking()->SetWillKeepTracks(false); val = MAUSGeant4Manager::GetInstance()->RunParticle(part_in); EXPECT_TRUE(val["tracks"].isNull()); MAUSGeant4Manager::GetInstance()->GetTracking()->SetWillKeepTracks(true); val = MAUSGeant4Manager::GetInstance()->RunParticle(part_in); EXPECT_EQ(val["tracks"].type(), Json::arrayValue); // test that steps can be switched on and off MAUSGeant4Manager::GetInstance()->GetStepping()->SetWillKeepSteps(false); val = MAUSGeant4Manager::GetInstance()->RunParticle(part_in); EXPECT_TRUE(val["tracks"][Json::Value::UInt(0)]["steps"].isNull()); MAUSGeant4Manager::GetInstance()->GetStepping()->SetWillKeepSteps(true); val = MAUSGeant4Manager::GetInstance()->RunParticle(part_in); EXPECT_EQ(val["tracks"][Json::Value::UInt(0)]["steps"].type(), Json::arrayValue); // test that virtuals can be switched on and off MAUSGeant4Manager::GetInstance()-> GetVirtualPlanes()->SetWillUseVirtualPlanes(false); val = MAUSGeant4Manager::GetInstance()->RunParticle(part_in); EXPECT_TRUE(val["virtual_hits"].isNull()); MAUSGeant4Manager::GetInstance()-> GetVirtualPlanes()->SetWillUseVirtualPlanes(true); val = MAUSGeant4Manager::GetInstance()->RunParticle(part_in); EXPECT_EQ(val["virtual_hits"].type(), Json::arrayValue); } TEST(MAUSGeant4ManagerTest, RunParticleJsonTest) { std::string pg_string = std::string("{\"primary\":{")+ std::string("\"position\":{\"x\":1.0, \"y\":2.0, \"z\":3.0}, ")+ std::string("\"momentum\":{\"x\":0.0, \"y\":0.0, \"z\":1.0}, ")+ std::string("\"spin\":{\"x\":0.0, \"y\":0.0, \"z\":1.0}, ")+ std::string("\"particle_id\":-13, \"energy\":226.0, ")+ std::string("\"time\":0.0, \"random_seed\":10}}"); Json::Value pg = JsonWrapper::StringToJson(pg_string); MAUSGeant4Manager::GetInstance()->GetStepping()->SetWillKeepSteps(false); Json::Value out = MAUSGeant4Manager::GetInstance()->RunParticle(pg); Json::Value track = out["tracks"][Json::Value::UInt(0)]; ASSERT_TRUE(track["initial_position"]["x"].isDouble()); EXPECT_NEAR(track["initial_position"]["x"].asDouble(), 1., 1e-9); EXPECT_NEAR(track["initial_position"]["y"].asDouble(), 2., 1e-9); EXPECT_NEAR(track["initial_position"]["z"].asDouble(), 3., 1e-9); ASSERT_TRUE(out["primary"]["position"]["x"].isDouble()); EXPECT_NEAR(out["primary"]["position"]["x"].asDouble(), 1., 1e-9); EXPECT_NEAR(out["primary"]["position"]["y"].asDouble(), 2., 1e-9); EXPECT_NEAR(out["primary"]["position"]["z"].asDouble(), 3., 1e-9); } TEST(MAUSGeant4ManagerTest, RunManyParticlesTest) { std::string pg_string = std::string("{\"primary\":{")+ std::string("\"position\":{\"x\":1.0, \"y\":2.0, \"z\":3.0}, ")+ std::string("\"momentum\":{\"x\":0.0, \"y\":0.0, \"z\":1.0}, ")+ std::string("\"spin\":{\"x\":0.0, \"y\":0.0, \"z\":1.0}, ")+ std::string("\"particle_id\":-13, \"energy\":226.0, ")+ std::string("\"time\":0.0, \"random_seed\":10}}"); std::string pg_array_string = "["+pg_string+","+pg_string+","+pg_string+"]"; Json::Value pg = JsonWrapper::StringToJson(pg_array_string); MAUSGeant4Manager::GetInstance()->GetStepping()->SetWillKeepSteps(false); Json::Value out = MAUSGeant4Manager::GetInstance()->RunManyParticles(pg); for (int i = 0; i < int(out.size()); ++i) { Json::Value track = out[i]["tracks"][Json::Value::UInt(0)]; ASSERT_TRUE(out.isArray()); ASSERT_TRUE(out[i].isObject()); ASSERT_TRUE(out[i]["tracks"].isArray()); ASSERT_TRUE(out[i]["tracks"][Json::Value::UInt(0)].isObject()); ASSERT_TRUE(track["initial_position"]["x"].isDouble()); EXPECT_NEAR(track["initial_position"]["x"].asDouble(), 1., 1e-9); EXPECT_NEAR(track["initial_position"]["y"].asDouble(), 2., 1e-9); EXPECT_NEAR(track["initial_position"]["z"].asDouble(), 3., 1e-9); ASSERT_TRUE(out[i]["primary"].isObject()); ASSERT_TRUE(out[i]["primary"]["position"]["x"].isDouble()); EXPECT_NEAR(out[i]["primary"]["position"]["x"].asDouble(), 1., 1e-9); EXPECT_NEAR(out[i]["primary"]["position"]["y"].asDouble(), 2., 1e-9); EXPECT_NEAR(out[i]["primary"]["position"]["z"].asDouble(), 3., 1e-9); } } #include "src/legacy/Interface/Squeak.hh" double get_energy(Json::Value virtual_hit) { double m =virtual_hit["mass"].asDouble(); double px =virtual_hit["momentum"]["x"].asDouble(); double py =virtual_hit["momentum"]["y"].asDouble(); double pz =virtual_hit["momentum"]["z"].asDouble(); return sqrt(m*m+px*px+py*py+pz*pz); } /* Rogers - this test fails for Geant4 knows what reason... works locally... humm TEST(MAUSGeant4ManagerTest, ScatteringOffMaterialTest) { MAUS::MAUSPrimaryGeneratorAction::PGParticle part_in; part_in.x = 0.; part_in.y = 0.; part_in.z = 1000.; part_in.time = 0.; part_in.px = 0.; part_in.py = 0.; part_in.pz = 1.; // just a direction part_in.energy = 5000.; part_in.seed = 10; part_in.pid = -13; MAUS::MAUSGeant4Manager * const simulator = MAUS::MAUSGeant4Manager::GetInstance(); MAUS::VirtualPlaneManager const * const old_virtual_planes = simulator->GetVirtualPlanes(); MAUS::VirtualPlaneManager * const virtual_planes = new MAUS::VirtualPlaneManager; MAUS::VirtualPlane end_plane = MAUS::VirtualPlane::BuildVirtualPlane( CLHEP::HepRotation(), CLHEP::Hep3Vector(0., 0., 2000.), -1, true, 2000., BTTracker::z, MAUS::VirtualPlane::ignore, false); virtual_planes->AddPlane(new MAUS::VirtualPlane(end_plane), NULL); simulator->SetVirtualPlanes(virtual_planes); simulator->GetStepping()->SetWillKeepSteps(false); // mu+, mu-, e+, e0, pi-, pi+, p, 4He, K+, K- int pid_list[] = {-13, 13, -11, 11, -211, 211, 2212, 1000020040, 321, -321}; // could add neutrons, antiprotons (though not for MICE) for (size_t pid_index = 0; pid_index < 10; ++pid_index) { part_in.pid = pid_list[pid_index]; Json::Value hits(Json::arrayValue); hits.append(simulator->RunParticle(part_in)["virtual_hits"]); // move now into lH2 part_in.z = 0.; hits.append(simulator->RunParticle(part_in)["virtual_hits"]); simulator->GetPhysicsList()->BeginOfReferenceParticleAction(); hits.append(simulator->RunParticle(part_in)["virtual_hits"]); simulator->GetPhysicsList()->BeginOfRunAction(); hits.append(simulator->RunParticle(part_in)["virtual_hits"]); part_in.z = 1000.; for (size_t i = 0; i < 4; ++i) ASSERT_EQ(1u, hits[i].size()); // full physics and vacuum EXPECT_NEAR(0., hits[0u][0u]["momentum"]["x"].asDouble(), 1.0e-3) << "Failed with pid " << part_in.pid; EXPECT_NEAR(0., hits[0u][0u]["momentum"]["y"].asDouble(), 1.0e-3) << "Failed with pid " << part_in.pid; EXPECT_NEAR(5000., get_energy(hits[0u][0u]), 1.0e-3) << "Failed with pid " << part_in.pid; // full physics and lh2 EXPECT_GE(fabs(0.-hits[1u][0u]["momentum"]["x"].asDouble()), 1.0e-3) << "Failed with pid " << part_in.pid; EXPECT_GE(fabs(0.-hits[1u][0u]["momentum"]["y"].asDouble()), 1.0e-3) << "Failed with pid " << part_in.pid; EXPECT_GE(fabs(5000.-get_energy(hits[1u][0u])), 1.0e-3) << "Failed with pid " << part_in.pid; // reference physics (mean dedx and no stochastics) EXPECT_NEAR(0., hits[2u][0u]["momentum"]["x"].asDouble(), 1.0e-3) << "Failed with pid " << part_in.pid; EXPECT_NEAR(0., hits[2u][0u]["momentum"]["y"].asDouble(), 1.0e-3) << "Failed with pid " << part_in.pid; EXPECT_GE(fabs(5000.-get_energy(hits[2u][0u])), 1.0e-3) << "Failed with pid " << part_in.pid; // full physics and lh2 EXPECT_GE(fabs(0.-hits[3u][0u]["momentum"]["x"].asDouble()), 1.0e-3) << "Failed with pid " << part_in.pid; EXPECT_GE(fabs(0.-hits[3u][0u]["momentum"]["y"].asDouble()), 1.0e-3) << "Failed with pid " << part_in.pid; EXPECT_GE(fabs(5000.-get_energy(hits[3u][0u])), 1.0e-3) << "Failed with pid " << part_in.pid; } simulator->SetVirtualPlanes( const_cast(old_virtual_planes)); delete virtual_planes; } */ }