File indexing completed on 2026-05-15 07:41:49
0001 #include "OpticsRun.hh"
0002
0003 #include <DD4hep/InstanceCount.h>
0004 #include <DDG4/Factories.h>
0005 #include <DDG4/Geant4Kernel.h>
0006
0007 #include <G4Material.hh>
0008 #include <G4MaterialPropertiesTable.hh>
0009 #include <G4Run.hh>
0010
0011 #include <chrono>
0012
0013 #include <G4CXOpticks.hh>
0014 #include <SEventConfig.hh>
0015 #include <SEvt.hh>
0016 #include <SSim.hh>
0017
0018 #include "DD4hepSensorIdentifier.hh"
0019
0020 namespace ddeicopticks
0021 {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 static void addOpticksPropertyAliases()
0033 {
0034 static const std::pair<const char *, const char *> aliases[] = {
0035 {"SCINTILLATIONCOMPONENT1", "FASTCOMPONENT"},
0036 {"SCINTILLATIONCOMPONENT2", "SLOWCOMPONENT"},
0037 };
0038
0039 auto const *matTable = G4Material::GetMaterialTable();
0040 for (auto const *mat : *matTable)
0041 {
0042 auto *mpt = mat->GetMaterialPropertiesTable();
0043 if (!mpt)
0044 continue;
0045
0046 for (auto const &[g4_11_name, g4_10_name] : aliases)
0047 {
0048 auto *prop = mpt->GetProperty(g4_11_name);
0049 if (prop && !mpt->GetProperty(g4_10_name))
0050 {
0051 bool createNewKey = true;
0052 mpt->AddProperty(g4_10_name, prop, createNewKey);
0053 }
0054 }
0055 }
0056 }
0057
0058
0059 OpticsRun::OpticsRun(dd4hep::sim::Geant4Context *ctxt, std::string const &name)
0060 : dd4hep::sim::Geant4RunAction(ctxt, name)
0061 {
0062 dd4hep::InstanceCount::increment(this);
0063 declareProperty("SaveGeometry", save_geometry_);
0064 }
0065
0066
0067 OpticsRun::~OpticsRun()
0068 {
0069 dd4hep::InstanceCount::decrement(this);
0070 }
0071
0072
0073 void OpticsRun::begin(G4Run const *run)
0074 {
0075 G4VPhysicalVolume *world = context()->world();
0076 if (!world)
0077 {
0078 except("OpticsRun: world volume is null at begin-of-run");
0079 return;
0080 }
0081
0082 info("Initializing G4CXOpticks geometry (run #%d)", run->GetRunID());
0083
0084
0085 addOpticksPropertyAliases();
0086
0087 SEvt::CreateOrReuse(SEvt::EGPU);
0088
0089
0090
0091
0092 static DD4hepSensorIdentifier dd4hep_sid;
0093 G4CXOpticks::SetSensorIdentifier(&dd4hep_sid);
0094
0095 bool hasDevice = SEventConfig::HasDevice();
0096 info("HasDevice=%s, IntegrationMode=%d", hasDevice ? "YES" : "NO", SEventConfig::IntegrationMode());
0097 G4CXOpticks::SetGeometry(world);
0098
0099 if (save_geometry_)
0100 {
0101 info("Saving Opticks geometry to disk");
0102 G4CXOpticks::SaveGeometry();
0103 }
0104
0105
0106 {
0107 const SSim *sim = SSim::Get();
0108 if (sim && sim->get_bnd())
0109 info("Boundary table: %zu boundaries", sim->get_bnd()->names.size());
0110 }
0111
0112 info("G4CXOpticks geometry initialized successfully");
0113 }
0114
0115
0116 void OpticsRun::end(G4Run const *run)
0117 {
0118
0119 SEvt *sev = SEvt::Get_EGPU();
0120 if (sev)
0121 {
0122 int64_t num_genstep = sev->getNumGenstepFromGenstep();
0123 int64_t num_photon = sev->getNumPhotonFromGenstep();
0124 if (num_genstep > 0)
0125 {
0126 G4CXOpticks *gx = G4CXOpticks::Get();
0127 if (gx)
0128 {
0129 int eventID = run->GetNumberOfEvent() > 0 ? run->GetNumberOfEvent() - 1 : 0;
0130 info("Flushing %lld remaining photons from %lld gensteps", static_cast<long long>(num_photon),
0131 static_cast<long long>(num_genstep));
0132
0133 auto t0 = std::chrono::high_resolution_clock::now();
0134 gx->simulate(eventID, false);
0135 auto t1 = std::chrono::high_resolution_clock::now();
0136 double ms = std::chrono::duration<double, std::milli>(t1 - t0).count();
0137
0138 unsigned num_hit = sev->getNumHit();
0139 info("OPTICKS_GPU_TIME event=%d ms=%.3f photons=%lld hits=%u", eventID, ms,
0140 static_cast<long long>(num_photon), num_hit);
0141
0142 sev->endOfEvent(eventID);
0143 gx->reset(eventID);
0144 }
0145 }
0146 }
0147
0148 info("Finalizing G4CXOpticks (run #%d)", run->GetRunID());
0149 G4CXOpticks::Finalize();
0150 }
0151
0152
0153 }
0154
0155 DECLARE_GEANT4ACTION_NS(ddeicopticks, OpticsRun)