Newer
Older
Markus Frank
committed
//==========================================================================
// AIDA Detector description implementation for LCD
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
Markus Frank
committed
// All rights reserved.
Markus Frank
committed
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
Markus Frank
committed
// Author : M.Frank
//
//==========================================================================
Markus Frank
committed
// Framework include files
#include "DD4hep/Printout.h"
#include "DD4hep/Primitives.h"
#include "DD4hep/InstanceCount.h"
#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"
Markus Frank
committed
// Geant4 include files
#include <G4Version.hh>
#include "G4UserRunAction.hh"
#include "G4UserEventAction.hh"
#include "G4UserTrackingAction.hh"
#include "G4UserStackingAction.hh"
#include "G4UserSteppingAction.hh"
#include "G4VUserPhysicsList.hh"
#include "G4VModularPhysicsList.hh"
#include "G4VUserPrimaryGeneratorAction.hh"
// C/C++ include files
/// Namespace for the AIDA detector description toolkit
/// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
namespace {
Geant4Context* s_globalContext = 0;
Geant4Random* s_globalRandom = 0;
}
Geant4Context* ddg4_globalContext() {
return s_globalContext;
}
/// Sequence handler implementing common actions to all sequences.
Markus Frank
committed
template <typename T> class SequenceHdl {
public:
Markus Frank
committed
: m_sequence(0), m_activeContext(0) {
Markus Frank
committed
SequenceHdl(Geant4Context* ctxt, T* seq) : m_sequence(0), m_activeContext(ctxt) {
Markus Frank
committed
_aquire(seq);
Markus Frank
committed
_release();
Markus Frank
committed
InstanceCount::increment(this);
m_sequence = s;
m_sequence->addRef();
Markus Frank
committed
releasePtr(m_sequence);
InstanceCount::decrement(this);
Markus Frank
committed
Geant4Context* context() const {
return m_activeContext;
}
Geant4Kernel& kernel() const {
return context()->kernel();
}
Markus Frank
committed
(Geant4Action::ContextUpdate(m_activeContext))(m_sequence);
Markus Frank
committed
Geant4Action::ContextUpdate(0)(m_sequence);
}
void createClientContext(const G4Run* run) {
Markus Frank
committed
Geant4Run* r = new Geant4Run(run);
m_activeContext->setRun(r);
setContextToClients();
Markus Frank
committed
Geant4Run* r = m_activeContext->runPtr();
releaseContextFromClients();
if ( r ) {
m_activeContext->setRun(0);
deletePtr(r);
}
}
void createClientContext(const G4Event* evt) {
Markus Frank
committed
Geant4Event* e = new Geant4Event(evt,s_globalRandom);
m_activeContext->setEvent(e);
setContextToClients();
}
void destroyClientContext(const G4Event*) {
Markus Frank
committed
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
/** @class Geant4UserRunAction
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
class Geant4UserRunAction : public G4UserRunAction, public SequenceHdl<Geant4RunActionSequence> {
public:
Markus Frank
committed
Geant4UserRunAction(Geant4Context* ctxt, Geant4RunActionSequence* seq)
: Base(ctxt, seq), eventAction(0) {
virtual ~Geant4UserRunAction() {
}
/// Begin-of-run callback
virtual void BeginOfRunAction(const G4Run* run);
virtual void EndOfRunAction(const G4Run* run);
/// Concrete implementation of the Geant4 event action
/** @class Geant4UserEventAction
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
class Geant4UserEventAction : public G4UserEventAction, public SequenceHdl<Geant4EventActionSequence> {
public:
Markus Frank
committed
Geant4UserEventAction(Geant4Context* ctxt, Geant4EventActionSequence* seq)
: Base(ctxt, seq), runAction(0) {
virtual ~Geant4UserEventAction() {
}
/// Begin-of-event callback
virtual void BeginOfEventAction(const G4Event* evt);
virtual void EndOfEventAction(const G4Event* evt);
/// Concrete implementation of the Geant4 tracking action
/** @class Geant4UserTrackingAction
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
class Geant4UserTrackingAction : public G4UserTrackingAction, public SequenceHdl<Geant4TrackingActionSequence> {
public:
Markus Frank
committed
Geant4UserTrackingAction(Geant4Context* ctxt, Geant4TrackingActionSequence* seq)
: Base(ctxt, seq) {
virtual ~Geant4UserTrackingAction() {
}
virtual void PreUserTrackingAction(const G4Track* trk) {
Markus Frank
committed
setContextToClients();
m_sequence->context()->kernel().setTrackMgr(fpTrackingManager);
virtual void PostUserTrackingAction(const G4Track* trk) {
m_sequence->end(trk);
Markus Frank
committed
m_sequence->context()->kernel().setTrackMgr(0);
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
/// Concrete implementation of the Geant4 stacking action sequence
/** @class Geant4UserStackingAction
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
class Geant4UserStackingAction : public G4UserStackingAction, public SequenceHdl<Geant4StackingActionSequence> {
public:
Markus Frank
committed
Geant4UserStackingAction(Geant4Context* ctxt, Geant4StackingActionSequence* seq)
: Base(ctxt, seq) {
virtual ~Geant4UserStackingAction() {
}
Markus Frank
committed
setContextToClients();
Markus Frank
committed
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
virtual void PrepareNewEvent() {
Markus Frank
committed
setContextToClients();
Markus Frank
committed
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
/// Concrete implementation of the Geant4 generator action
/** @class Geant4UserGeneratorAction
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
class Geant4UserGeneratorAction : public G4VUserPrimaryGeneratorAction, public SequenceHdl<Geant4GeneratorActionSequence> {
public:
Markus Frank
committed
Geant4UserGeneratorAction(Geant4Context* ctxt, Geant4GeneratorActionSequence* seq)
: G4VUserPrimaryGeneratorAction(), Base(ctxt, seq) {
virtual ~Geant4UserGeneratorAction() {
}
virtual void GeneratePrimaries(G4Event* event) {
Markus Frank
committed
createClientContext(event);
Markus Frank
committed
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
/// Concrete implementation of the Geant4 stepping action
/** @class Geant4UserSteppingAction
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
class Geant4UserSteppingAction : public G4UserSteppingAction, public SequenceHdl<Geant4SteppingActionSequence> {
public:
Markus Frank
committed
Geant4UserSteppingAction(Geant4Context* ctxt, Geant4SteppingActionSequence* seq)
: Base(ctxt, seq) {
virtual ~Geant4UserSteppingAction() {
/// User stepping callback
virtual void UserSteppingAction(const G4Step* s) {
Markus Frank
committed
setContextToClients();
(*m_sequence)(s, fpSteppingManager);
Markus Frank
committed
releaseContextFromClients(); //Let's leave this out for now...Frank has dirty tricks.
/// Begin-of-run callback
void Geant4UserRunAction::BeginOfRunAction(const G4Run* run) {
createClientContext(run);
Markus Frank
committed
kernel().executePhase("begin-run",(const void**)&run);
eventAction->setContextToClients();
m_sequence->begin(run);
}
/// End-of-run callback
void Geant4UserRunAction::EndOfRunAction(const G4Run* run) {
m_sequence->end(run);
Markus Frank
committed
kernel().executePhase("end-run",(const void**)&run);
eventAction->releaseContextFromClients();
destroyClientContext(run);
}
/// Begin-of-event callback
void Geant4UserEventAction::BeginOfEventAction(const G4Event* evt) {
runAction->setContextToClients();
setContextToClients();
Markus Frank
committed
kernel().executePhase("begin-event",(const void**)&evt);
m_sequence->begin(evt);
}
/// End-of-event callback
void Geant4UserEventAction::EndOfEventAction(const G4Event* evt) {
m_sequence->end(evt);
runAction->releaseContextFromClients();
Markus Frank
committed
kernel().executePhase("end-event",(const void**)&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();
Markus Frank
committed
kernel.executePhase("configure",0);
// 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.sensitiveDetectors().size()));
Geant4DetectorConstruction* detector = Geant4DetectorConstruction::instance(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
Markus Frank
committed
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
//
Markus Frank
committed
kernel.executePhase("initialize",0);
runManager.Initialize();
return 1;
}
/// Run the simulation
int Geant4Exec::run(Geant4Kernel& kernel) {
Property& p = kernel.property("UI");
string value = p.value<string>();
Markus Frank
committed
kernel.executePhase("start",0);
if ( !value.empty() ) {
Geant4Action* ui = kernel.globalAction(value);
if ( ui ) {
Geant4Call* c = dynamic_cast<Geant4Call*>(ui);
if ( c ) {
Markus Frank
committed
(*c)(0);
Markus Frank
committed
kernel.executePhase("stop",0);
Markus Frank
committed
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>();
Markus Frank
committed
kernel.executePhase("stop",0);
return 1;
}
/// Run the simulation
Markus Frank
committed
int Geant4Exec::terminate(Geant4Kernel& kernel) {
kernel.executePhase("terminate",0);