Newer
Older
// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $
//====================================================================
// AIDA Detector description implementation
//--------------------------------------------------------------------
//
// Author : M.Frank
//
//====================================================================
#include "DD4hep/Printout.h"
#include "DD4hep/Primitives.h"
#include "DD4hep/InstanceCount.h"
#include "G4UserRunAction.hh"
#include "G4UserEventAction.hh"
#include "G4UserTrackingAction.hh"
#include "G4UserStackingAction.hh"
#include "G4UserSteppingAction.hh"
#include "G4UserReactionAction.hh"
#include "G4VUserPhysicsList.hh"
#include "G4VModularPhysicsList.hh"
#include "G4VUserPrimaryGeneratorAction.hh"
#include "DD4hep/Handle.h"
#include "DDG4/Geant4RunAction.h"
#include "DDG4/Geant4EventAction.h"
#include "DDG4/Geant4SteppingAction.h"
#include "DDG4/Geant4TrackingAction.h"
#include "DDG4/Geant4StackingAction.h"
#include "DDG4/Geant4GeneratorAction.h"
#include "DDG4/Geant4PhysicsList.h"
#include "DDG4/Geant4Kernel.h"
#include "DDG4/Geant4Random.h"
/*
* DD4hep namespace declaration
*/
namespace DD4hep {
/*
* Simulation namespace declaration
*/
namespace {
Geant4Context* s_globalContext = 0;
Geant4Random* s_globalRandom = 0;
}
Geant4Context* ddg4_globalContext() {
return s_globalContext;
}
template <typename T> struct SequenceHdl {
typedef SequenceHdl<T> Base;
T* m_sequence;
SequenceHdl(Geant4Context* context, T* seq) : m_sequence(0), m_activeContext(context) {
_aquire(seq);
}
virtual ~SequenceHdl() {
_release();
}
void _aquire(T* s) {
InstanceCount::increment(this);
m_sequence = s;
m_sequence->addRef();
}
void _release() {
releasePtr(m_sequence);
InstanceCount::decrement(this);
}
void setContextToClients() {
(Geant4Action::ContextUpdate(m_activeContext))(m_sequence);
}
void releaseContextFromClients() {
Geant4Action::ContextUpdate(0)(m_sequence);
}
void createClientContext(const G4Run* run) {
Geant4Run* r = new Geant4Run(run);
m_activeContext->setRun(r);
setContextToClients();
}
void destroyClientContext(const G4Run*) {
Geant4Run* r = m_activeContext->runPtr();
releaseContextFromClients();
if ( r ) {
m_activeContext->setRun(0);
deletePtr(r);
}
}
void createClientContext(const G4Event* evt) {
Geant4Event* e = new Geant4Event(evt,s_globalRandom);
m_activeContext->setEvent(e);
setContextToClients();
}
void destroyClientContext(const G4Event*) {
Geant4Event* e = m_activeContext->eventPtr();
releaseContextFromClients();
if ( e ) {
m_activeContext->setEvent(0);
deletePtr(e);
}
}
class Geant4UserRunAction;
class Geant4UserEventAction;
* Concrete implementation of the Geant4 run action
*
* @author M.Frank
* @version 1.0
*/
struct Geant4UserRunAction : public G4UserRunAction, public SequenceHdl<Geant4RunActionSequence> {
Geant4UserRunAction(Geant4Context* context, Geant4RunActionSequence* seq)
virtual ~Geant4UserRunAction() {
}
/// Begin-of-run callback
virtual void BeginOfRunAction(const G4Run* run);
virtual void EndOfRunAction(const G4Run* run);
};
/** @class Geant4UserEventAction
* Concrete implementation of the Geant4 event action
*
* @author M.Frank
* @version 1.0
*/
struct Geant4UserEventAction : public G4UserEventAction, public SequenceHdl<Geant4EventActionSequence> {
Geant4UserEventAction(Geant4Context* context, Geant4EventActionSequence* seq)
virtual ~Geant4UserEventAction() {
}
/// Begin-of-event callback
virtual void BeginOfEventAction(const G4Event* evt);
virtual void EndOfEventAction(const G4Event* evt);
};
/** @class Geant4UserTrackingAction
* Concrete implementation of the Geant4 tracking action
*
* @author M.Frank
* @version 1.0
*/
struct Geant4UserTrackingAction : public G4UserTrackingAction, public SequenceHdl<Geant4TrackingActionSequence> {
Geant4UserTrackingAction(Geant4Context* context, Geant4TrackingActionSequence* seq)
: Base(context, seq) {
virtual ~Geant4UserTrackingAction() {
}
virtual void PreUserTrackingAction(const G4Track* trk) {
m_sequence->context()->kernel().setTrackMgr(fpTrackingManager);
virtual void PostUserTrackingAction(const G4Track* trk) {
m_sequence->end(trk);
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
};
/** @class Geant4UserStackingAction
* Concrete implementation of the Geant4 stacking action sequence
*
* @author M.Frank
* @version 1.0
*/
struct Geant4UserStackingAction : public G4UserStackingAction, public SequenceHdl<Geant4StackingActionSequence> {
Geant4UserStackingAction(Geant4Context* context, Geant4StackingActionSequence* seq)
: Base(context, seq) {
virtual ~Geant4UserStackingAction() {
}
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
virtual void PrepareNewEvent() {
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
};
/** @class Geant4UserGeneratorAction
* Concrete implementation of the Geant4 generator action
*
* @author M.Frank
* @version 1.0
*/
struct Geant4UserGeneratorAction : public G4VUserPrimaryGeneratorAction, public SequenceHdl<Geant4GeneratorActionSequence> {
Geant4UserGeneratorAction(Geant4Context* context, Geant4GeneratorActionSequence* seq)
: G4VUserPrimaryGeneratorAction(), Base(context, seq) {
virtual ~Geant4UserGeneratorAction() {
}
virtual void GeneratePrimaries(G4Event* event) {
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
};
/** @class Geant4UserSteppingAction
*
* Concrete implementation of the Geant4 stepping action
*
* @author M.Frank
* @version 1.0
*/
struct Geant4UserSteppingAction : public G4UserSteppingAction, public SequenceHdl<Geant4SteppingActionSequence> {
Geant4UserSteppingAction(Geant4Context* context, Geant4SteppingActionSequence* seq)
: Base(context, seq) {
virtual ~Geant4UserSteppingAction() {
/// User stepping callback
virtual void UserSteppingAction(const G4Step* s) {
(*m_sequence)(s, fpSteppingManager);
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/// Begin-of-run callback
void Geant4UserRunAction::BeginOfRunAction(const G4Run* run) {
createClientContext(run);
eventAction->setContextToClients();
m_sequence->begin(run);
}
/// End-of-run callback
void Geant4UserRunAction::EndOfRunAction(const G4Run* run) {
m_sequence->end(run);
eventAction->releaseContextFromClients();
destroyClientContext(run);
}
/// Begin-of-event callback
void Geant4UserEventAction::BeginOfEventAction(const G4Event* evt) {
runAction->setContextToClients();
setContextToClients();
m_sequence->begin(evt);
}
/// End-of-event callback
void Geant4UserEventAction::EndOfEventAction(const G4Event* evt) {
m_sequence->end(evt);
runAction->releaseContextFromClients();
destroyClientContext(evt);
}
#include "DDG4/Geant4DetectorConstruction.h"
#include "DDG4/Geant4UserPhysicsList.h"
#include "DDG4/Geant4Kernel.h"
using namespace std;
using namespace DD4hep;
using namespace DD4hep::Simulation;
// Geant4 include files
#include "G4RunManager.hh"
/// Configure the simulation
int Geant4Exec::configure(Geant4Kernel& kernel) {
CLHEP::HepRandom::setTheEngine(new CLHEP::RanecuEngine);
Geometry::LCDD& lcdd = kernel.lcdd();
Geant4Context* ctx = s_globalContext = new Geant4Context(&kernel);
// For now do this:
/* Geant4Random* rnd = */ s_globalRandom = new Geant4Random();
// Construct the default run manager
G4RunManager& runManager = kernel.runManager();
// Check if the geometry was loaded
printout(WARNING, "Geant4Exec", "+++ Only %d subdetectors present. "
"You sure you loaded the geometry properly?",int(lcdd.detectors().size()));
Geant4DetectorConstruction* detector = new Geant4DetectorConstruction(kernel);
runManager.SetUserInitialization(detector);
G4VUserPhysicsList* physics = 0;
Geant4PhysicsListActionSequence* seq = kernel.physicsList(false);
if (seq) {
string nam = kernel.physicsList().properties()["extends"].value<string>();
if (nam.empty())
nam = "EmptyPhysics";
physics = PluginService::Create<G4VUserPhysicsList*>(nam, seq, int(1));
}
else {
printout(INFO, "Geant4Exec", "+++ Using Geant4 physics constructor QGSP_BERT");
physics = PluginService::Create<G4VUserPhysicsList*>(string("QGSP_BERT"), seq, int(1));
}
if (0 == physics) {
throw runtime_error("Panic! No valid user physics list present!");
}
runManager.SetUserInitialization(physics);
// Set user generator action sequence. Not optional, since event context is defined inside
Geant4UserGeneratorAction* gen_action =
new Geant4UserGeneratorAction(ctx,kernel.generatorAction(false));
runManager.SetUserAction(gen_action);
// Set the run action sequence. Not optional, since run context is defined/destroyed inside
Geant4UserRunAction* run_action = new Geant4UserRunAction(ctx,kernel.runAction(false));
runManager.SetUserAction(run_action);
// Set the event action sequence. Not optional, since event context is destroyed inside
Geant4UserEventAction* evt_action = new Geant4UserEventAction(ctx,kernel.eventAction(false));
run_action->eventAction = evt_action;
evt_action->runAction = run_action;
// Set the tracking action sequence
if (kernel.trackingAction(false)) {
Geant4UserTrackingAction* action = new Geant4UserTrackingAction(ctx,kernel.trackingAction(false));
if (kernel.steppingAction(false)) {
Geant4UserSteppingAction* action = new Geant4UserSteppingAction(ctx,kernel.steppingAction(false));
runManager.SetUserAction(action);
}
// Set the stacking action sequence
if (kernel.stackingAction(false)) {
Geant4UserStackingAction* action = new Geant4UserStackingAction(ctx,kernel.stackingAction(false));
runManager.SetUserAction(action);
}
return 1;
}
/// Initialize the simulation
int Geant4Exec::initialize(Geant4Kernel& kernel) {
// Construct the default run manager
G4RunManager& runManager = kernel.runManager();
//
// Initialize G4 engine
//
runManager.Initialize();
return 1;
}
/// Run the simulation
int Geant4Exec::run(Geant4Kernel& kernel) {
Property& p = kernel.property("UI");
string value = p.value<string>();
if ( !value.empty() ) {
Geant4Action* ui = kernel.globalAction(value);
if ( ui ) {
Geant4Call* c = dynamic_cast<Geant4Call*>(ui);
if ( c ) {
(*c)(0);
return 1;
ui->except("++ Geant4Exec: Failed to start UI interface.");
throw runtime_error(format("Geant4Exec","++ Failed to locate UI interface %s.",value.c_str()));
long nevt = kernel.property("NumEvents").value<long>();
return 1;
}
/// Run the simulation
int Geant4Exec::terminate(Geant4Kernel&) {