File indexing completed on 2025-01-30 09:17:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/Primitives.h>
0017 #include <DD4hep/InstanceCount.h>
0018 #include <DD4hep/Handle.h>
0019 #include <DDG4/Geant4RunAction.h>
0020 #include <DDG4/Geant4EventAction.h>
0021 #include <DDG4/Geant4SteppingAction.h>
0022 #include <DDG4/Geant4TrackingAction.h>
0023 #include <DDG4/Geant4StackingAction.h>
0024 #include <DDG4/Geant4GeneratorAction.h>
0025 #include <DDG4/Geant4UserInitialization.h>
0026 #include <DDG4/Geant4DetectorConstruction.h>
0027 #include <DDG4/Geant4PhysicsList.h>
0028 #include <DDG4/Geant4UIManager.h>
0029 #include <DDG4/Geant4Kernel.h>
0030 #include <DDG4/Geant4Random.h>
0031
0032
0033 #include <G4Version.hh>
0034 #include <G4UserRunAction.hh>
0035 #include <G4UserEventAction.hh>
0036 #include <G4UserTrackingAction.hh>
0037 #include <G4UserStackingAction.hh>
0038 #include <G4UserSteppingAction.hh>
0039 #include <G4VUserPhysicsList.hh>
0040 #include <G4VModularPhysicsList.hh>
0041 #include <G4VUserPrimaryGeneratorAction.hh>
0042 #include <G4VUserActionInitialization.hh>
0043 #include <G4VUserDetectorConstruction.hh>
0044
0045
0046 #include <memory>
0047 #include <stdexcept>
0048
0049 namespace {
0050 G4Mutex action_mutex=G4MUTEX_INITIALIZER;
0051 }
0052
0053
0054 namespace dd4hep {
0055
0056
0057 namespace sim {
0058
0059 class Geant4DetectorConstructionSequence;
0060
0061
0062
0063
0064
0065
0066
0067 template <typename T> class SequenceHdl {
0068 public:
0069 typedef SequenceHdl<T> Base;
0070 T* m_sequence;
0071 mutable Geant4Context* m_activeContext;
0072
0073 SequenceHdl()
0074 : m_sequence(0), m_activeContext(0) {
0075 }
0076
0077 SequenceHdl(Geant4Context* ctxt, T* seq) : m_sequence(0), m_activeContext(ctxt) {
0078 _aquire(seq);
0079 }
0080
0081 virtual ~SequenceHdl() {
0082 _release();
0083 }
0084
0085 void _aquire(T* s) {
0086 InstanceCount::increment(this);
0087 m_sequence = s;
0088 if ( m_sequence ) m_sequence->addRef();
0089 }
0090
0091 void _release() {
0092 detail::releasePtr(m_sequence);
0093 InstanceCount::decrement(this);
0094 }
0095
0096 void updateContext(Geant4Context* ctxt) {
0097 m_activeContext = ctxt;
0098 if ( m_sequence ) {
0099 m_sequence->updateContext(ctxt);
0100 }
0101 }
0102
0103 Geant4Context* context() const {
0104 return m_activeContext;
0105 }
0106
0107 Geant4Kernel& kernel() const {
0108 return context()->kernel();
0109 }
0110
0111 void configureFiber(Geant4Context* ctxt) {
0112 if ( m_sequence ) {
0113 m_sequence->configureFiber(ctxt);
0114 }
0115 }
0116
0117 void createClientContext(const G4Run* run) {
0118 Geant4Run* r = new Geant4Run(run);
0119 m_activeContext->setRun(r);
0120 }
0121
0122 void destroyClientContext(const G4Run*) {
0123 Geant4Run* r = m_activeContext->runPtr();
0124 if ( r ) {
0125 m_activeContext->setRun(0);
0126 detail::deletePtr(r);
0127 }
0128 }
0129
0130 void createClientContext(const G4Event* evt) {
0131 Geant4Event* e = new Geant4Event(evt,Geant4Random::instance());
0132 m_activeContext->setEvent(e);
0133 }
0134
0135 void destroyClientContext(const G4Event*) {
0136 Geant4Event* e = m_activeContext->eventPtr();
0137 if ( e ) {
0138 m_activeContext->setEvent(0);
0139 detail::deletePtr(e);
0140 }
0141 }
0142 };
0143
0144
0145 class Geant4UserRunAction;
0146 class Geant4UserEventAction;
0147
0148
0149
0150
0151
0152
0153
0154 class Geant4UserRunAction :
0155 public G4UserRunAction,
0156 public SequenceHdl<Geant4RunActionSequence>
0157 {
0158 public:
0159 Geant4UserEventAction* eventAction;
0160
0161 Geant4UserRunAction(Geant4Context* ctxt, Geant4RunActionSequence* seq)
0162 : Base(ctxt, seq), eventAction(0) {
0163 updateContext(ctxt);
0164 configureFiber(ctxt);
0165 }
0166
0167 virtual ~Geant4UserRunAction() {
0168 }
0169
0170 virtual void BeginOfRunAction(const G4Run* run) final;
0171
0172 virtual void EndOfRunAction(const G4Run* run) final;
0173 };
0174
0175
0176
0177
0178
0179
0180
0181 class Geant4UserEventAction :
0182 public G4UserEventAction,
0183 public SequenceHdl<Geant4EventActionSequence>
0184 {
0185 public:
0186 Geant4UserRunAction* runAction;
0187
0188 Geant4UserEventAction(Geant4Context* ctxt, Geant4EventActionSequence* seq)
0189 : Base(ctxt, seq), runAction(0) {
0190 updateContext(ctxt);
0191 configureFiber(ctxt);
0192 }
0193
0194 virtual ~Geant4UserEventAction() {
0195 }
0196
0197 virtual void BeginOfEventAction(const G4Event* evt) final;
0198
0199 virtual void EndOfEventAction(const G4Event* evt) final;
0200 };
0201
0202
0203
0204
0205
0206
0207
0208 class Geant4UserTrackingAction :
0209 public G4UserTrackingAction,
0210 public SequenceHdl<Geant4TrackingActionSequence>
0211 {
0212 public:
0213
0214 Geant4UserTrackingAction(Geant4Context* ctxt, Geant4TrackingActionSequence* seq)
0215 : Base(ctxt, seq) {
0216 updateContext(ctxt);
0217 configureFiber(ctxt);
0218 }
0219
0220 virtual ~Geant4UserTrackingAction() {
0221 }
0222
0223 virtual void PreUserTrackingAction(const G4Track* trk) final {
0224 m_sequence->context()->kernel().setTrackMgr(fpTrackingManager);
0225 m_sequence->begin(trk);
0226 }
0227
0228 virtual void PostUserTrackingAction(const G4Track* trk) final {
0229 m_sequence->end(trk);
0230 m_sequence->context()->kernel().setTrackMgr(0);
0231 }
0232 };
0233
0234
0235
0236
0237
0238
0239
0240 class Geant4UserStackingAction :
0241 public G4UserStackingAction,
0242 public SequenceHdl<Geant4StackingActionSequence>
0243 {
0244 public:
0245
0246 Geant4UserStackingAction(Geant4Context* ctxt, Geant4StackingActionSequence* seq)
0247 : Base(ctxt, seq) {
0248 updateContext(ctxt);
0249 configureFiber(ctxt);
0250 }
0251
0252 virtual ~Geant4UserStackingAction() {
0253 }
0254
0255 virtual void NewStage() override final {
0256 m_sequence->newStage(stackManager);
0257 }
0258
0259 virtual void PrepareNewEvent() override final {
0260 m_sequence->prepare(stackManager);
0261 }
0262 virtual G4ClassificationOfNewTrack ClassifyNewTrack(const G4Track* track) override final {
0263 auto ret = m_sequence->classifyNewTrack(stackManager, track);
0264 if ( ret.type != NoTrackClassification )
0265 return ret.value;
0266 return this->G4UserStackingAction::ClassifyNewTrack(track);
0267 }
0268 };
0269
0270
0271
0272
0273
0274
0275
0276
0277 class Geant4UserGeneratorAction :
0278 public G4VUserPrimaryGeneratorAction,
0279 public SequenceHdl<Geant4GeneratorActionSequence>
0280 {
0281 public:
0282
0283 Geant4UserGeneratorAction(Geant4Context* ctxt, Geant4GeneratorActionSequence* seq)
0284 : G4VUserPrimaryGeneratorAction(), Base(ctxt, seq) {
0285 updateContext(ctxt);
0286 configureFiber(ctxt);
0287 }
0288
0289 virtual ~Geant4UserGeneratorAction() {
0290 }
0291
0292 virtual void GeneratePrimaries(G4Event* event) final;
0293 };
0294
0295
0296
0297
0298
0299
0300
0301 class Geant4UserSteppingAction :
0302 public G4UserSteppingAction,
0303 public SequenceHdl<Geant4SteppingActionSequence>
0304 {
0305 public:
0306
0307 Geant4UserSteppingAction(Geant4Context* ctxt, Geant4SteppingActionSequence* seq)
0308 : Base(ctxt, seq) {
0309 updateContext(ctxt);
0310 configureFiber(ctxt);
0311 }
0312
0313 virtual ~Geant4UserSteppingAction() {
0314 }
0315
0316 virtual void UserSteppingAction(const G4Step* s) final {
0317 (*m_sequence)(s, fpSteppingManager);
0318 }
0319 };
0320
0321
0322
0323
0324
0325
0326
0327 class Geant4UserDetectorConstruction :
0328 public G4VUserDetectorConstruction,
0329 public SequenceHdl<Geant4DetectorConstructionSequence>
0330 {
0331 protected:
0332 Geant4DetectorConstructionContext m_ctxt;
0333 public:
0334
0335 Geant4UserDetectorConstruction(Geant4Context* ctxt, Geant4DetectorConstructionSequence* seq)
0336 : G4VUserDetectorConstruction(), Base(ctxt, seq),
0337 m_ctxt(ctxt->kernel().detectorDescription(), this)
0338 {
0339 }
0340
0341 virtual ~Geant4UserDetectorConstruction() {
0342 }
0343
0344 virtual void ConstructSDandField() final;
0345
0346 virtual G4VPhysicalVolume* Construct() final;
0347 };
0348
0349
0350
0351
0352
0353
0354
0355 class Geant4UserActionInitialization :
0356 public G4VUserActionInitialization,
0357 public SequenceHdl<Geant4UserInitializationSequence>
0358 {
0359 public:
0360
0361 Geant4UserActionInitialization(Geant4Context* ctxt, Geant4UserInitializationSequence* seq)
0362 : G4VUserActionInitialization(), Base(ctxt, seq) {
0363 }
0364
0365 virtual ~Geant4UserActionInitialization() {
0366 }
0367
0368 virtual void Build() const final;
0369
0370 virtual void BuildForMaster() const final;
0371 };
0372
0373
0374 void Geant4UserRunAction::BeginOfRunAction(const G4Run* run) {
0375 createClientContext(run);
0376 kernel().executePhase("begin-run",(const void**)&run);
0377 if ( m_sequence ) m_sequence->begin(run);
0378 kernel().applyInterruptHandlers();
0379 }
0380
0381
0382 void Geant4UserRunAction::EndOfRunAction(const G4Run* run) {
0383 if ( m_sequence ) m_sequence->end(run);
0384 kernel().executePhase("end-run",(const void**)&run);
0385 destroyClientContext(run);
0386 }
0387
0388
0389 void Geant4UserEventAction::BeginOfEventAction(const G4Event* evt) {
0390 kernel().executePhase("begin-event",(const void**)&evt);
0391 if ( m_sequence ) m_sequence->begin(evt);
0392 }
0393
0394
0395 void Geant4UserEventAction::EndOfEventAction(const G4Event* evt) {
0396 if ( m_sequence ) m_sequence->end(evt);
0397 kernel().executePhase("end-event",(const void**)&evt);
0398 destroyClientContext(evt);
0399 }
0400
0401
0402 void Geant4UserGeneratorAction::GeneratePrimaries(G4Event* event) {
0403 createClientContext(event);
0404 if ( m_sequence ) {
0405 (*m_sequence)(event);
0406 return;
0407 }
0408 throw std::runtime_error("GeneratePrimaries: Panic! No action sequencer defined. "
0409 "No primary particles can be produced.");
0410 }
0411
0412
0413 void Geant4UserDetectorConstruction::ConstructSDandField() {
0414 G4AutoLock protection_lock(&action_mutex);
0415 Geant4Context* ctx = m_sequence->context();
0416 Geant4Kernel& krnl = kernel().worker(Geant4Kernel::thread_self(),true);
0417 updateContext(krnl.workerContext());
0418 m_sequence->constructField(&m_ctxt);
0419 m_sequence->constructSensitives(&m_ctxt);
0420 updateContext(ctx);
0421 }
0422
0423
0424 G4VPhysicalVolume* Geant4UserDetectorConstruction::Construct() {
0425
0426
0427
0428 G4AutoLock protection_lock(&action_mutex);
0429 updateContext(m_sequence->context());
0430 m_sequence->constructGeo(&m_ctxt);
0431 if ( nullptr == m_ctxt.world ) {
0432 m_sequence->except("+++ Executing G4 detector construction did not result in a valid world volume!");
0433 }
0434 m_sequence->context()->kernel().setWorld(m_ctxt.world);
0435 return m_ctxt.world;
0436 }
0437
0438
0439 void Geant4UserActionInitialization::Build() const {
0440 G4AutoLock protection_lock(&action_mutex);
0441 Geant4Kernel& krnl = kernel().worker(Geant4Kernel::thread_self(),true);
0442 Geant4Context* ctx = krnl.workerContext();
0443
0444 if ( m_sequence ) {
0445 Geant4Context* old = m_sequence->context();
0446 m_sequence->info("+++ Executing Geant4UserActionInitialization::Build. "
0447 "Context:%p Kernel:%p [%ld]", (void*)ctx, (void*)&krnl, krnl.id());
0448
0449 m_sequence->updateContext(ctx);
0450 m_sequence->build();
0451 m_sequence->updateContext(old);
0452 }
0453
0454 Geant4UserGeneratorAction* gen_action = new Geant4UserGeneratorAction(ctx,krnl.generatorAction(false));
0455 SetUserAction(gen_action);
0456
0457
0458 Geant4UserRunAction* run_action = new Geant4UserRunAction(ctx,krnl.runAction(false));
0459 SetUserAction(run_action);
0460
0461
0462 Geant4UserEventAction* evt_action = new Geant4UserEventAction(ctx,krnl.eventAction(false));
0463 run_action->eventAction = evt_action;
0464 evt_action->runAction = run_action;
0465 SetUserAction(evt_action);
0466
0467
0468 Geant4TrackingActionSequence* trk_action = krnl.trackingAction(false);
0469 if ( trk_action ) {
0470 Geant4UserTrackingAction* action = new Geant4UserTrackingAction(ctx, trk_action);
0471 SetUserAction(action);
0472 }
0473
0474 Geant4SteppingActionSequence* stp_action = krnl.steppingAction(false);
0475 if ( stp_action ) {
0476 Geant4UserSteppingAction* action = new Geant4UserSteppingAction(ctx, stp_action);
0477 SetUserAction(action);
0478 }
0479
0480 Geant4StackingActionSequence* stk_action = krnl.stackingAction(false);
0481 if ( stk_action ) {
0482 Geant4UserStackingAction* action = new Geant4UserStackingAction(ctx, stk_action);
0483 SetUserAction(action);
0484 }
0485
0486 }
0487
0488
0489 void Geant4UserActionInitialization::BuildForMaster() const {
0490 if ( m_sequence ) {
0491 m_sequence->info("+++ Executing Geant4UserActionInitialization::BuildForMaster....");
0492 m_sequence->buildMaster();
0493 }
0494 }
0495
0496
0497
0498
0499
0500
0501
0502 class Geant4Compatibility {
0503 public:
0504
0505 Geant4Compatibility() = default;
0506
0507 virtual ~Geant4Compatibility() = default;
0508
0509 Geant4DetectorConstructionSequence* buildDefaultDetectorConstruction(Geant4Kernel& kernel);
0510 };
0511
0512 }
0513 }
0514
0515 #include <DD4hep/Detector.h>
0516 #include <DD4hep/Plugins.h>
0517 #include <DDG4/Geant4DetectorConstruction.h>
0518 #include <DDG4/Geant4Kernel.h>
0519
0520 using namespace dd4hep::sim;
0521
0522
0523 #include <G4RunManager.hh>
0524 #include <G4PhysListFactory.hh>
0525
0526
0527 Geant4DetectorConstructionSequence* Geant4Compatibility::buildDefaultDetectorConstruction(Geant4Kernel& kernel) {
0528 Geant4Action* cr;
0529 Geant4DetectorConstruction* det_cr;
0530 Geant4Context* ctx = kernel.workerContext();
0531 Geant4DetectorConstructionSequence* seq = kernel.detectorConstruction(true);
0532 printout(WARNING, "Geant4Exec", "+++ Building default Geant4DetectorConstruction for single threaded compatibility.");
0533
0534
0535 cr = PluginService::Create<Geant4Action*>("Geant4DetectorGeometryConstruction",ctx,std::string("ConstructGeometry"));
0536 det_cr = dynamic_cast<Geant4DetectorConstruction*>(cr);
0537 if ( det_cr )
0538 seq->adopt(det_cr);
0539 else
0540 throw std::runtime_error("Panic! Failed to build Geant4DetectorGeometryConstruction.");
0541
0542 cr = PluginService::Create<Geant4Action*>("Geant4DetectorSensitivesConstruction",ctx,std::string("ConstructSensitives"));
0543 det_cr = dynamic_cast<Geant4DetectorConstruction*>(cr);
0544 if ( det_cr )
0545 seq->adopt(det_cr);
0546 else
0547 throw std::runtime_error("Panic! Failed to build Geant4DetectorSensitivesConstruction.");
0548 return seq;
0549 }
0550
0551
0552 int Geant4Exec::configure(Geant4Kernel& kernel) {
0553 Detector& description = kernel.detectorDescription();
0554 Geant4Context* ctx = kernel.workerContext();
0555 Geant4Random* rndm = Geant4Random::instance(false);
0556
0557 if ( !rndm ) {
0558 rndm = new Geant4Random(ctx, "Geant4Random");
0559
0560 rndm->initialize();
0561 }
0562 Geant4Random::setMainInstance(rndm);
0563 kernel.executePhase("configure",0);
0564
0565
0566 G4RunManager& runManager = kernel.runManager();
0567
0568
0569 if (description.sensitiveDetectors().size() <= 1) {
0570 printout(WARNING, "Geant4Exec", "+++ Only %d subdetectors present. "
0571 "You sure you loaded the geometry properly?",
0572 int(description.sensitiveDetectors().size()));
0573 }
0574
0575
0576 Geant4DetectorConstructionSequence* user_det = kernel.detectorConstruction(false);
0577 if ( nullptr == user_det && kernel.isMultiThreaded() ) {
0578 throw std::runtime_error("Panic! No valid detector construction sequencer present. [Mandatory MT]");
0579 }
0580 if ( nullptr == user_det && !kernel.isMultiThreaded() ) {
0581 user_det = Geant4Compatibility().buildDefaultDetectorConstruction(kernel);
0582 }
0583 Geant4UserDetectorConstruction* det_seq = new Geant4UserDetectorConstruction(ctx,user_det);
0584 runManager.SetUserInitialization(det_seq);
0585
0586
0587 Geant4PhysicsListActionSequence* phys_seq = kernel.physicsList(false);
0588 if ( nullptr == phys_seq ) {
0589 std::string phys_model = "QGSP_BERT";
0590 phys_seq = kernel.physicsList(true);
0591 phys_seq->property("extends").set(phys_model);
0592 }
0593 G4VUserPhysicsList* physics = phys_seq->extensionList();
0594 if (nullptr == physics) {
0595 throw std::runtime_error("Panic! No valid user physics list present!");
0596 }
0597 #if 0
0598
0599 printout(INFO, "Geant4Exec", "+++ PhysicsList RangeCut: %f", phys_seq->m_rangecut );
0600 physics->SetDefaultCutValue(phys_seq->m_rangecut);
0601 physics->SetCuts();
0602 if( DEBUG == printLevel() ) physics->DumpCutValuesTable();
0603 #endif
0604 phys_seq->enable(physics);
0605 runManager.SetUserInitialization(physics);
0606
0607
0608 Geant4UserInitializationSequence* user_init = kernel.userInitialization(false);
0609 if ( nullptr == user_init && kernel.isMultiThreaded() ) {
0610 throw std::runtime_error("Panic! No valid user initialization sequencer present. [Mandatory MT]");
0611 }
0612 else if ( nullptr == user_init && !kernel.isMultiThreaded() ) {
0613
0614 user_init = kernel.userInitialization(true);
0615 }
0616 Geant4UserActionInitialization* init = new Geant4UserActionInitialization(ctx,user_init);
0617 runManager.SetUserInitialization(init);
0618 return 1;
0619 }
0620
0621
0622 int Geant4Exec::initialize(Geant4Kernel& kernel) {
0623
0624 G4RunManager& runManager = kernel.runManager();
0625
0626
0627
0628 kernel.applyInterruptHandlers();
0629 kernel.executePhase("initialize",0);
0630 runManager.Initialize();
0631 return 1;
0632 }
0633
0634
0635 int Geant4Exec::run(Geant4Kernel& kernel) {
0636 Property& p = kernel.property("UI");
0637 std::string value = p.value<std::string>();
0638
0639 kernel.executePhase("start",0);
0640 if ( !value.empty() ) {
0641 Geant4Action* ui = kernel.globalAction(value);
0642 if ( ui ) {
0643 Geant4Call* c = dynamic_cast<Geant4Call*>(ui);
0644 if ( c ) {
0645 (*c)(nullptr);
0646 kernel.executePhase("stop",0);
0647 return 1;
0648 }
0649 ui->except("++ Geant4Exec: Failed to start UI interface.");
0650 }
0651 throw std::runtime_error(format("Geant4Exec","++ Failed to locate UI interface %s.",value.c_str()));
0652 }
0653 long nevt = kernel.property("NumEvents").value<long>();
0654 kernel.applyInterruptHandlers();
0655 kernel.runManager().BeamOn(nevt);
0656 kernel.executePhase("stop",0);
0657 return 1;
0658 }
0659
0660
0661 int Geant4Exec::terminate(Geant4Kernel& kernel) {
0662 kernel.executePhase("terminate",0);
0663 return 1;
0664 }