LDMX Software
Simulator.cxx
Go to the documentation of this file.
1
8#include "SimCore/Simulator.h"
9
10#include <map>
11#include <memory>
12
14#include "Framework/Version.h"
15#include "Randomize.hh"
17#include "SimCore/BiasOperators/XsecBiasingOperator.h"
18#include "SimCore/DetectorConstruction.h"
19#include "SimCore/Event/HepMC3GenEvent.h"
20#include "SimCore/G4User/UserEventInformation.h"
22#include "SimCore/RunManager.h"
23#include "SimCore/SDs/SensitiveDetector.h"
24
25namespace simcore {
26
27Simulator::Simulator(const std::string& name, framework::Process& process)
28 : simcore::SimulatorBase(name, process) {}
29
33
35 // Get the detector header from the user detector construction
36 DetectorConstruction* detector =
37 dynamic_cast<RunManager*>(RunManager::GetRunManager())
38 ->getDetectorConstruction();
39
40 header.setDetectorName(detector->getDetectorName());
41 header.setDescription(parameters_.get<std::string>("description"));
42 header.setIntParameter(
43 "Included Scoring Planes",
44 !parameters_.get<std::string>("scoring_planes").empty());
45 header.setIntParameter("Use Random Seed from Event Header",
46 parameters_.get<bool>("root_primary_gen_use_seed"));
47
48 // lambda function for dumping 3-vectors into the run header
49 auto three_vector_dump = [&header](const std::string& name,
50 const std::vector<double>& vec) {
51 header.setFloatParameter(name + " X", vec.at(0));
52 header.setFloatParameter(name + " Y", vec.at(1));
53 header.setFloatParameter(name + " Z", vec.at(2));
54 };
55
56 auto beam_spot_smear{
57 parameters_.get<std::vector<double>>("beamSpotSmear", {})};
58 if (!beam_spot_smear.empty()) {
59 three_vector_dump("Smear Beam Spot [mm]", beam_spot_smear);
60 }
61
62 // lambda function for dumping vectors of strings to the run header
63 auto string_vector_dump = [&header](const std::string& name,
64 const std::vector<std::string>& vec) {
65 int index = 0;
66 for (auto const& val : vec) {
67 header.setStringParameter(name + " " + std::to_string(++index), val);
68 }
69 };
70
71 string_vector_dump(
72 "Pre Init Command",
73 parameters_.get<std::vector<std::string>>("pre_init_commands", {}));
74 string_vector_dump(
75 "Post Init Command",
76 parameters_.get<std::vector<std::string>>("post_init_commands", {}));
77
78 simcore::XsecBiasingOperator::Factory::get().apply(
79 [&header](auto bop) { bop->RecordConfig(header); });
80
81 int counter = 0;
82 PrimaryGenerator::Factory::get().apply([&header, &counter](auto gen) {
83 std::string gen_id = "Gen" + std::to_string(counter++);
84 gen->RecordConfig(gen_id, header);
85 });
86
87 // Set a string parameter with the Geant4 SHA-1.
88 if (G4RunManagerKernel::GetRunManagerKernel()) {
89 G4String g4_version{
90 G4RunManagerKernel::GetRunManagerKernel()->GetVersionString()};
91 header.setStringParameter("Geant4 revision", g4_version);
92 } else {
93 ldmx_log(warn) << "Unable to access G4 RunManager Kernel. Will not store "
94 "G4 Version string.";
95 }
96
97 header.setStringParameter("SIM version", LDMXSW_VERSION);
98 header.setStringParameter("SIM revision", GIT_SHA1);
99}
100
101void Simulator::onNewRun(const ldmx::RunHeader& runHeader) {
105 std::vector<int> seeds;
106 seeds.push_back(rseed.getSeed("Simulator[0]"));
107 seeds.push_back(rseed.getSeed("Simulator[1]"));
108 setSeeds(seeds);
109
110 run_ = runHeader.getRunNumber();
111}
112
114 // Generate and process a Geant4 event.
116 // Save the state of the random engine to an output stream. A string
117 // is then extracted and saved to the event header.
118 std::ostringstream stream;
119 G4Random::saveFullState(stream);
120
122 run_manager_->ProcessOneEvent(event.getEventHeader().getEventNumber());
123
124 // If a Geant4 event has been aborted, skip the rest of the processing
125 // sequence. This will immediately force the simulation to move on to
126 // the next event.
127 if (run_manager_->GetCurrentEvent()->IsAborted()) {
128 run_manager_->TerminateOneEvent(); // clean up event objects
129 SensitiveDetector::Factory::get().apply(
130 [](auto sd) { sd->onFinishedEvent(); });
131 this->abortEvent(); // get out of processors loop
132 }
133
134 // Terminate the event. This checks if an event is to be stored or
135 // stacked for later.
137
138 // store event-wide information in EventHeader
139 auto& event_header = event.getEventHeader();
140 updateEventHeader(event_header);
141
142 event_header.setStringParameter("eventSeed", stream.str());
143
144 auto event_info = static_cast<UserEventInformation*>(
145 run_manager_->GetCurrentEvent()->GetUserInformation());
146
147 auto hepmc3_events = event_info->getHepMC3GenEvents();
148 for (auto& hepmc3ev : hepmc3_events) {
149 hepmc3ev.event_number = event.getEventHeader().getEventNumber();
150 }
151 if (hepmc3_events.size() > 0) event.add("SimHepMC3Events", hepmc3_events);
152
153 saveTracks(event);
154
155 saveSDHits(event);
156
157 savePhotonuclearInteractions(event);
158
159 // Extract and save Bertini cascade histories if any were recorded
160 auto& history_store = bertini::CascadeHistoryStore::getInstance();
161 ldmx_log(debug) << "Checking cascade history store: "
162 << (history_store.empty() ? "empty" : "has histories");
163 if (!history_store.empty()) {
164 auto cascade_histories = history_store.extractHistories();
165 ldmx_log(info) << "Saving " << cascade_histories.size()
166 << " cascade histories to event";
167 event.add("PhotonuclearCascadeHistories", cascade_histories);
168 }
169
170 run_manager_->TerminateOneEvent();
171
172 return;
173}
174
177 // Put this to warn level, just so it's printed out for sure
178 ldmx_log(warn) << "Started " << num_events_began_ << " events to produce "
179 << num_events_completed_ << " events.";
180}
181
182void Simulator::setSeeds(std::vector<int> seeds) {
183 // If no seeds have been specified then return immediately.
184 if (seeds.empty()) {
185 return;
186 }
187
188 // If seeds are specified, make sure that the container has at least
189 // two seeds. If not, throw an exception.
190 if (seeds.size() == 1) {
191 EXCEPTION_RAISE("ConfigurationException",
192 "At least two seeds need to be specified.");
193 }
194
195 // Create the array of seeds and pass them to G4Random. Currently,
196 // only 100 seeds can be specified at a time. If less than 100
197 // seeds are specified, the remaining slots are set to 0.
198
199 constexpr int max_number_of_seeds{100};
200 std::vector<long> seed_vec(max_number_of_seeds, 0);
201 for (std::size_t index{0}; index < seeds.size(); ++index) {
202 seed_vec[index] = static_cast<long>(seeds[index]);
203 }
204
205 // Pass the array of seeds to the random engine.
206 G4Random::setTheSeeds(seed_vec.data());
207}
208
209} // namespace simcore
210
Thread-local storage for cascade histories during simulation.
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Header file for PrimaryGenerator.
Conditions object for random number seeds.
Class providing a Geant4 run manager implementation.
Run the G4 simulation inside of ldmx-app.
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
void abortEvent()
Abort the event immediately.
Implements an event buffer system for storing event data.
Definition Event.h:40
ldmx::EventHeader & getEventHeader()
Get the event header.
Definition Event.h:57
Class which represents the process under execution.
Definition Process.h:34
System for consistent seeding of random number generators.
static const std::string CONDITIONS_OBJECT_NAME
Conditions object name.
uint64_t getSeed(const std::string &name) const
Access a given seed by name.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
int getEventNumber() const
Return the event number.
Definition EventHeader.h:78
Run-specific configuration and data stored in its own output TTree alongside the event TTree in the o...
Definition RunHeader.h:68
void setFloatParameter(const std::string &name, float value)
Set a float parameter value.
Definition RunHeader.h:236
void setDetectorName(const std::string &det)
Set the name of the detector that was used in this run.
Definition RunHeader.h:102
void setStringParameter(const std::string &name, std::string value)
Set a string parameter value.
Definition RunHeader.h:261
void setDescription(const std::string &des)
Set the description of this run.
Definition RunHeader.h:119
void setIntParameter(const std::string &name, int value)
Set an int parameter value.
Definition RunHeader.h:211
int getRunNumber() const
Definition RunHeader.h:96
Implements the Geant4 detector construction.
Extension of Geant4 run manager.
Definition RunManager.h:39
std::unique_ptr< RunManager > run_manager_
Manager controlling G4 simulation run.
virtual void prepEvent(framework::Event &event)
prepare a new event before entering into the Geant4 simulation
void configure(framework::config::Parameters &parameters) override
Callback for the EventProcessor to configure itself from the given set of parameters.
void onProcessEnd() override
Callback called once processing is complete.
framework::config::Parameters parameters_
The parameters used to configure the simulation.
Producer that runs Geant4 simulation inside of ldmx-app.
Definition Simulator.h:62
void configure(framework::config::Parameters &parameters) override
Callback for the processor to configure itself from the given set of parameters.
Definition Simulator.cxx:30
Simulator(const std::string &name, framework::Process &process)
Constructor.
Definition Simulator.cxx:27
void beforeNewRun(ldmx::RunHeader &header) override
Given a non-const reference to the new RunHeader, we can add parameters from the simulation here befo...
Definition Simulator.cxx:34
void setSeeds(std::vector< int > seeds)
Set the seeds to be used by the Geant4 random engine.
void onNewRun(const ldmx::RunHeader &header) override
Before the run starts (but after the conditions are configured) set up the random seeds for this run.
virtual void produce(framework::Event &event) override
Run simulation and export results to output event.
int num_events_began_
Number of events started.
Definition Simulator.h:129
void onProcessEnd() override
Callback called once processing is complete.
int run_
the run number (for accessing the run header in onFileClose
Definition Simulator.h:135
int num_events_completed_
Number of events completed.
Definition Simulator.h:132
Encapsulates user defined information associated with a Geant4 event.
Dynamically loadable photonuclear models either from SimCore or external libraries implementing this ...