File indexing completed on 2026-11-09 09:33:00
0001 #include <cstdlib>
0002 #include <future>
0003 #include <stdexcept>
0004 #include <vector>
0005
0006 #include "G4DynamicParticle.hh"
0007 #include "G4Electron.hh"
0008 #include "G4Material.hh"
0009 #include "G4Step.hh"
0010 #include "G4SystemOfUnits.hh"
0011 #include "G4Track.hh"
0012 #include "OpticksGenstep.h"
0013 #include "SEvt.hh"
0014 #include "U4.hh"
0015 #include "squad.h"
0016
0017 namespace
0018 {
0019 void Require(bool condition, const char* message)
0020 {
0021 if (!condition)
0022 throw std::runtime_error(message);
0023 }
0024
0025 std::vector<quad6> Collect(const G4Material* material, int photons)
0026 {
0027 G4Track track(new G4DynamicParticle(G4Electron::Definition(), {0., 0., 1.}, 1. * MeV),
0028 0., {1., 2., 3.});
0029 G4Step step;
0030 step.SetTrack(&track);
0031 track.SetStep(&step);
0032 track.SetTrackID(17);
0033 step.SetStepLength(2. * mm);
0034 step.GetPreStepPoint()->SetMaterial(const_cast<G4Material*>(material));
0035 step.GetPreStepPoint()->SetPosition({1., 2., 3.});
0036 step.GetPostStepPoint()->SetPosition({1., 2., 5.});
0037 step.GetPreStepPoint()->SetVelocity(200. * mm / ns);
0038 step.GetPostStepPoint()->SetVelocity(150. * mm / ns);
0039 std::vector<quad6> buffer;
0040 for (int i = 0; i < 32; ++i)
0041 {
0042 U4::CollectGenstep_G4Cerenkov_modified(
0043 &track, &step, photons, 1.1, 2. * eV, 3. * eV, 0.9, 0.19, 10., 12., &buffer);
0044 U4::CollectGenstep_Scintillation(&track, &step, photons + 1, 0, 12. * ns, &buffer);
0045 }
0046 return buffer;
0047 }
0048 }
0049
0050 int main()
0051 {
0052 Require(!SEvt::Exists(SEvt::EGPU) && !SEvt::Exists(SEvt::ECPU), "Unexpected global event");
0053 G4Electron::Definition();
0054 G4Material material("buffer_test", 1., 1. * g / mole, 1. * g / cm3);
0055 std::vector<std::future<std::vector<quad6>>> workers;
0056 #ifdef G4MULTITHREADED
0057 constexpr auto launch_policy = std::launch::async;
0058 #else
0059
0060 constexpr auto launch_policy = std::launch::deferred;
0061 #endif
0062 for (int worker = 0; worker < 4; ++worker)
0063 workers.push_back(std::async(launch_policy, [&material, worker] {
0064 return Collect(&material, 3 + worker);
0065 }));
0066 for (int worker = 0; worker < 4; ++worker)
0067 {
0068 const auto buffer = workers[worker].get();
0069 Require(buffer.size() == 64, "A worker lost or shared gensteps");
0070 for (int i = 0; i < 64; ++i)
0071 {
0072 const auto& genstep = buffer[i];
0073 Require(genstep.gentype() == (i % 2 == 0 ? OpticksGenstep_G4Cerenkov_modified
0074 : OpticksGenstep_SCINTILLATION),
0075 "Incorrect genstep process");
0076 Require(genstep.numphoton() == 3 + worker + i % 2, "Worker photon counts were mixed");
0077 Require(genstep.matline() == material.GetIndex() + SEvt::G4_INDEX_OFFSET,
0078 "Material mapping must wait until GPU submission");
0079 Require(genstep.q0.i.y == 17, "Track identity was lost");
0080 Require(genstep.q1.f.x == 1.f && genstep.q2.f.z == 2.f, "Step geometry was lost");
0081 }
0082 }
0083 Require(!SEvt::Exists(SEvt::EGPU) && !SEvt::Exists(SEvt::ECPU), "Collection created global events");
0084 setenv(U4::CollectGenstep_G4Cerenkov_modified_DISABLE, "1", 1);
0085 setenv(U4::CollectGenstep_Scintillation_DISABLE, "1", 1);
0086 Require(Collect(&material, 3).empty(), "Disabled processes still collected gensteps");
0087 unsetenv(U4::CollectGenstep_G4Cerenkov_modified_DISABLE);
0088 unsetenv(U4::CollectGenstep_Scintillation_DISABLE);
0089 return 0;
0090 }