LDMX Software
simcore::generators::GenieGenerator Class Reference

Class that uses GENIE's GEVGDriver to generator eN interactions. More...

#include <GenieGenerator.h>

Public Member Functions

 GenieGenerator (const std::string &name, const framework::config::Parameters &parameters)
 Constructor.
 
 ~GenieGenerator ()
 Destructor.
 
void GeneratePrimaryVertex (G4Event *event) final override
 Generate the primary vertices in the Geant4 event.
 
void RecordConfig (const std::string &id, ldmx::RunHeader &rh) final override
 Record the configuration of the primary generator into the run header.
 
- Public Member Functions inherited from simcore::PrimaryGenerator
 PrimaryGenerator (const std::string &name, const framework::config::Parameters &parameters)
 Constructor.
 
 DECLARE_FACTORY_WITH_WAREHOUSE (PrimaryGenerator, std::shared_ptr< PrimaryGenerator >, const std::string &, const framework::config::Parameters &)
 
virtual ~PrimaryGenerator ()=default
 Destructor.
 
std::string name ()
 
void smearBeamspot (G4PrimaryVertex *primary_vertex)
 Apply beam spot smearing to a primary vertex.
 
bool useBeamspot () const
 Check if beam spot smearing is enabled for this generator.
 

Private Member Functions

void fillConfig (const framework::config::Parameters &)
 
bool validateConfig ()
 fill the configuration
 
void initializeGENIE ()
 simple validation check on configuration params
 
void calculateTotalXS ()
 GENIE initialization.
 

Private Attributes

std::vector< genie::GEVGDriver > evg_drivers_
 One GENIE event generator driver per target and convertor to HepMC3GenEvent.
 
genie::HepMC3Converter hep_mc3_converter_
 
double energy_
 
std::vector< int > targets_
 
std::vector< double > abundances_
 
std::vector< double > position_
 
std::vector< double > beam_size_
 
float target_thickness_
 
float time_
 
std::vector< double > direction_
 
std::string tune_
 
std::string spline_file_
 
std::string message_threshold_file_
 
std::vector< float > ev_weighting_integral_
 
size_t n_events_generated_
 
std::vector< size_t > n_events_by_target_
 
std::vector< float > xsec_by_target_
 
float xsec_total_
 

Additional Inherited Members

- Protected Attributes inherited from simcore::PrimaryGenerator
std::string name_ {""}
 Name of the PrimaryGenerator.
 
bool use_beamspot_ {false}
 Flag denoting whether beam spot smearing is enabled for this generator.
 
double beamspot_x_size_ {0}
 Extent of the beamspot in x [mm].
 
double beamspot_y_size_ {0}
 Extent of the beamspot in y [mm].
 
double beamspot_z_size_ {0}
 Extent of the beamspot in z [mm].
 

Detailed Description

Class that uses GENIE's GEVGDriver to generator eN interactions.

Definition at line 42 of file GenieGenerator.h.

Constructor & Destructor Documentation

◆ GenieGenerator()

simcore::generators::GenieGenerator::GenieGenerator ( const std::string & name,
const framework::config::Parameters & parameters )

Constructor.

Parameters
parametersParameters used to configure GENIE generator.

Parameters: energy : energy of initial electron (GeV) targets : list of ten-digit 10LZZZAAAI target codes abundances: list of relative abundances for the given targets position : position of interaction from (mm three-vector) time : time to shoot at (ns) direction : direction to shoot in (unitless three-vector) tune : name of GENIE tune seed : seed for random generator

Definition at line 235 of file GenieGenerator.cxx.

237 : PrimaryGenerator(name, p) {
238 fillConfig(p);
239
240 if (!validateConfig())
241 EXCEPTION_RAISE("ConfigurationException", "Configuration not valid.");
242
243 n_events_generated_ = 0;
246}
PrimaryGenerator(const std::string &name, const framework::config::Parameters &parameters)
Constructor.
void calculateTotalXS()
GENIE initialization.
void initializeGENIE()
simple validation check on configuration params
bool validateConfig()
fill the configuration

References calculateTotalXS(), initializeGENIE(), and validateConfig().

◆ ~GenieGenerator()

simcore::generators::GenieGenerator::~GenieGenerator ( )

Destructor.

Definition at line 248 of file GenieGenerator.cxx.

248 {
249 ldmx_log(info) << "--- GENIE Generation Summary BEGIN ---";
250 double total_xsec = 0;
251 for (size_t i_t = 0; i_t < targets_.size(); ++i_t) {
252 ldmx_log(info) << "Target=" << targets_[i_t]
253 << "\tAbundance=" << abundances_[i_t] << "\tXSEC="
254 << xsec_by_target_[i_t] / genie::units::millibarn << " mb"
255 << "\tEvents=" << n_events_by_target_[i_t];
256 if (n_events_by_target_[i_t] > 0)
257 total_xsec += xsec_by_target_[i_t] * abundances_[i_t];
258 }
259
260 ldmx_log(info) << "Total events generated = " << n_events_generated_
261 << "\nTotal XSEC = " << total_xsec / genie::units::millibarn
262 << " mb";
263
264 ldmx_log(info) << "--- GENIE Generation Summary *END* ---";
265}

Member Function Documentation

◆ calculateTotalXS()

void simcore::generators::GenieGenerator::calculateTotalXS ( )
private

GENIE initialization.

Definition at line 191 of file GenieGenerator.cxx.

191 {
192 // initializing...
193 xsec_total_ = 0;
194 ev_weighting_integral_.resize(targets_.size(), 0.0);
195 evg_drivers_.resize(targets_.size());
196
197 // calculate the total xsec per target...
198 for (size_t i_t = 0; i_t < targets_.size(); ++i_t) {
199 genie::InitialState initial_state(targets_[i_t], 11);
200 evg_drivers_[i_t].SetEventGeneratorList(
201 genie::RunOpt::Instance()->EventGeneratorList());
202 evg_drivers_[i_t].SetUnphysEventMask(
203 *genie::RunOpt::Instance()->UnphysEventMask());
204 evg_drivers_[i_t].Configure(initial_state);
205 evg_drivers_[i_t].UseSplines();
206
207 // setup the initial election
208 TParticle initial_e;
209 initial_e.SetPdgCode(11);
210 auto elec_i_p = std::sqrt(energy_ * energy_ -
211 initial_e.GetMass() * initial_e.GetMass());
212 initial_e.SetMomentum(elec_i_p * direction_[0], elec_i_p * direction_[1],
213 elec_i_p * direction_[2], energy_);
214 TLorentzVector e_p4;
215 initial_e.Momentum(e_p4);
216
217 xsec_by_target_[i_t] = evg_drivers_[i_t].XSecSum(e_p4);
218 xsec_total_ += xsec_by_target_[i_t] * abundances_[i_t];
219
220 ev_weighting_integral_[i_t] = xsec_total_; // running sum
221
222 // print...
223 ldmx_log(debug) << "Target=" << targets_[i_t]
224 << "\tAbundance=" << abundances_[i_t] << "\tXSEC="
225 << xsec_by_target_[i_t] / genie::units::millibarn << "mb";
226 }
227 ldmx_log(debug) << "Total XSEC = " << xsec_total_ / genie::units::millibarn
228 << " mb";
229
230 // renormalize our weighting integral
231 for (size_t i_t = 0; i_t < ev_weighting_integral_.size(); ++i_t)
232 ev_weighting_integral_[i_t] = ev_weighting_integral_[i_t] / xsec_total_;
233}
std::vector< genie::GEVGDriver > evg_drivers_
One GENIE event generator driver per target and convertor to HepMC3GenEvent.

References evg_drivers_.

Referenced by GenieGenerator().

◆ fillConfig()

void simcore::generators::GenieGenerator::fillConfig ( const framework::config::Parameters & p)
private

Definition at line 61 of file GenieGenerator.cxx.

61 {
62 energy_ = p.get<double>("energy"); // * GeV;
63
64 targets_ = p.get<std::vector<int> >("targets");
65 abundances_ = p.get<std::vector<double> >("abundances");
66
67 time_ = p.get<double>("time"); // * ns;
68 position_ = p.get<std::vector<double> >("position"); // mm
69 beam_size_ = p.get<std::vector<double> >("beam_size"); // mm
70 direction_ = p.get<std::vector<double> >("direction");
71 target_thickness_ = p.get<double>("target_thickness"); // mm
72
73 tune_ = p.get<std::string>("tune");
74 spline_file_ = p.get<std::string>("spline_file");
75
76 message_threshold_file_ = p.get<std::string>("message_threshold_file");
77}
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78

◆ GeneratePrimaryVertex()

void simcore::generators::GenieGenerator::GeneratePrimaryVertex ( G4Event * event)
finaloverridevirtual

Generate the primary vertices in the Geant4 event.

Parameters
eventThe Geant4 event.

Implements simcore::PrimaryGenerator.

Definition at line 267 of file GenieGenerator.cxx.

267 {
268 if (n_events_generated_ == 0) {
269 // set random seed
270 // have to do this here since seeds aren't properly set until we know the
271 // run number
272 auto seed = G4Random::getTheEngine()->getSeed();
273 ldmx_log(debug) << "Initializing GENIE with seed " << seed;
274 genie::utils::app_init::RandGen(seed);
275 }
276
277 auto nucl_target_i = 0;
278
279 if (targets_.size() > 0) {
280 double rand_uniform = G4Random::getTheGenerator()->flat();
281
282 nucl_target_i = std::distance(
283 ev_weighting_integral_.begin(),
284 std::lower_bound(ev_weighting_integral_.begin(),
285 ev_weighting_integral_.end(), rand_uniform));
286
287 ldmx_log(debug) << "Random number = " << rand_uniform << ", target picked "
288 << targets_.at(nucl_target_i);
289 }
290
291 auto x_pos = position_[0] +
292 (G4Random::getTheGenerator()->flat() - 0.5) * beam_size_[0];
293 auto y_pos = position_[1] +
294 (G4Random::getTheGenerator()->flat() - 0.5) * beam_size_[1];
295 auto z_pos = position_[2] +
296 (G4Random::getTheGenerator()->flat() - 0.5) * target_thickness_;
297
298 ldmx_log(debug) << "Generating interaction at (x_,y_,z_)=" << "(" << x_pos
299 << "," << y_pos << "," << z_pos << ")";
300
301 // setup the initial election
302 TParticle initial_e;
303 initial_e.SetPdgCode(11);
304 float elec_i_p =
305 std::sqrt(energy_ * energy_ - initial_e.GetMass() * initial_e.GetMass());
306 initial_e.SetMomentum(elec_i_p * direction_[0], elec_i_p * direction_[1],
307 elec_i_p * direction_[2], energy_);
308 TLorentzVector e_p4;
309 initial_e.Momentum(e_p4);
310
311 ldmx_log(debug) << "Generating interation with (px,py,pz,e)=" << "("
312 << e_p4.Px() << "," << e_p4.Py() << "," << e_p4.Pz() << ","
313 << e_p4.E() << ")";
314
315 n_events_by_target_[nucl_target_i] += 1;
316
317 // GENIE magic — use the pre-configured driver for this target
318 genie::EventRecord* genie_event = NULL;
319 while (!genie_event)
320 genie_event = evg_drivers_[nucl_target_i].GenerateEvent(e_p4);
321
322 auto ev_info = new UserEventInformation;
323 auto hepmc3_genie = hep_mc3_converter_.ConvertToHepMC3(*genie_event);
324 ldmx::HepMC3GenEvent hepmc3_ldmx_genie;
325 hepmc3_genie->write_data(hepmc3_ldmx_genie);
326 ev_info->addHepMC3GenEvent(hepmc3_ldmx_genie);
327 event->SetUserInformation(ev_info);
328
329 // setup the primary vertex now
330
331 G4PrimaryVertex* vertex = new G4PrimaryVertex();
332 vertex->SetPosition(x_pos, y_pos, z_pos);
333 vertex->SetWeight(genie_event->Weight());
334
335 // loop over the entries and add to the G4Event
336 int n_entries = genie_event->GetEntries();
337
338 ldmx_log(debug) << "---------- " << "Generated Event "
339 << n_events_generated_ + 1 << " ----------";
340
341 for (int i_p = 0; i_p < n_entries; ++i_p) {
342 genie::GHepParticle* p = (genie::GHepParticle*)(*genie_event)[i_p];
343
344 // make sure it's a final state particle
345 if (p->Status() != 1) continue;
346
347 ldmx_log(debug) << "\tAdding particle " << p->Pdg() << " with status "
348 << p->Status() << " energy " << p->E() << " ...";
349
350 G4PrimaryParticle* primary = new G4PrimaryParticle();
351 primary->SetPDGcode(p->Pdg());
352
353 // this sets the 4momentum. But may not respect masses in G4...
354 // primary->Set4Momentum(p->Px() * CLHEP::GeV, p->Py() * CLHEP::GeV,
355 // p->Pz() * CLHEP::GeV, p->E() * CLHEP::GeV);
356
357 // for now, do this to set the masses to be the G4 ones, through the PDG
358 // code
359 primary->SetMomentum(p->Px() * CLHEP::GeV, p->Py() * CLHEP::GeV,
360 p->Pz() * CLHEP::GeV);
361
362 primary->SetProperTime(time_ * CLHEP::ns);
363
364 UserPrimaryParticleInformation* primary_info =
365 new UserPrimaryParticleInformation();
366 primary_info->setHepEvtStatus(1);
367 primary->SetUserInformation(primary_info);
368
369 vertex->SetPrimary(primary);
370 }
371
372 // add the vertex to the event
373 event->AddPrimaryVertex(vertex);
374
375 // Apply beam spot smearing if configured for this generator
376 if (useBeamspot()) {
377 smearBeamspot(vertex);
378 }
379
380 ++n_events_generated_;
381 delete genie_event;
382}
bool useBeamspot() const
Check if beam spot smearing is enabled for this generator.
void smearBeamspot(G4PrimaryVertex *primary_vertex)
Apply beam spot smearing to a primary vertex.

References evg_drivers_, simcore::UserPrimaryParticleInformation::setHepEvtStatus(), simcore::PrimaryGenerator::smearBeamspot(), and simcore::PrimaryGenerator::useBeamspot().

◆ initializeGENIE()

void simcore::generators::GenieGenerator::initializeGENIE ( )
private

simple validation check on configuration params

Definition at line 165 of file GenieGenerator.cxx.

165 {
166 // initialize some RunOpt by hacking the command line interface
167 {
168 char* in_arr[3] = {const_cast<char*>(""),
169 const_cast<char*>("--event-generator-list"),
170 const_cast<char*>("EM")};
171 genie::RunOpt::Instance()->ReadFromCommandLine(3, in_arr);
172 }
173
174 // set message thresholds
175 genie::utils::app_init::MesgThresholds(message_threshold_file_);
176
177 // set tune info
178 genie::RunOpt::Instance()->SetTuneName(tune_);
179 if (!genie::RunOpt::Instance()->Tune()) {
180 EXCEPTION_RAISE("ConfigurationException", "No TuneId in RunOption.");
181 }
182 genie::RunOpt::Instance()->BuildTune();
183
184 // give it the splint file and require it
185 genie::utils::app_init::XSecTable(spline_file_, true);
186
187 // set GHEP print level (needed?)
188 genie::GHepRecord::SetPrintLevel(0);
189}

Referenced by GenieGenerator().

◆ RecordConfig()

void simcore::generators::GenieGenerator::RecordConfig ( const std::string & id,
ldmx::RunHeader & rh )
finaloverridevirtual

Record the configuration of the primary generator into the run header.

Note
you must include the id number in each entry into the run header just in case there are other generators

Implements simcore::PrimaryGenerator.

Definition at line 384 of file GenieGenerator.cxx.

384 {
385 rh.setStringParameter(id + " Class", "simcore::generators::GenieGenerator");
386 rh.setStringParameter(id + "GenieTune", tune_);
387}
void setStringParameter(const std::string &name, std::string value)
Set a string parameter value.
Definition RunHeader.h:222

References ldmx::RunHeader::setStringParameter().

◆ validateConfig()

bool simcore::generators::GenieGenerator::validateConfig ( )
private

fill the configuration

Definition at line 79 of file GenieGenerator.cxx.

79 {
80 bool ret = true;
81
82 if (targets_.size() == 0 || abundances_.size() == 0) {
83 ldmx_log(error) << "targets and/or abundances sizes are zero." << " "
84 << targets_.size() << ", " << abundances_.size();
85 ret = false;
86 }
87 if (targets_.size() != abundances_.size()) {
88 ldmx_log(error) << "targets and abundances sizes unequal." << " "
89 << targets_.size() << " != " << abundances_.size();
90 ret = false;
91 }
92
93 if (position_.size() != 3 || direction_.size() != 3) {
94 ldmx_log(error) << "position and/or direction sizes are not 3." << " "
95 << position_.size() << ", " << direction_.size();
96 ret = false;
97 }
98
99 if (target_thickness_ < 0) {
100 ldmx_log(warn) << "target thickness cannot be less than 0! (thickness="
101 << target_thickness_ << "). Taking absolute value.";
102 target_thickness_ = std::abs(target_thickness_);
103 }
104
105 if (beam_size_.size() != 2) {
106 if (beam_size_.size() == 0) {
107 ldmx_log(info) << "beam size not set. Using zero.";
108 beam_size_.resize(2);
109 beam_size_[0] = 0.0;
110 beam_size_[1] = 0.0;
111 } else {
112 ldmx_log(error) << "beam size is set, but does not have size 2." << " "
113 << beam_size_.size();
114 ret = false;
115 }
116 } else if (beam_size_[0] < 0 || beam_size_[1] < 0) {
117 ldmx_log(warn) << "Beam size set as negative value? " << "("
118 << beam_size_[0] << "," << beam_size_[1] << ")"
119 << ". Changing to positive.";
120 beam_size_[0] = std::abs(beam_size_[0]);
121 beam_size_[1] = std::abs(beam_size_[1]);
122 }
123
124 // normalize abundances
125 float abundance_sum = 0;
126 for (auto a : abundances_) {
127 abundance_sum += a;
128 }
129
130 if (std::abs(abundance_sum) < 1e-6) {
131 ldmx_log(error) << "abundances list sums to zero? " << abundance_sum;
132 ret = false;
133 }
134
135 if (std::abs(abundance_sum - 1.0) > 2e-2) {
136 ldmx_log(info) << "abundances list sums is not unity (" << abundance_sum
137 << " instead.) Will renormalize abundances to unity!";
138 }
139
140 for (size_t i_a = 0; i_a < abundances_.size(); ++i_a) {
141 abundances_[i_a] = abundances_[i_a] / abundance_sum;
142
143 ldmx_log(debug) << "Target=" << targets_[i_a]
144 << ", Abundance=" << abundances_[i_a];
145 }
146
147 float dir_total_sq = 0;
148 for (auto d : direction_) dir_total_sq += d * d;
149
150 if (dir_total_sq < 1e-6) {
151 ldmx_log(error) << "direction vector is zero or negative? " << "("
152 << direction_[0] << "," << direction_[1] << ","
153 << direction_[2] << ")";
154 ret = false;
155 }
156 for (size_t i_d = 0; i_d < direction_.size(); ++i_d)
157 direction_[i_d] = direction_[i_d] / std::sqrt(dir_total_sq);
158
159 xsec_by_target_.resize(targets_.size(), -999.);
160 n_events_by_target_.resize(targets_.size(), 0);
161
162 return ret;
163}

Referenced by GenieGenerator().

Member Data Documentation

◆ abundances_

std::vector<double> simcore::generators::GenieGenerator::abundances_
private

Definition at line 85 of file GenieGenerator.h.

◆ beam_size_

std::vector<double> simcore::generators::GenieGenerator::beam_size_
private

Definition at line 87 of file GenieGenerator.h.

◆ direction_

std::vector<double> simcore::generators::GenieGenerator::direction_
private

Definition at line 90 of file GenieGenerator.h.

◆ energy_

double simcore::generators::GenieGenerator::energy_
private

Definition at line 83 of file GenieGenerator.h.

◆ ev_weighting_integral_

std::vector<float> simcore::generators::GenieGenerator::ev_weighting_integral_
private

Definition at line 97 of file GenieGenerator.h.

◆ evg_drivers_

std::vector<genie::GEVGDriver> simcore::generators::GenieGenerator::evg_drivers_
private

One GENIE event generator driver per target and convertor to HepMC3GenEvent.

Each driver is configured once for its target during initialization.

Definition at line 80 of file GenieGenerator.h.

Referenced by calculateTotalXS(), and GeneratePrimaryVertex().

◆ hep_mc3_converter_

genie::HepMC3Converter simcore::generators::GenieGenerator::hep_mc3_converter_
private

Definition at line 81 of file GenieGenerator.h.

◆ message_threshold_file_

std::string simcore::generators::GenieGenerator::message_threshold_file_
private

Definition at line 95 of file GenieGenerator.h.

◆ n_events_by_target_

std::vector<size_t> simcore::generators::GenieGenerator::n_events_by_target_
private

Definition at line 99 of file GenieGenerator.h.

◆ n_events_generated_

size_t simcore::generators::GenieGenerator::n_events_generated_
private

Definition at line 98 of file GenieGenerator.h.

◆ position_

std::vector<double> simcore::generators::GenieGenerator::position_
private

Definition at line 86 of file GenieGenerator.h.

◆ spline_file_

std::string simcore::generators::GenieGenerator::spline_file_
private

Definition at line 93 of file GenieGenerator.h.

◆ target_thickness_

float simcore::generators::GenieGenerator::target_thickness_
private

Definition at line 88 of file GenieGenerator.h.

◆ targets_

std::vector<int> simcore::generators::GenieGenerator::targets_
private

Definition at line 84 of file GenieGenerator.h.

◆ time_

float simcore::generators::GenieGenerator::time_
private

Definition at line 89 of file GenieGenerator.h.

◆ tune_

std::string simcore::generators::GenieGenerator::tune_
private

Definition at line 92 of file GenieGenerator.h.

◆ xsec_by_target_

std::vector<float> simcore::generators::GenieGenerator::xsec_by_target_
private

Definition at line 100 of file GenieGenerator.h.

◆ xsec_total_

float simcore::generators::GenieGenerator::xsec_total_
private

Definition at line 102 of file GenieGenerator.h.


The documentation for this class was generated from the following files: