|
| 1 | +#include "G4VUserDetectorConstruction.hh" |
| 2 | +#include "G4VUserPrimaryGeneratorAction.hh" |
| 3 | +#include "G4UserEventAction.hh" |
| 4 | +#include "G4UserRunAction.hh" |
| 5 | +#include "G4ParticleGun.hh" |
| 6 | +#include "G4RunManager.hh" |
| 7 | +#include "G4UImanager.hh" |
| 8 | +#include "G4RunManagerFactory.hh" |
| 9 | +#include "QBBC.hh" |
| 10 | +#include "G4NistManager.hh" |
| 11 | +#include "G4Box.hh" |
| 12 | +#include "G4LogicalVolume.hh" |
| 13 | +#include "G4PVPlacement.hh" |
| 14 | +//#include "G4SystemOfUnits.hh" |
| 15 | +#include "globals.hh" |
| 16 | +#include "G4VUserActionInitialization.hh" |
| 17 | +#include <julia.h> |
| 18 | +#include <iostream> |
| 19 | + |
| 20 | +//---Detector construction class------------------------------------------------------------------- |
| 21 | +class DetectorConstruction : public G4VUserDetectorConstruction |
| 22 | +{ |
| 23 | + public: |
| 24 | + DetectorConstruction() = default; |
| 25 | + ~DetectorConstruction() override = default; |
| 26 | + G4VPhysicalVolume* Construct() override { |
| 27 | + auto nist = G4NistManager::Instance(); |
| 28 | + auto world_mat = nist->FindOrBuildMaterial("G4_AIR"); |
| 29 | + auto core_mat = nist->FindOrBuildMaterial("G4_WATER"); |
| 30 | + auto world_size = 1.0*CLHEP::m; |
| 31 | + auto solidWorld = new G4Box("World", world_size, world_size, world_size); |
| 32 | + auto logicWorld = new G4LogicalVolume(solidWorld, world_mat, "World"); |
| 33 | + auto physWorld = new G4PVPlacement(0, G4ThreeVector(), logicWorld, "World", 0, false, 0); |
| 34 | + auto core_size = 0.5*CLHEP::m; |
| 35 | + auto solidCore = new G4Box("Core", core_size, core_size, core_size); |
| 36 | + auto logicCore = new G4LogicalVolume(solidCore, core_mat, "Core"); |
| 37 | + new G4PVPlacement(0, G4ThreeVector(), logicCore, "Core", logicWorld, false, 0); |
| 38 | + return physWorld; |
| 39 | + } |
| 40 | +}; |
| 41 | + |
| 42 | +//---Primary generator action class---------------------------------------------------------------- |
| 43 | +class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction |
| 44 | +{ |
| 45 | +public: |
| 46 | + PrimaryGeneratorAction() { fParticleGun = new G4ParticleGun(); } |
| 47 | + ~PrimaryGeneratorAction() { delete fParticleGun; } |
| 48 | + void GeneratePrimaries(G4Event* anEvent) override { |
| 49 | + fPrimaryParticleName = fParticleGun->GetParticleDefinition()->GetParticleName(); |
| 50 | + fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0.,0.,1.)); |
| 51 | + fParticleGun->SetParticlePosition(G4ThreeVector(0.,0.,-1.*CLHEP::m)); |
| 52 | + fParticleGun->GeneratePrimaryVertex(anEvent); |
| 53 | + } |
| 54 | + G4ParticleGun* GetParticleGun() {return fParticleGun;}; |
| 55 | + const G4String& GetParticleName() { return fPrimaryParticleName;} |
| 56 | +private: |
| 57 | + G4String fPrimaryParticleName; |
| 58 | + G4ParticleGun* fParticleGun; |
| 59 | +}; |
| 60 | + |
| 61 | +typedef void (*stepaction_f)(const G4Step*); |
| 62 | +class SteppingAction : public G4UserSteppingAction |
| 63 | +{ |
| 64 | +public: |
| 65 | + SteppingAction() { |
| 66 | + action_jl = (stepaction_f)(jl_unbox_voidpointer(jl_eval_string("@cfunction(stepping_action, Nothing, (CxxPtr{G4Step},))"))); |
| 67 | + std::cout << "=====> " << action_jl << std::endl; |
| 68 | + } |
| 69 | + ~SteppingAction() {} |
| 70 | + void UserSteppingAction(const G4Step* step) override { action_jl(step); } |
| 71 | +private: |
| 72 | + stepaction_f action_jl; |
| 73 | +}; |
| 74 | + |
| 75 | +typedef void (*eventaction_f)(const G4Event*); |
| 76 | +class EventAction : public G4UserEventAction |
| 77 | +{ |
| 78 | + public: |
| 79 | + EventAction() { |
| 80 | + beginevent_jl = (eventaction_f)(jl_unbox_voidpointer(jl_eval_string("@cfunction(begin_of_event_action, Nothing, (CxxPtr{G4Event},))"))); |
| 81 | + endevent_jl = (eventaction_f)(jl_unbox_voidpointer(jl_eval_string("@cfunction(end_of_event_action, Nothing, (CxxPtr{G4Event},))"))); |
| 82 | + } |
| 83 | + ~EventAction() override = default; |
| 84 | + |
| 85 | + void BeginOfEventAction(const G4Event* event) override { beginevent_jl(event); } |
| 86 | + void EndOfEventAction(const G4Event* event) override { endevent_jl(event); } |
| 87 | + private: |
| 88 | + eventaction_f beginevent_jl; |
| 89 | + eventaction_f endevent_jl; |
| 90 | +}; |
| 91 | + |
| 92 | +typedef void (*runaction_f)(const G4Run*); |
| 93 | +class RunAction : public G4UserRunAction |
| 94 | +{ |
| 95 | + public: |
| 96 | + RunAction() { |
| 97 | + beginrun_jl = (runaction_f)(jl_unbox_voidpointer(jl_eval_string("@cfunction(begin_of_run_action, Nothing, (CxxPtr{G4Run},))"))); |
| 98 | + endrun_jl = (runaction_f)(jl_unbox_voidpointer(jl_eval_string("@cfunction(end_of_run_action, Nothing, (CxxPtr{G4Run},))"))); |
| 99 | + } |
| 100 | + ~RunAction() override = default; |
| 101 | + |
| 102 | + void BeginOfRunAction(const G4Run* run) override { beginrun_jl(run); } |
| 103 | + void EndOfRunAction(const G4Run* run) override { endrun_jl(run); } |
| 104 | + |
| 105 | + private: |
| 106 | + runaction_f beginrun_jl; |
| 107 | + runaction_f endrun_jl; |
| 108 | +}; |
| 109 | + |
| 110 | +//---Action initialization class------------------------------------------------------------------- |
| 111 | +class ActionInitialization : public G4VUserActionInitialization |
| 112 | +{ |
| 113 | + public: |
| 114 | + ActionInitialization() = default; |
| 115 | + ~ActionInitialization() override = default; |
| 116 | + void BuildForMaster() const override {} |
| 117 | + void Build() const override { |
| 118 | + SetUserAction(new PrimaryGeneratorAction); |
| 119 | + SetUserAction(new RunAction); |
| 120 | + SetUserAction(new EventAction); |
| 121 | + SetUserAction(new SteppingAction); |
| 122 | + } |
| 123 | +}; |
| 124 | + |
| 125 | +JULIA_DEFINE_FAST_TLS // only define this once, in an executable (not in a shared library) if you want fast code. |
| 126 | + |
| 127 | +//----Main program--------------------------------------------------------------------------------- |
| 128 | +int main(int, char**) |
| 129 | +{ |
| 130 | + //--- Required to setup the Julia context |
| 131 | + jl_init(); |
| 132 | + /* run Julia commands */ |
| 133 | + jl_eval_string("include(\"MyCode.jl\")"); |
| 134 | + if (jl_exception_occurred()) { |
| 135 | + std::cout << "=====> " << jl_typeof_str(jl_exception_occurred()) << std::endl; |
| 136 | + } |
| 137 | + |
| 138 | + //---Construct the default run manager |
| 139 | + auto runManager = G4RunManagerFactory::CreateRunManager(G4RunManagerType::Serial); |
| 140 | + |
| 141 | + //---Set mandatory initialization classes |
| 142 | + // Detector construction |
| 143 | + runManager->SetUserInitialization(new DetectorConstruction()); |
| 144 | + |
| 145 | + // Physics list |
| 146 | + runManager->SetUserInitialization(new QBBC(0)); |
| 147 | + |
| 148 | + // User action initialization |
| 149 | + runManager->SetUserInitialization(new ActionInitialization()); |
| 150 | + |
| 151 | + // Initialize G4 kernel |
| 152 | + runManager->Initialize(); |
| 153 | + |
| 154 | + // Get the pointer to the User Interface manager |
| 155 | + auto UImanager = G4UImanager::GetUIpointer(); |
| 156 | + UImanager->ApplyCommand("/control/verbose 1"); |
| 157 | + UImanager->ApplyCommand("/run/verbose 1"); |
| 158 | + //UImanager->ApplyCommand("/event/verbose 0"); |
| 159 | + //UImanager->ApplyCommand("/tracking/verbose 1"); |
| 160 | + UImanager->ApplyCommand("/gun/particle e+"); |
| 161 | + UImanager->ApplyCommand("/gun/energy 100 MeV"); |
| 162 | + UImanager->ApplyCommand("/run/beamOn 100000"); |
| 163 | + |
| 164 | + // Job termination |
| 165 | + delete runManager; |
| 166 | + |
| 167 | + // strongly recommended: notify Julia that the program is about to terminate. |
| 168 | + // this allows Julia time to cleanup pending write requests and run all finalizers |
| 169 | + jl_atexit_hook(0); |
| 170 | +} |
0 commit comments