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 236 of file GenieGenerator.cxx.

238 : PrimaryGenerator(name, p) {
239 fillConfig(p);
240
241 if (!validateConfig())
242 EXCEPTION_RAISE("ConfigurationException", "Configuration not valid.");
243
244 n_events_generated_ = 0;
247}
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 249 of file GenieGenerator.cxx.

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

Member Function Documentation

◆ calculateTotalXS()

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

GENIE initialization.

Definition at line 192 of file GenieGenerator.cxx.

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

62 {
63 energy_ = p.get<double>("energy"); // * GeV;
64
65 targets_ = p.get<std::vector<int> >("targets");
66 abundances_ = p.get<std::vector<double> >("abundances");
67
68 time_ = p.get<double>("time"); // * ns;
69 position_ = p.get<std::vector<double> >("position"); // mm
70 beam_size_ = p.get<std::vector<double> >("beam_size"); // mm
71 direction_ = p.get<std::vector<double> >("direction");
72 target_thickness_ = p.get<double>("target_thickness"); // mm
73
74 tune_ = p.get<std::string>("tune");
75 spline_file_ = p.get<std::string>("spline_file");
76
77 message_threshold_file_ = p.get<std::string>("message_threshold_file");
78}
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 268 of file GenieGenerator.cxx.

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

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

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 385 of file GenieGenerator.cxx.

385 {
386 rh.setStringParameter(id + " Class", "simcore::generators::GenieGenerator");
387 rh.setStringParameter(id + "GenieTune", tune_);
388}
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 80 of file GenieGenerator.cxx.

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

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: