Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-10 07:50:30

0001 /**
0002 U4App.h  : Geant4 Application in a header (formerly misnamed U4RecorderTest.h)
0003 =========================================================================================
0004 
0005 Note that the methods are not inlined, but that does not matter as this should only be included
0006 once into the main.  This is effectively providing a Geant4 application in a single header. 
0007 
0008 Geometry setup in U4App::Construct is done by U4VolumeMaker::PV 
0009 which is controlled by the GEOM envvar.  
0010 
0011 Note that this does not have access to CSGFoundry geometry, so the SEvt/sframe
0012 is a default one with zero ce.w extent. 
0013 
0014 **/
0015 
0016 #include <csignal>
0017 
0018 #include "G4RunManager.hh"
0019 #include "G4VUserDetectorConstruction.hh"
0020 #include "G4VUserPrimaryGeneratorAction.hh"
0021 #include "G4UserRunAction.hh"
0022 #include "G4UserEventAction.hh"
0023 #include "G4UserTrackingAction.hh"
0024 #include "G4UserSteppingAction.hh"
0025 
0026 #include "G4SystemOfUnits.hh"
0027 #include "G4ParticleTable.hh"
0028 #include "G4ParticleGun.hh"
0029 #include "G4GeometryManager.hh"
0030 
0031 #include "OPTICKS_LOG.hh"
0032 #include "SEvt.hh"
0033 #include "ssys.h"
0034 #include "SPath.hh"
0035 #include "SEventConfig.hh"
0036 #include "NP.hh"
0037 #include "sframe.h"
0038 
0039 #include "U4Material.hh"
0040 #include "U4VolumeMaker.hh"
0041 #include "U4Recorder.hh"
0042 #include "U4Random.hh"
0043 #include "U4Physics.hh"
0044 #include "U4VPrimaryGenerator.h"
0045 
0046 #ifdef WITH_PMTSIM
0047 #include "PMTSim.hh"
0048 #endif
0049 
0050 
0051 struct U4App
0052     : 
0053     public G4UserRunAction,  
0054     public G4UserEventAction,
0055     public G4UserTrackingAction,
0056     public G4UserSteppingAction,
0057     public G4VUserPrimaryGeneratorAction,
0058     public G4VUserDetectorConstruction
0059 {
0060     static const plog::Severity LEVEL ; 
0061     static std::string Desc(); 
0062     static char PrimaryMode(); 
0063     static G4ParticleGun* InitGun(); 
0064 
0065     G4RunManager*         fRunMgr ;  
0066     char                  fPrimaryMode ;  
0067     U4Recorder*           fRecorder ; 
0068     G4ParticleGun*        fGun ;  
0069     G4VPhysicalVolume*    fPV ; 
0070 
0071     G4VPhysicalVolume* Construct(); 
0072 
0073     void BeginOfRunAction(const G4Run*);
0074     void EndOfRunAction(const G4Run*);
0075 
0076     void GeneratePrimaries(G4Event* evt); 
0077     void BeginOfEventAction(const G4Event*);
0078     void EndOfEventAction(const G4Event*);
0079 
0080     void PreUserTrackingAction(const G4Track*);
0081     void PostUserTrackingAction(const G4Track*);
0082 
0083     void UserSteppingAction(const G4Step*);
0084 
0085 
0086     U4App(G4RunManager* runMgr); 
0087     virtual ~U4App(); 
0088 
0089     static void SaveMeta(const char* savedir); 
0090     static G4RunManager* InitRunManager(); 
0091     static U4App*        Create(); 
0092     void                 BeamOn() ;
0093     static void          Main(); 
0094 
0095 };
0096 
0097 const plog::Severity U4App::LEVEL = info ;   // PLOG logging level control doesnt work in the main 
0098 
0099 std::string U4App::Desc()
0100 {
0101     std::string phy = U4Physics::Desc() ; 
0102     std::string rec = U4Recorder::Desc() ; 
0103     std::stringstream ss ; 
0104     if(!phy.empty()) ss << phy  ; 
0105     if(!rec.empty()) ss << "/" << rec ; 
0106     std::string s = ss.str(); 
0107     return s ; 
0108 }
0109 
0110 char U4App::PrimaryMode()
0111 {
0112     char mode = '?' ; 
0113     const char* mode_ = ssys::getenvvar("U4App__PRIMARY_MODE", "gun" ); 
0114     if(strcmp(mode_, "gun")   == 0) mode = 'G' ; 
0115     if(strcmp(mode_, "torch") == 0) mode = 'T' ; 
0116     if(strcmp(mode_, "iphoton") == 0) mode = 'I' ;   // CAUTION: torch and iphoton both call U4VPrimaryGenerator::GeneratePrimaries
0117     return mode ;   
0118 }
0119 
0120 G4ParticleGun* U4App::InitGun()
0121 {
0122     G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
0123     G4ParticleDefinition* particle = particleTable->FindParticle("e+");
0124     LOG(LEVEL) << " particle " << particle ; 
0125     G4ParticleGun* gun = new G4ParticleGun(1) ;   
0126     gun->SetParticleDefinition(particle);
0127     gun->SetParticleTime(0.0*CLHEP::ns);
0128     gun->SetParticlePosition(G4ThreeVector(0.0*CLHEP::cm,0.0*CLHEP::cm,0.0*CLHEP::cm));
0129     gun->SetParticleMomentumDirection(G4ThreeVector(1.,0.,0.));
0130     gun->SetParticleEnergy(1.0*MeV); 
0131     return gun ; 
0132 }
0133 
0134 U4App::U4App(G4RunManager* runMgr)
0135     :
0136     fRunMgr(runMgr),
0137     fPrimaryMode(PrimaryMode()),
0138     fRecorder(new U4Recorder),
0139     fGun(fPrimaryMode == 'G' ? InitGun() : nullptr),
0140     fPV(nullptr)
0141 {
0142     fRunMgr->SetUserInitialization((G4VUserDetectorConstruction*)this);
0143     fRunMgr->SetUserAction((G4VUserPrimaryGeneratorAction*)this);
0144     fRunMgr->SetUserAction((G4UserRunAction*)this);
0145     fRunMgr->SetUserAction((G4UserEventAction*)this);
0146     fRunMgr->SetUserAction((G4UserTrackingAction*)this);
0147     fRunMgr->SetUserAction((G4UserSteppingAction*)this);
0148     fRunMgr->Initialize(); 
0149 
0150 }
0151 
0152 G4VPhysicalVolume* U4App::Construct()
0153 { 
0154     LOG(info) << "[" ; 
0155     const G4VPhysicalVolume* pv_ = U4VolumeMaker::PV() ;
0156     LOG_IF(fatal, pv_ == nullptr) << " FAILED TO CREATE PV : CHECK GEOM envvar " ;  
0157     if(pv_ == nullptr) std::raise(SIGINT) ; 
0158 
0159     G4VPhysicalVolume* pv = const_cast<G4VPhysicalVolume*>(pv_);  
0160     fPV = pv ; 
0161     LOG(LEVEL) << " fPV " << ( fPV ? fPV->GetName() : "ERR-NO-PV" ) ; 
0162 
0163     LOG(info) << "]" ; 
0164     return pv ; 
0165 }  
0166 
0167 // pass along the message to the recorder
0168 void U4App::BeginOfRunAction(const G4Run* run)
0169 { 
0170     LOG(info) ; 
0171     fRecorder->BeginOfRunAction(run);   
0172 }
0173 void U4App::EndOfRunAction(const G4Run* run)
0174 {   
0175     LOG(info); 
0176     fRecorder->EndOfRunAction(run);     
0177 }
0178 
0179 
0180 /**
0181 U4App::GeneratePrimaries
0182 ------------------------------------
0183 
0184 Other that for gun running this uses U4VPrimaryGenerator::GeneratePrimaries
0185 which is based on SGenerate::GeneratePhotons
0186 
0187 **/
0188 
0189 void U4App::GeneratePrimaries(G4Event* /*event*/)
0190 {   
0191     std::raise(SIGINT) ;  // THIS NEEDS REVISIT : FOLLOWING G4CXApp.h   
0192 
0193    /**
0194     LOG(LEVEL) << "[ fPrimaryMode " << fPrimaryMode  ; 
0195 
0196     if(fPrimaryMode == 'T')
0197     {
0198         SEvt::AddTorchGenstep();  
0199     }
0200 
0201     switch(fPrimaryMode)
0202     {
0203         case 'G': fGun->GeneratePrimaryVertex(event)              ; break ; 
0204         case 'T': U4VPrimaryGenerator::GeneratePrimaries(event);  ; break ; // eg from collected torch gensteps 
0205         case 'I': U4VPrimaryGenerator::GeneratePrimaries(event);  ; break ; // NOTE torch and iphoton are doing the same thing : misleading 
0206         default:  assert(0) ; break ; 
0207     }
0208     LOG(LEVEL) << "]" ; 
0209     **/
0210 }
0211 
0212 void U4App::BeginOfEventAction(const G4Event* event)
0213 {  
0214     // TOO LATE TO SEvt::AddTorchGenstep here as GeneratePrimaries already run 
0215     fRecorder->BeginOfEventAction(event); 
0216 }
0217 void U4App::EndOfEventAction(const G4Event* event)
0218 {   
0219     fRecorder->EndOfEventAction(event);  
0220 
0221     const char* savedir = SEvt::GetSaveDir(1); 
0222     SaveMeta(savedir); 
0223 
0224 #if defined(WITH_PMTSIM) && defined(POM_DEBUG)
0225     PMTSim::ModelTrigger_Debug_Save(savedir) ; 
0226 #else
0227     LOG(info) << "not-(WITH_PMTSIM and POM_DEBUG)"  ; 
0228 #endif
0229 }
0230 
0231 void U4App::PreUserTrackingAction(const G4Track* trk){  fRecorder->PreUserTrackingAction(trk); }
0232 void U4App::PostUserTrackingAction(const G4Track* trk){ fRecorder->PostUserTrackingAction(trk); }
0233 void U4App::UserSteppingAction(const G4Step* step){     fRecorder->UserSteppingAction(step) ; }
0234 
0235 
0236 U4App::~U4App(){  G4GeometryManager::GetInstance()->OpenGeometry(); }
0237 // G4GeometryManager::OpenGeometry is needed to avoid cleanup warning
0238 
0239 
0240 void U4App::SaveMeta(const char* savedir) // static
0241 {
0242     if(savedir == nullptr)
0243     {
0244         LOG(error) << " NULL savedir " ; 
0245         return ; 
0246     }  
0247     // U4Recorder::SaveMeta(savedir);   // try moving to U4Recorder::EndOfEventAction
0248     U4VolumeMaker::SaveTransforms(savedir) ;   
0249 }
0250 
0251 G4RunManager* U4App::InitRunManager()  // static
0252 {
0253     G4VUserPhysicsList* phy = (G4VUserPhysicsList*)new U4Physics ; 
0254     G4RunManager* run = new G4RunManager ; 
0255     run->SetUserInitialization(phy) ; 
0256     return run ; 
0257 }
0258 
0259 /**
0260 U4App::Create
0261 ----------------
0262 
0263 Geant4 requires G4RunManager to be instanciated prior to the Actions 
0264 
0265 **/
0266 
0267 U4App* U4App::Create()  // static 
0268 {
0269     LOG(info) << U4Recorder::Switches() ; 
0270 
0271     G4RunManager* run = InitRunManager(); 
0272     U4App* app = new U4App(run); 
0273     return app ; 
0274 }
0275 
0276 void U4App::BeamOn()
0277 {
0278     fRunMgr->BeamOn(ssys::getenvint("BeamOn",1)); 
0279 }
0280 
0281 
0282 
0283 void U4App::Main()  // static
0284 {
0285     LOG(info) << SLOG::Banner() ; 
0286 
0287     U4App* app = U4App::Create() ;  
0288     app->BeamOn(); 
0289     delete app ; 
0290 
0291     LOG(info) << SLOG::Banner() << " " << " savedir " << SEvt::GetSaveDir(1) ; 
0292 }
0293 
0294 
0295