add detector simulation
This commit is contained in:
@@ -65,7 +65,9 @@ public:
|
|||||||
HLine3f worldPlane;
|
HLine3f worldPlane;
|
||||||
Matrix4f M = this->GetWorldMatrix();
|
Matrix4f M = this->GetWorldMatrix();
|
||||||
worldPlane.origin = M * m_ProjectionPlane.origin;
|
worldPlane.origin = M * m_ProjectionPlane.origin;
|
||||||
worldPlane.direction = M * m_ProjectionPlane.direction;
|
HVector3f dirNorm = M * m_ProjectionPlane.direction;
|
||||||
|
dirNorm.normalize(); // Normalize for consistent dot products
|
||||||
|
worldPlane.direction = dirNorm;
|
||||||
return worldPlane;
|
return worldPlane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,37 +5,26 @@
|
|||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Geant {
|
namespace Geant {
|
||||||
|
|
||||||
ActionInitialization::ActionInitialization(EmitterPrimary *emitter,
|
ActionInitialization::ActionInitialization(EmitterPrimary *emitter, SimulationContext *context)
|
||||||
Vector<GeantEvent> *output,
|
|
||||||
int verbosity)
|
|
||||||
: G4VUserActionInitialization(),
|
: G4VUserActionInitialization(),
|
||||||
m_Emitter(emitter),
|
m_Emitter(emitter),
|
||||||
m_Output(output),
|
m_Context(context)
|
||||||
m_Verbosity(verbosity)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ActionInitialization::~ActionInitialization() {}
|
ActionInitialization::~ActionInitialization() {}
|
||||||
|
|
||||||
void ActionInitialization::BuildForMaster() const {
|
void ActionInitialization::BuildForMaster() const {}
|
||||||
// Master thread: no per-event actions needed
|
|
||||||
}
|
|
||||||
|
|
||||||
void ActionInitialization::Build() const {
|
void ActionInitialization::Build() const {
|
||||||
// Register the primary generator
|
|
||||||
if (m_Emitter) {
|
if (m_Emitter) {
|
||||||
SetUserAction(m_Emitter->Clone());
|
SetUserAction(m_Emitter->Clone());
|
||||||
} else {
|
} else {
|
||||||
// Fallback: default EmitterPrimary
|
|
||||||
SetUserAction(new EmitterPrimary());
|
SetUserAction(new EmitterPrimary());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register actions
|
SteppingAction *sa = new SteppingAction(m_Context);
|
||||||
if (m_Output) {
|
|
||||||
SteppingAction *sa = new SteppingAction(m_Output);
|
|
||||||
sa->SetVerbosity(m_Verbosity);
|
|
||||||
SetUserAction(static_cast<G4UserSteppingAction*>(sa));
|
SetUserAction(static_cast<G4UserSteppingAction*>(sa));
|
||||||
SetUserAction(static_cast<G4UserEventAction*>(sa));
|
SetUserAction(static_cast<G4UserEventAction*>(sa));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Geant
|
} // namespace Geant
|
||||||
|
|||||||
@@ -2,35 +2,24 @@
|
|||||||
#define ActionInitialization_h
|
#define ActionInitialization_h
|
||||||
|
|
||||||
#include "G4VUserActionInitialization.hh"
|
#include "G4VUserActionInitialization.hh"
|
||||||
#include "Core/Vector.h"
|
#include "SimulationContext.h"
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Geant {
|
namespace Geant {
|
||||||
|
|
||||||
class EmitterPrimary;
|
class EmitterPrimary;
|
||||||
class GeantEvent;
|
|
||||||
|
|
||||||
class ActionInitialization : public G4VUserActionInitialization {
|
class ActionInitialization : public G4VUserActionInitialization {
|
||||||
public:
|
public:
|
||||||
/// @param emitter the primary generator to use (owned by caller)
|
ActionInitialization(EmitterPrimary *emitter, SimulationContext *context);
|
||||||
/// @param output pointer to the results vector (owned by caller)
|
|
||||||
ActionInitialization(EmitterPrimary *emitter = nullptr,
|
|
||||||
Vector<GeantEvent> *output = nullptr,
|
|
||||||
int verbosity = 0);
|
|
||||||
~ActionInitialization();
|
~ActionInitialization();
|
||||||
|
|
||||||
void SetVerbosity(int level) { m_Verbosity = level; }
|
virtual void BuildForMaster() const override;
|
||||||
|
virtual void Build() const override;
|
||||||
// Metodo chiamato solo dal thread principale (Master)
|
|
||||||
virtual void BuildForMaster() const;
|
|
||||||
|
|
||||||
// Metodo chiamato dai thread di lavoro (Worker) o in modalità sequenziale
|
|
||||||
virtual void Build() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EmitterPrimary *m_Emitter;
|
EmitterPrimary *m_Emitter;
|
||||||
Vector<GeantEvent> *m_Output;
|
SimulationContext *m_Context;
|
||||||
int m_Verbosity = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Geant
|
} // namespace Geant
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ set(HEADERS
|
|||||||
PhysicsList.hh
|
PhysicsList.hh
|
||||||
ActionInitialization.hh
|
ActionInitialization.hh
|
||||||
SteppingAction.hh
|
SteppingAction.hh
|
||||||
|
SimulationContext.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
|||||||
43
src/HEP/Geant/DetectorActionInitialization.cpp
Normal file
43
src/HEP/Geant/DetectorActionInitialization.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include "DetectorActionInitialization.hh"
|
||||||
|
#include "EmitterPrimary.hh"
|
||||||
|
#include "DetectorSteppingAction.hh"
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Geant {
|
||||||
|
|
||||||
|
DetectorActionInitialization::DetectorActionInitialization(EmitterPrimary *emitter,
|
||||||
|
Vector<MuonEvent> *output,
|
||||||
|
const Vector<HLine3f> &planes,
|
||||||
|
int verbosity)
|
||||||
|
: G4VUserActionInitialization(),
|
||||||
|
m_Emitter(emitter),
|
||||||
|
m_Output(output),
|
||||||
|
m_Planes(planes),
|
||||||
|
m_Verbosity(verbosity)
|
||||||
|
{}
|
||||||
|
|
||||||
|
DetectorActionInitialization::~DetectorActionInitialization() {}
|
||||||
|
|
||||||
|
void DetectorActionInitialization::BuildForMaster() const {}
|
||||||
|
|
||||||
|
void DetectorActionInitialization::Build() const {
|
||||||
|
if (m_Verbosity > 0) {
|
||||||
|
std::cout << "[Geant] Worker thread Building actions... Output ptr: " << m_Output
|
||||||
|
<< ", Planes count: " << m_Planes.size() << std::endl;
|
||||||
|
}
|
||||||
|
if (m_Emitter) {
|
||||||
|
SetUserAction(m_Emitter->Clone());
|
||||||
|
} else {
|
||||||
|
SetUserAction(new EmitterPrimary());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Output) {
|
||||||
|
DetectorSteppingAction *sa = new DetectorSteppingAction(m_Output, m_Planes);
|
||||||
|
sa->SetVerbosity(m_Verbosity);
|
||||||
|
SetUserAction(static_cast<G4UserSteppingAction*>(sa));
|
||||||
|
SetUserAction(static_cast<G4UserEventAction*>(sa));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Geant
|
||||||
|
} // namespace uLib
|
||||||
35
src/HEP/Geant/DetectorActionInitialization.hh
Normal file
35
src/HEP/Geant/DetectorActionInitialization.hh
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef U_GEANT_DETECTORACTIONINITIALIZATION_HH
|
||||||
|
#define U_GEANT_DETECTORACTIONINITIALIZATION_HH
|
||||||
|
|
||||||
|
#include "G4VUserActionInitialization.hh"
|
||||||
|
#include "Core/Vector.h"
|
||||||
|
#include "HEP/Detectors/MuonEvent.h"
|
||||||
|
#include "Math/Dense.h"
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Geant {
|
||||||
|
|
||||||
|
class EmitterPrimary;
|
||||||
|
|
||||||
|
class DetectorActionInitialization : public G4VUserActionInitialization {
|
||||||
|
public:
|
||||||
|
DetectorActionInitialization(EmitterPrimary *emitter,
|
||||||
|
Vector<MuonEvent> *output,
|
||||||
|
const Vector<HLine3f> &planes,
|
||||||
|
int verbosity = 0);
|
||||||
|
~DetectorActionInitialization();
|
||||||
|
|
||||||
|
virtual void BuildForMaster() const override;
|
||||||
|
virtual void Build() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EmitterPrimary *m_Emitter;
|
||||||
|
Vector<MuonEvent> *m_Output;
|
||||||
|
Vector<HLine3f> m_Planes;
|
||||||
|
int m_Verbosity;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Geant
|
||||||
|
} // namespace uLib
|
||||||
|
|
||||||
|
#endif
|
||||||
110
src/HEP/Geant/DetectorSteppingAction.cpp
Normal file
110
src/HEP/Geant/DetectorSteppingAction.cpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#include "DetectorSteppingAction.hh"
|
||||||
|
#include <Geant4/G4Step.hh>
|
||||||
|
#include <Geant4/G4Track.hh>
|
||||||
|
#include <Geant4/G4Event.hh>
|
||||||
|
#include <Geant4/G4SystemOfUnits.hh>
|
||||||
|
#include <cmath>
|
||||||
|
#include <mutex>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
static std::mutex g_DetectorOutputMutex;
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Geant {
|
||||||
|
|
||||||
|
DetectorSteppingAction::DetectorSteppingAction(Vector<MuonEvent> *output, const Vector<HLine3f> &planes)
|
||||||
|
: G4UserSteppingAction(),
|
||||||
|
G4UserEventAction(),
|
||||||
|
m_Output(output),
|
||||||
|
m_Planes(planes),
|
||||||
|
m_CrossCount(0),
|
||||||
|
m_Verbosity(1)
|
||||||
|
{
|
||||||
|
// std::cout << "[Geant] SteppingAction created with " << m_Planes.size() << " planes." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
DetectorSteppingAction::~DetectorSteppingAction() {}
|
||||||
|
|
||||||
|
void DetectorSteppingAction::BeginOfEventAction(const G4Event* /*event*/) {
|
||||||
|
m_CrossCount = 0;
|
||||||
|
|
||||||
|
// Initialize with NaN
|
||||||
|
float nan = std::numeric_limits<float>::quiet_NaN();
|
||||||
|
m_Current.LineIn().origin = HPoint3f(nan, nan, nan);
|
||||||
|
m_Current.LineIn().direction = HVector3f(nan, nan, nan);
|
||||||
|
m_Current.LineOut().origin = HPoint3f(nan, nan, nan);
|
||||||
|
m_Current.LineOut().direction = HVector3f(nan, nan, nan);
|
||||||
|
m_Current.Momentum() = nan;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DetectorSteppingAction::EndOfEventAction(const G4Event* /*event*/) {
|
||||||
|
if (m_Output) {
|
||||||
|
std::lock_guard<std::mutex> lock(g_DetectorOutputMutex);
|
||||||
|
m_Output->push_back(m_Current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DetectorSteppingAction::UserSteppingAction(const G4Step *step) {
|
||||||
|
if (!step) return;
|
||||||
|
if (!m_Output) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const G4Track *track = step->GetTrack();
|
||||||
|
if (!track) return;
|
||||||
|
|
||||||
|
static size_t step_count = 0;
|
||||||
|
if (++step_count % 1000 == 0 && m_Verbosity > 0) {
|
||||||
|
std::cout << "[GeantMT] Processed " << step_count << " total steps across events." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only consider primary muons
|
||||||
|
if (track->GetParentID() != 0) return;
|
||||||
|
|
||||||
|
// Track the momentum at generation/first step if not set
|
||||||
|
if (std::isnan(m_Current.Momentum())) {
|
||||||
|
m_Current.Momentum() = static_cast<Scalarf>(track->GetMomentum().mag() / MeV);
|
||||||
|
}
|
||||||
|
|
||||||
|
G4ThreeVector p1 = step->GetPreStepPoint()->GetPosition();
|
||||||
|
G4ThreeVector p2 = step->GetPostStepPoint()->GetPosition();
|
||||||
|
G4ThreeVector dir_g4 = track->GetMomentumDirection();
|
||||||
|
|
||||||
|
HPoint3f p1f(p1.x(), p1.y(), p1.z());
|
||||||
|
HPoint3f p2f(p2.x(), p2.y(), p2.z());
|
||||||
|
HVector3f dirf(dir_g4.x(), dir_g4.y(), dir_g4.z());
|
||||||
|
|
||||||
|
// Check intersection with each detector plane
|
||||||
|
for (const auto& plane : m_Planes) {
|
||||||
|
// Plane: origin=O, direction=N (normal)
|
||||||
|
HPoint3f O = plane.origin;
|
||||||
|
HVector3f N = plane.direction;
|
||||||
|
|
||||||
|
float d1 = (p1f - O).dot(N);
|
||||||
|
float d2 = (p2f - O).dot(N);
|
||||||
|
|
||||||
|
// Check if the step crossed the plane
|
||||||
|
if ((d1 > 0 && d2 <= 0) || (d1 < 0 && d2 >= 0)) {
|
||||||
|
// Intersection point t = d1 / (d1 - d2)
|
||||||
|
float t = d1 / (d1 - d2);
|
||||||
|
HPoint3f intersection = p1f + t * (p2f - p1f);
|
||||||
|
|
||||||
|
if (m_CrossCount == 0) {
|
||||||
|
m_Current.LineIn().origin = intersection;
|
||||||
|
m_Current.LineIn().direction = dirf;
|
||||||
|
m_CrossCount++;
|
||||||
|
if (m_Verbosity > 0) std::cout << "[GeantMT] Hit first plane at " << intersection.transpose() << std::endl;
|
||||||
|
} else if (m_CrossCount == 1) {
|
||||||
|
m_Current.LineOut().origin = intersection;
|
||||||
|
m_Current.LineOut().direction = dirf;
|
||||||
|
m_CrossCount++;
|
||||||
|
if (m_Verbosity > 0) std::cout << "[GeantMT] Hit second plane at " << intersection.transpose() << std::endl;
|
||||||
|
}
|
||||||
|
// We break to avoid crossing multiple planes in one infinitesimal step (unlikely but possible)
|
||||||
|
// Actually, we should check ALL planes.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Geant
|
||||||
|
} // namespace uLib
|
||||||
36
src/HEP/Geant/DetectorSteppingAction.hh
Normal file
36
src/HEP/Geant/DetectorSteppingAction.hh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef U_GEANT_DETECTORSTEPPINGACTION_HH
|
||||||
|
#define U_GEANT_DETECTORSTEPPINGACTION_HH
|
||||||
|
|
||||||
|
#include "G4UserSteppingAction.hh"
|
||||||
|
#include "G4UserEventAction.hh"
|
||||||
|
#include "Core/Vector.h"
|
||||||
|
#include "HEP/Detectors/MuonEvent.h"
|
||||||
|
#include "HEP/Detectors/DetectorChamber.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Geant {
|
||||||
|
|
||||||
|
class DetectorSteppingAction : public G4UserSteppingAction, public G4UserEventAction {
|
||||||
|
public:
|
||||||
|
DetectorSteppingAction(Vector<MuonEvent> *output, const Vector<HLine3f> &planes);
|
||||||
|
virtual ~DetectorSteppingAction();
|
||||||
|
|
||||||
|
virtual void UserSteppingAction(const G4Step *step) override;
|
||||||
|
virtual void BeginOfEventAction(const G4Event *event) override;
|
||||||
|
virtual void EndOfEventAction(const G4Event *event) override;
|
||||||
|
|
||||||
|
void SetVerbosity(int level) { m_Verbosity = level; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<MuonEvent> *m_Output;
|
||||||
|
Vector<HLine3f> m_Planes; // World projection planes
|
||||||
|
MuonEvent m_Current;
|
||||||
|
int m_CrossCount = 0;
|
||||||
|
int m_Verbosity = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Geant
|
||||||
|
} // namespace uLib
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -73,6 +73,7 @@ public:
|
|||||||
|
|
||||||
void Print(const size_t size = 10) const;
|
void Print(const size_t size = 10) const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Id_t m_EventID;
|
Id_t m_EventID;
|
||||||
Scalarf m_Momentum;
|
Scalarf m_Momentum;
|
||||||
|
|||||||
@@ -1,28 +1,3 @@
|
|||||||
/*//////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 3.0 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library.
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////*/
|
|
||||||
|
|
||||||
#include <Geant4/G4Box.hh>
|
#include <Geant4/G4Box.hh>
|
||||||
#include <Geant4/G4LogicalVolume.hh>
|
#include <Geant4/G4LogicalVolume.hh>
|
||||||
#include <Geant4/G4Material.hh>
|
#include <Geant4/G4Material.hh>
|
||||||
@@ -42,13 +17,15 @@
|
|||||||
#include "Scene.h"
|
#include "Scene.h"
|
||||||
#include "PhysicsList.hh"
|
#include "PhysicsList.hh"
|
||||||
#include "ActionInitialization.hh"
|
#include "ActionInitialization.hh"
|
||||||
|
#include "SimulationContext.h"
|
||||||
|
#include "HEP/Detectors/DetectorChamber.h"
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Geant {
|
namespace Geant {
|
||||||
|
|
||||||
class SceneDetectorConstruction : public DetectorConstruction {
|
class SceneDetectorConstruction : public DetectorConstruction {
|
||||||
public:
|
public:
|
||||||
SceneDetectorConstruction(class SceneImpl *owner);
|
SceneDetectorConstruction(class SceneImpl *owner) : DetectorConstruction("Scene"), m_Owner(owner) {}
|
||||||
G4VPhysicalVolume *Construct() override;
|
G4VPhysicalVolume *Construct() override;
|
||||||
private:
|
private:
|
||||||
class SceneImpl *m_Owner;
|
class SceneImpl *m_Owner;
|
||||||
@@ -69,57 +46,50 @@ static void CheckGeant4Environment() {
|
|||||||
|
|
||||||
class SceneImpl {
|
class SceneImpl {
|
||||||
public:
|
public:
|
||||||
// constructor //
|
|
||||||
SceneImpl() : m_RunManager(G4RunManagerFactory::CreateRunManager(G4RunManagerType::Default)),
|
SceneImpl() : m_RunManager(G4RunManagerFactory::CreateRunManager(G4RunManagerType::Default)),
|
||||||
m_Emitter(nullptr),
|
m_Emitter(nullptr),
|
||||||
m_Output(nullptr),
|
m_InitCalled(false) {
|
||||||
m_Verbosity(0) {
|
|
||||||
m_RunManager->SetUserInitialization(new PhysicsList);
|
m_RunManager->SetUserInitialization(new PhysicsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor //
|
|
||||||
~SceneImpl() {
|
~SceneImpl() {
|
||||||
if (m_RunManager) delete m_RunManager;
|
if (m_RunManager) delete m_RunManager;
|
||||||
if (m_World) delete m_World;
|
// m_World deletion is handled in Scene destructor or here
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialize() {
|
void Initialize() {
|
||||||
// Set mandatory initialization classes for Geant4
|
if (m_InitCalled) return;
|
||||||
|
|
||||||
m_RunManager->SetUserInitialization(new SceneDetectorConstruction(this));
|
m_RunManager->SetUserInitialization(new SceneDetectorConstruction(this));
|
||||||
m_RunManager->SetUserInitialization(
|
m_RunManager->SetUserInitialization(new ActionInitialization(m_Emitter, &m_Context));
|
||||||
new ActionInitialization(m_Emitter, m_Output, m_Verbosity));
|
|
||||||
|
|
||||||
m_RunManager->SetVerboseLevel(m_Verbosity);
|
|
||||||
|
|
||||||
// Initialize Geant4
|
|
||||||
m_RunManager->Initialize();
|
m_RunManager->Initialize();
|
||||||
|
m_InitCalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// members //
|
|
||||||
Vector<Solid *> m_Solids;
|
Vector<Solid *> m_Solids;
|
||||||
Solid *m_World = nullptr;
|
Solid *m_World = nullptr;
|
||||||
ContainerBox m_WorldBox;
|
ContainerBox m_WorldBox;
|
||||||
G4RunManager *m_RunManager;
|
G4RunManager *m_RunManager;
|
||||||
EmitterPrimary *m_Emitter;
|
EmitterPrimary *m_Emitter;
|
||||||
Vector<GeantEvent> *m_Output;
|
SimulationContext m_Context;
|
||||||
int m_Verbosity;
|
bool m_InitCalled;
|
||||||
};
|
};
|
||||||
|
|
||||||
SceneDetectorConstruction::SceneDetectorConstruction(SceneImpl *owner)
|
|
||||||
: DetectorConstruction("Scene"), m_Owner(owner) {}
|
|
||||||
|
|
||||||
G4VPhysicalVolume *SceneDetectorConstruction::Construct() {
|
G4VPhysicalVolume *SceneDetectorConstruction::Construct() {
|
||||||
return m_Owner->m_World->GetPhysical();
|
return m_Owner->m_World->GetPhysical();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scene::Scene() {
|
Scene::Scene() {
|
||||||
CheckGeant4Environment();
|
CheckGeant4Environment();
|
||||||
d = new SceneImpl();
|
d = new SceneImpl();
|
||||||
}
|
}
|
||||||
Scene::~Scene() { delete d; }
|
|
||||||
|
Scene::~Scene() {
|
||||||
|
// Delete solids
|
||||||
|
for(auto s : d->m_Solids) delete s;
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
void Scene::AddSolid(Solid *solid, Solid *parent) {
|
void Scene::AddSolid(Solid *solid, Solid *parent) {
|
||||||
d->m_Solids.push_back(solid);
|
d->m_Solids.push_back(solid);
|
||||||
@@ -131,12 +101,9 @@ void Scene::AddSolid(Solid *solid, Solid *parent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Solid* Scene::GetWorld() const { return d->m_World; }
|
const Solid* Scene::GetWorld() const { return d->m_World; }
|
||||||
|
|
||||||
ContainerBox* Scene::GetWorldBox() const { return &d->m_WorldBox; }
|
ContainerBox* Scene::GetWorldBox() const { return &d->m_WorldBox; }
|
||||||
|
|
||||||
void Scene::ConstructWorldBox(const Vector3f &size, const char *material) {
|
void Scene::ConstructWorldBox(const Vector3f &size, const char *material) {
|
||||||
// Get nist material manager
|
|
||||||
|
|
||||||
d->m_WorldBox.Scale(size);
|
d->m_WorldBox.Scale(size);
|
||||||
d->m_WorldBox.SetPosition(-size/2.0f);
|
d->m_WorldBox.SetPosition(-size/2.0f);
|
||||||
|
|
||||||
@@ -146,61 +113,48 @@ void Scene::ConstructWorldBox(const Vector3f &size, const char *material) {
|
|||||||
AddSolid(d->m_World);
|
AddSolid(d->m_World);
|
||||||
}
|
}
|
||||||
|
|
||||||
G4Box *solidWorld = new G4Box("World",
|
G4Box *solidWorld = new G4Box("World", 0.5 * size(0), 0.5 * size(1), 0.5 * size(2));
|
||||||
0.5 * size(0),
|
G4LogicalVolume *logicWorld = new G4LogicalVolume(solidWorld, d->m_World->GetMaterial(), d->m_World->GetName());
|
||||||
0.5 * size(1),
|
|
||||||
0.5 * size(2));
|
|
||||||
|
|
||||||
G4LogicalVolume *logicWorld = new G4LogicalVolume(solidWorld,
|
|
||||||
d->m_World->GetMaterial(),
|
|
||||||
d->m_World->GetName());
|
|
||||||
|
|
||||||
d->m_World->SetLogical(logicWorld);
|
d->m_World->SetLogical(logicWorld);
|
||||||
|
|
||||||
G4PVPlacement *physWorld = new G4PVPlacement(
|
G4PVPlacement *physWorld = new G4PVPlacement(nullptr, G4ThreeVector(0, 0, 0), logicWorld, d->m_World->GetName(), 0, false, 0, true);
|
||||||
nullptr,
|
|
||||||
G4ThreeVector(0, 0, 0),
|
|
||||||
logicWorld,
|
|
||||||
d->m_World->GetName(),
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
true);
|
|
||||||
|
|
||||||
d->m_World->SetPhysical(physWorld);
|
d->m_World->SetPhysical(physWorld);
|
||||||
|
|
||||||
// no transforms are allowed for the world box
|
|
||||||
// Matrix4f transform = box->GetMatrix();
|
|
||||||
// d->m_World->SetTransform(transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::SetEmitter(EmitterPrimary *emitter) {
|
void Scene::SetEmitter(EmitterPrimary *emitter) { d->m_Emitter = emitter; }
|
||||||
d->m_Emitter = emitter;
|
void Scene::Initialize() { d->Initialize(); }
|
||||||
}
|
|
||||||
|
|
||||||
void Scene::Initialize() {
|
|
||||||
d->Initialize();
|
|
||||||
}
|
|
||||||
void Scene::SetVerbosity(int level) {
|
void Scene::SetVerbosity(int level) {
|
||||||
d->m_Verbosity = level;
|
d->m_Context.verbosity = level;
|
||||||
if (d->m_RunManager) d->m_RunManager->SetVerboseLevel(level);
|
if (d->m_RunManager) d->m_RunManager->SetVerboseLevel(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::RunSimulation(int nEvents, Vector<GeantEvent> &results) {
|
void Scene::RunSimulation(int nEvents, Vector<GeantEvent> &results) {
|
||||||
d->m_Output = &results;
|
d->Initialize(); // Ensure initialized
|
||||||
|
d->m_Context.mode = SimulationMode::DETAILED;
|
||||||
|
d->m_Context.outputGeant = &results;
|
||||||
|
d->m_Context.outputMuon = nullptr;
|
||||||
|
|
||||||
// Re-initialize ActionInitialization with the output buffer
|
d->m_RunManager->BeamOn(nEvents);
|
||||||
// (ActionInitialization was already set during Initialize, but we need
|
}
|
||||||
// to ensure the output pointer is current)
|
|
||||||
d->m_RunManager->SetUserInitialization(
|
|
||||||
new ActionInitialization(d->m_Emitter, &results, d->m_Verbosity));
|
|
||||||
|
|
||||||
// Re-run initialization to propagate the ActionInitialization change to worker threads
|
void Scene::RunDetectorSimulation(int nEvents, Vector<MuonEvent> &results) {
|
||||||
d->m_RunManager->Initialize();
|
d->Initialize(); // Ensure initialized
|
||||||
|
d->m_Context.mode = SimulationMode::DETECTOR;
|
||||||
|
d->m_Context.outputGeant = nullptr;
|
||||||
|
d->m_Context.outputMuon = &results;
|
||||||
|
|
||||||
|
// Find detector planes
|
||||||
|
d->m_Context.detectorPlanes.clear();
|
||||||
|
for (Solid* s : d->m_Solids) {
|
||||||
|
if (BoxSolid* bs = dynamic_cast<BoxSolid*>(s)) {
|
||||||
|
if (DetectorChamber* dc = dynamic_cast<DetectorChamber*>(bs->GetObject())) {
|
||||||
|
d->m_Context.detectorPlanes.push_back(dc->GetWorldProjectionPlane());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
d->m_RunManager->BeamOn(nEvents);
|
d->m_RunManager->BeamOn(nEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Geant
|
} // namespace Geant
|
||||||
} // namespace uLib
|
} // namespace uLib
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "Core/Vector.h"
|
#include "Core/Vector.h"
|
||||||
#include "Solid.h"
|
#include "Solid.h"
|
||||||
#include "GeantEvent.h"
|
#include "GeantEvent.h"
|
||||||
|
#include "HEP/Detectors/MuonEvent.h"
|
||||||
|
|
||||||
class G4VPhysicalVolume;
|
class G4VPhysicalVolume;
|
||||||
|
|
||||||
@@ -68,6 +69,9 @@ public:
|
|||||||
/// Results are appended to the provided vector.
|
/// Results are appended to the provided vector.
|
||||||
void RunSimulation(int nEvents, Vector<GeantEvent> &results);
|
void RunSimulation(int nEvents, Vector<GeantEvent> &results);
|
||||||
|
|
||||||
|
/// Specialized detector simulation trackingMuonEvent line crossings.
|
||||||
|
void RunDetectorSimulation(int nEvents, Vector<MuonEvent> &results);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class SceneImpl *d;
|
class SceneImpl *d;
|
||||||
};
|
};
|
||||||
|
|||||||
30
src/HEP/Geant/SimulationContext.h
Normal file
30
src/HEP/Geant/SimulationContext.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef U_GEANT_SIMULATIONCONTEXT_H
|
||||||
|
#define U_GEANT_SIMULATIONCONTEXT_H
|
||||||
|
|
||||||
|
#include "Core/Vector.h"
|
||||||
|
#include "GeantEvent.h"
|
||||||
|
#include "HEP/Detectors/MuonEvent.h"
|
||||||
|
#include "Math/Dense.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Geant {
|
||||||
|
|
||||||
|
enum class SimulationMode {
|
||||||
|
DETAILED,
|
||||||
|
DETECTOR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SimulationContext {
|
||||||
|
SimulationMode mode = SimulationMode::DETAILED;
|
||||||
|
Vector<GeantEvent> *outputGeant = nullptr;
|
||||||
|
Vector<MuonEvent> *outputMuon = nullptr;
|
||||||
|
Vector<HLine3f> detectorPlanes;
|
||||||
|
int verbosity = 0;
|
||||||
|
std::mutex outputMutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Geant
|
||||||
|
} // namespace uLib
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -107,6 +107,8 @@ public:
|
|||||||
BoxSolid(const char *name, ContainerBox *box);
|
BoxSolid(const char *name, ContainerBox *box);
|
||||||
virtual G4VSolid* GetG4Solid() const override { return (G4VSolid*)m_Solid; }
|
virtual G4VSolid* GetG4Solid() const override { return (G4VSolid*)m_Solid; }
|
||||||
|
|
||||||
|
ContainerBox* GetObject() const { return m_Object; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
|
|||||||
@@ -1,111 +1,124 @@
|
|||||||
#include "SteppingAction.hh"
|
#include "SteppingAction.hh"
|
||||||
|
#include <Geant4/G4Step.hh>
|
||||||
#include "G4Step.hh"
|
#include <Geant4/G4Track.hh>
|
||||||
#include "G4Track.hh"
|
#include <Geant4/G4Event.hh>
|
||||||
#include "G4Event.hh"
|
#include <Geant4/G4SystemOfUnits.hh>
|
||||||
#include "G4RunManager.hh"
|
|
||||||
#include "G4LogicalVolume.hh"
|
|
||||||
#include "G4SystemOfUnits.hh"
|
|
||||||
#include "G4ParticleDefinition.hh"
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <cmath>
|
||||||
static std::mutex g_SimulationOutputMutex;
|
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Geant {
|
namespace Geant {
|
||||||
|
|
||||||
SteppingAction::SteppingAction(Vector<GeantEvent> *output)
|
SteppingAction::SteppingAction(SimulationContext *context)
|
||||||
: G4UserSteppingAction(),
|
: G4UserSteppingAction(),
|
||||||
m_Output(output),
|
G4UserEventAction(),
|
||||||
m_Current(),
|
m_Context(context),
|
||||||
m_LastEventID(-1)
|
m_Verbosity(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SteppingAction::~SteppingAction() {}
|
SteppingAction::~SteppingAction() {}
|
||||||
|
|
||||||
void SteppingAction::BeginOfEventAction(const G4Event *event) {
|
void SteppingAction::BeginOfEventAction(const G4Event *event) {
|
||||||
if (!event || !m_Output) return;
|
if (!event || !m_Context) return;
|
||||||
|
|
||||||
// Start a new GeantEvent
|
if (m_Context->mode == SimulationMode::DETAILED) {
|
||||||
m_Current = GeantEvent();
|
m_CurrentGeant = GeantEvent();
|
||||||
m_Current.m_EventID = static_cast<Id_t>(event->GetEventID());
|
m_CurrentGeant.m_EventID = static_cast<Id_t>(event->GetEventID());
|
||||||
|
|
||||||
// Set initial momentum and generation vector from primary vertex
|
|
||||||
if (event->GetNumberOfPrimaryVertex() > 0) {
|
if (event->GetNumberOfPrimaryVertex() > 0) {
|
||||||
G4PrimaryVertex *vtx = event->GetPrimaryVertex(0);
|
G4PrimaryVertex *vtx = event->GetPrimaryVertex(0);
|
||||||
G4ThreeVector pos = vtx->GetPosition();
|
G4ThreeVector pos = vtx->GetPosition();
|
||||||
m_Current.m_GenVector.origin = HPoint3f(pos.x(), pos.y(), pos.z());
|
m_CurrentGeant.m_GenVector.origin = HPoint3f(pos.x(), pos.y(), pos.z());
|
||||||
|
|
||||||
if (vtx->GetNumberOfParticle() > 0) {
|
if (vtx->GetNumberOfParticle() > 0) {
|
||||||
G4PrimaryParticle *prim = vtx->GetPrimary(0);
|
G4PrimaryParticle *prim = vtx->GetPrimary(0);
|
||||||
G4ThreeVector mom = prim->GetMomentumDirection();
|
G4ThreeVector mom = prim->GetMomentumDirection();
|
||||||
m_Current.m_GenVector.direction = HVector3f(mom.x(), mom.y(), mom.z());
|
m_CurrentGeant.m_GenVector.direction = HVector3f(mom.x(), mom.y(), mom.z());
|
||||||
m_Current.m_Momentum = static_cast<Scalarf>(prim->GetTotalMomentum() / MeV);
|
m_CurrentGeant.m_Momentum = static_cast<Scalarf>(prim->GetTotalMomentum() / MeV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Detector mode
|
||||||
|
m_MuonCrossCount = 0;
|
||||||
|
float nan = std::numeric_limits<float>::quiet_NaN();
|
||||||
|
m_CurrentMuon.LineIn().origin = HPoint3f(nan, nan, nan);
|
||||||
|
m_CurrentMuon.LineIn().direction = HVector3f(nan, nan, nan);
|
||||||
|
m_CurrentMuon.LineOut().origin = HPoint3f(nan, nan, nan);
|
||||||
|
m_CurrentMuon.LineOut().direction = HVector3f(nan, nan, nan);
|
||||||
|
m_CurrentMuon.Momentum() = nan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteppingAction::EndOfEventAction(const G4Event *event) {
|
void SteppingAction::EndOfEventAction(const G4Event *event) {
|
||||||
if (m_Output && !m_Current.m_Path.empty()) {
|
if (!m_Context) return;
|
||||||
if (m_Verbosity > 0) {
|
|
||||||
std::cout << "[Geant] Finished Event " << m_Current.m_EventID
|
|
||||||
<< " with " << m_Current.m_Path.size() << " steps." << std::endl;
|
|
||||||
|
|
||||||
// Check if we hit anything other than World
|
if (m_Context->mode == SimulationMode::DETAILED && m_Context->outputGeant) {
|
||||||
std::set<std::string> volumes;
|
if (!m_CurrentGeant.m_Path.empty()) {
|
||||||
for (const auto& delta : m_Current.m_Path) {
|
std::lock_guard<std::mutex> lock(m_Context->outputMutex);
|
||||||
if (!delta.m_SolidName.empty()) volumes.insert(delta.m_SolidName);
|
m_Context->outputGeant->push_back(m_CurrentGeant);
|
||||||
}
|
|
||||||
if (volumes.size() > 1) {
|
|
||||||
std::cout << " - Hit volumes: ";
|
|
||||||
for (const auto& v : volumes) std::cout << v << " ";
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(g_SimulationOutputMutex);
|
|
||||||
m_Output->push_back(m_Current);
|
|
||||||
}
|
}
|
||||||
|
} else if (m_Context->mode == SimulationMode::DETECTOR && m_Context->outputMuon) {
|
||||||
|
// In detector mode, we always push the event (to keep indexing consistent)
|
||||||
|
// or only if hit? User requested "all muon event line in and out ar at first set to nan".
|
||||||
|
// So we push everything.
|
||||||
|
std::lock_guard<std::mutex> lock(m_Context->outputMutex);
|
||||||
|
m_Context->outputMuon->push_back(m_CurrentMuon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteppingAction::UserSteppingAction(const G4Step *step) {
|
void SteppingAction::UserSteppingAction(const G4Step *step) {
|
||||||
if (!step || !m_Output) return;
|
if (!step || !m_Context) return;
|
||||||
|
|
||||||
const G4Track *track = step->GetTrack();
|
const G4Track *track = step->GetTrack();
|
||||||
if (!track) return;
|
if (!track || track->GetParentID() != 0) return;
|
||||||
|
|
||||||
// Only record primary particle (muon)
|
if (m_Context->mode == SimulationMode::DETAILED) {
|
||||||
if (track->GetParentID() != 0) return;
|
|
||||||
|
|
||||||
// Record a Delta for this step
|
|
||||||
GeantEvent::Delta delta;
|
GeantEvent::Delta delta;
|
||||||
|
|
||||||
// Step length
|
|
||||||
delta.m_Length = static_cast<Scalarf>(step->GetStepLength() / mm);
|
delta.m_Length = static_cast<Scalarf>(step->GetStepLength() / mm);
|
||||||
|
delta.m_Momentum = static_cast<Scalarf>(track->GetMomentum().mag() / MeV);
|
||||||
// Post-step momentum
|
|
||||||
G4ThreeVector postMom = track->GetMomentum();
|
|
||||||
delta.m_Momentum = static_cast<Scalarf>(postMom.mag() / MeV);
|
|
||||||
|
|
||||||
// Post-step direction
|
|
||||||
G4ThreeVector dir = track->GetMomentumDirection();
|
G4ThreeVector dir = track->GetMomentumDirection();
|
||||||
delta.m_Direction = HVector3f(static_cast<float>(dir.x()),
|
delta.m_Direction = HVector3f(dir.x(), dir.y(), dir.z());
|
||||||
static_cast<float>(dir.y()),
|
|
||||||
static_cast<float>(dir.z()));
|
|
||||||
|
|
||||||
// Solid name where the step occurred
|
if (track->GetVolume()) {
|
||||||
const G4LogicalVolume *vol = track->GetVolume()
|
delta.m_SolidName = track->GetVolume()->GetName();
|
||||||
? track->GetVolume()->GetLogicalVolume()
|
}
|
||||||
: nullptr;
|
m_CurrentGeant.m_Path.push_back(delta);
|
||||||
if (vol) {
|
} else {
|
||||||
delta.m_SolidName = vol->GetName();
|
// Detector Mode
|
||||||
|
if (std::isnan(m_CurrentMuon.Momentum())) {
|
||||||
|
m_CurrentMuon.Momentum() = static_cast<Scalarf>(track->GetMomentum().mag() / MeV);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Current.m_Path.push_back(delta);
|
G4ThreeVector p1 = step->GetPreStepPoint()->GetPosition();
|
||||||
|
G4ThreeVector p2 = step->GetPostStepPoint()->GetPosition();
|
||||||
|
G4ThreeVector dir_g4 = track->GetMomentumDirection();
|
||||||
|
|
||||||
|
HPoint3f p1f(p1.x(), p1.y(), p1.z());
|
||||||
|
HPoint3f p2f(p2.x(), p2.y(), p2.z());
|
||||||
|
HVector3f dirf(dir_g4.x(), dir_g4.y(), dir_g4.z());
|
||||||
|
|
||||||
|
for (const auto& plane : m_Context->detectorPlanes) {
|
||||||
|
float d1 = (p1f - plane.origin).dot(plane.direction);
|
||||||
|
float d2 = (p2f - plane.origin).dot(plane.direction);
|
||||||
|
|
||||||
|
if ((d1 > 0 && d2 <= 0) || (d1 < 0 && d2 >= 0)) {
|
||||||
|
float t = d1 / (d1 - d2);
|
||||||
|
HPoint3f intersection = p1f + t * (p2f - p1f);
|
||||||
|
|
||||||
|
if (m_MuonCrossCount == 0) {
|
||||||
|
m_CurrentMuon.LineIn().origin = intersection;
|
||||||
|
m_CurrentMuon.LineIn().direction = dirf;
|
||||||
|
m_MuonCrossCount++;
|
||||||
|
} else if (m_MuonCrossCount == 1) {
|
||||||
|
m_CurrentMuon.LineOut().origin = intersection;
|
||||||
|
m_CurrentMuon.LineOut().direction = dirf;
|
||||||
|
m_MuonCrossCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Geant
|
} // namespace Geant
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
#include "G4UserEventAction.hh"
|
#include "G4UserEventAction.hh"
|
||||||
#include "Core/Vector.h"
|
#include "Core/Vector.h"
|
||||||
#include "GeantEvent.h"
|
#include "GeantEvent.h"
|
||||||
|
#include "HEP/Detectors/MuonEvent.h"
|
||||||
|
#include "SimulationContext.h"
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Geant {
|
namespace Geant {
|
||||||
|
|
||||||
/// SteppingAction collects scattering data at each Geant4 step and
|
/// SteppingAction collects scattering data at each Geant4 step.
|
||||||
/// builds GeantEvent objects in the output buffer.
|
|
||||||
class SteppingAction : public G4UserSteppingAction, public G4UserEventAction {
|
class SteppingAction : public G4UserSteppingAction, public G4UserEventAction {
|
||||||
public:
|
public:
|
||||||
/// @param output pointer to the results vector owned by the Scene
|
SteppingAction(SimulationContext *context);
|
||||||
SteppingAction(Vector<GeantEvent> *output);
|
|
||||||
virtual ~SteppingAction();
|
virtual ~SteppingAction();
|
||||||
|
|
||||||
virtual void UserSteppingAction(const G4Step *step) override;
|
virtual void UserSteppingAction(const G4Step *step) override;
|
||||||
@@ -24,9 +24,10 @@ public:
|
|||||||
void SetVerbosity(int level) { m_Verbosity = level; }
|
void SetVerbosity(int level) { m_Verbosity = level; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<GeantEvent> *m_Output; ///< destination for finished events
|
SimulationContext *m_Context;
|
||||||
GeantEvent m_Current; ///< event being built
|
GeantEvent m_CurrentGeant;
|
||||||
int m_LastEventID; ///< track event transitions
|
MuonEvent m_CurrentMuon;
|
||||||
|
int m_MuonCrossCount = 0;
|
||||||
int m_Verbosity = 0;
|
int m_Verbosity = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ int main(int argc, char **argv) {
|
|||||||
// runManager->SetUserInitialization(new PhysicsList());
|
// runManager->SetUserInitialization(new PhysicsList());
|
||||||
|
|
||||||
// 3. INIZIALIZZAZIONE DELLE AZIONI (Il nostro generatore!)
|
// 3. INIZIALIZZAZIONE DELLE AZIONI (Il nostro generatore!)
|
||||||
runManager->SetUserInitialization(new uLib::Geant::ActionInitialization());
|
runManager->SetUserInitialization(new uLib::Geant::ActionInitialization(nullptr, nullptr));
|
||||||
|
|
||||||
// ... Inizializzazione del kernel ( runManager->Initialize(); ), UI manager,
|
// ... Inizializzazione del kernel ( runManager->Initialize(); ), UI manager,
|
||||||
// vis manager, ecc.
|
// vis manager, ecc.
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ int main(int argc, char** argv) {
|
|||||||
scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR");
|
scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR");
|
||||||
|
|
||||||
ContainerBox iron_box;
|
ContainerBox iron_box;
|
||||||
iron_box.Scale(Vector3f(18_m, 18_m, 18_m));
|
iron_box.Scale(Vector3f(18_m, 10_cm, 18_m));
|
||||||
iron_box.SetPosition(Vector3f(-9_m, -9_m, -9_m));
|
iron_box.SetPosition(Vector3f(-9_m, -5_cm, -9_m));
|
||||||
Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box);
|
Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box);
|
||||||
iron_cube->SetNistMaterial("G4_Fe");
|
iron_cube->SetNistMaterial("G4_Fe");
|
||||||
iron_cube->Update();
|
iron_cube->Update();
|
||||||
@@ -60,7 +60,9 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
scene.SetEmitter(emitter);
|
scene.SetEmitter(emitter);
|
||||||
scene.SetVerbosity(1);
|
scene.SetVerbosity(1);
|
||||||
scene.Initialize();
|
// scene.Initialize(); // Removed to avoid premature initialization
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::cout << "Starting simulation of " << nEvents << " events..." << std::endl;
|
std::cout << "Starting simulation of " << nEvents << " events..." << std::endl;
|
||||||
Vector<Geant::GeantEvent> results;
|
Vector<Geant::GeantEvent> results;
|
||||||
@@ -80,5 +82,23 @@ int main(int argc, char** argv) {
|
|||||||
std::cout << " Average steps per event: " << static_cast<double>(total_steps) / results.size() << std::endl;
|
std::cout << " Average steps per event: " << static_cast<double>(total_steps) / results.size() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "\nStarting Detector Simulation of " << nEvents << " events..." << std::endl;
|
||||||
|
Vector<MuonEvent> detectorResults;
|
||||||
|
scene.RunDetectorSimulation(nEvents, detectorResults);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "Detector Simulation finished." << std::endl;
|
||||||
|
size_t hit_count = 0;
|
||||||
|
for (const auto& ev : detectorResults) {
|
||||||
|
if (!std::isnan(ev.LineIn().origin.x())) {
|
||||||
|
hit_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << " Muons crossing at least one detector: " << hit_count << std::endl;
|
||||||
|
if (nEvents > 0) {
|
||||||
|
std::cout << " Efficiency: " << (100.0 * hit_count / nEvents) << "%" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user