geant events for multiple scattering

This commit is contained in:
AndreaRigoni
2026-03-14 23:33:31 +00:00
parent 692cdf7ae3
commit c63a1ae047
18 changed files with 681 additions and 90 deletions

View File

@@ -1,6 +1,10 @@
#include "Geant/Solid.h"
#include "HEP/Geant/GeantEvent.h"
#include "HEP/Geant/Scene.h"
#include "HEP/Geant/EmitterPrimary.hh"
#include "Math/ContainerBox.h"
#include "Math/TriangleMesh.h"
#include "Math/Dense.h"
#include "testing-prototype.h"
#include <Geant4/G4Material.hh>
#include <Geant4/G4NistManager.hh>
@@ -13,59 +17,73 @@ using namespace uLib;
int main() {
BEGIN_TESTING(Geant Event);
// Test Solid initialization and NIST material //
// Test: Scene with iron cube in air, launch muons, collect events //
{
Geant::Solid solid("test_solid");
TEST1(solid.GetLogical() != nullptr);
solid.SetNistMaterial("G4_AIR");
TEST1(solid.GetMaterial() != nullptr);
TEST1(solid.GetMaterial()->GetName() == "G4_AIR");
}
// 1. Create world box (air, 30m x 30m x 30m)
ContainerBox world_box(Vector3f(30000, 30000, 30000)); // mm
Geant::Scene scene;
scene.ConstructWorldBox(&world_box, "G4_AIR");
// Test TessellatedSolid with a simple mesh //
{
Geant::TessellatedSolid tsolid("test_tessellated");
TEST1(tsolid.GetLogical() != nullptr);
TEST1(tsolid.GetSolid() != nullptr);
// 2. Create iron cube (1m x 1m x 1m) at center
ContainerBox iron_box(Vector3f(1000, 1000, 1000)); // mm
Geant::BoxSolid *iron_cube = new Geant::BoxSolid("IronCube", &iron_box);
iron_cube->SetNistMaterial("G4_Fe");
iron_cube->Update(); // apply dimensions
scene.AddSolid(iron_cube);
// cube mesh //
TriangleMesh mesh;
mesh.AddPoint(Vector3f(0,0,0));
mesh.AddPoint(Vector3f(1,0,0));
mesh.AddPoint(Vector3f(0,1,0));
mesh.AddPoint(Vector3f(1,1,0));
mesh.AddPoint(Vector3f(0,0,1));
mesh.AddPoint(Vector3f(1,0,1));
mesh.AddPoint(Vector3f(0,1,1));
mesh.AddPoint(Vector3f(1,1,1));
// create triangles (consistent outward winding) //
// bottom (z=0)
mesh.AddTriangle(Vector3i(0,2,3));
mesh.AddTriangle(Vector3i(0,3,1));
// top (z=1)
mesh.AddTriangle(Vector3i(4,5,7));
mesh.AddTriangle(Vector3i(4,7,6));
// left (x=0)
mesh.AddTriangle(Vector3i(0,4,6));
mesh.AddTriangle(Vector3i(0,6,2));
// right (x=1)
mesh.AddTriangle(Vector3i(1,3,7));
mesh.AddTriangle(Vector3i(1,7,5));
// front (y=0)
mesh.AddTriangle(Vector3i(0,1,5));
mesh.AddTriangle(Vector3i(0,5,4));
// back (y=1)
mesh.AddTriangle(Vector3i(2,6,7));
mesh.AddTriangle(Vector3i(2,7,3));
// 3. Set up emitter (default: mu- at 1 GeV, from z=+10m downward)
Geant::EmitterPrimary *emitter = new Geant::EmitterPrimary();
scene.SetEmitter(emitter);
// 4. Initialize Geant4
scene.Initialize();
// 5. Run simulation: 10 muons
int nEvents = 10;
Vector<Geant::GeantEvent> results;
scene.RunSimulation(nEvents, results);
tsolid.SetMesh(mesh);
// GeantEvent geant_event;
// 6. Check results
printf(" Collected %zu events\n", results.size());
TEST1(results.size() > 0);
for (size_t i = 0; i < results.size(); ++i) {
const Geant::GeantEvent &ev = results[i];
bool hitIron = false;
for (const auto &d : ev.Path()) {
if (d.SolidName() == "IronCube") {
hitIron = true;
break;
}
}
printf(" Event %d: momentum=%.1f MeV, path steps=%zu, hitIron=%s\n",
ev.GetEventID(),
ev.GetMomentum(),
ev.Path().size(),
hitIron ? "YES" : "NO");
// Each event should have at least one step
TEST1(ev.Path().size() > 0);
// Print first few deltas
const auto &path = ev.Path();
for (size_t j = 0; j < path.size() && j < 5; ++j) {
const auto &d = path[j];
printf(" Delta[%zu]: solid=%s len=%.2f mm, p=%.1f MeV, "
"dir=(%.3f, %.3f, %.3f)\n",
j,
d.SolidName().c_str(),
d.GetLength(),
d.GetMomentum(),
d.Direction()(0),
d.Direction()(1),
d.Direction()(2));
}
if (path.size() > 5) {
printf(" ... (%zu more deltas)\n", path.size() - 5);
}
}
}
END_TESTING