71 if (targets_.size() == 0 || abundances_.size() == 0) {
72 ldmx_log(error) <<
"targets and/or abundances sizes are zero." <<
" "
73 << targets_.size() <<
", " << abundances_.size();
76 if (targets_.size() != abundances_.size()) {
77 ldmx_log(error) <<
"targets and abundances sizes unequal." <<
" "
78 << targets_.size() <<
" != " << abundances_.size();
82 if (position_.size() != 3 || direction_.size() != 3) {
83 ldmx_log(error) <<
"position and/or direction sizes are not 3." <<
" "
84 << position_.size() <<
", " << direction_.size();
88 if (target_thickness_ < 0) {
89 ldmx_log(warn) <<
"target thickness cannot be less than 0! (thickness="
90 << target_thickness_ <<
"). Taking absolute value.";
91 target_thickness_ = std::abs(target_thickness_);
94 if (beam_size_.size() != 2) {
95 if (beam_size_.size() == 0) {
96 ldmx_log(info) <<
"beam size not set. Using zero.";
101 ldmx_log(error) <<
"beam size is set, but does not have size 2." <<
" "
102 << beam_size_.size();
105 }
else if (beam_size_[0] < 0 || beam_size_[1] < 0) {
106 ldmx_log(warn) <<
"Beam size set as negative value? " <<
"("
107 << beam_size_[0] <<
"," << beam_size_[1] <<
")"
108 <<
". Changing to positive.";
109 beam_size_[0] = std::abs(beam_size_[0]);
110 beam_size_[1] = std::abs(beam_size_[1]);
114 float abundance_sum = 0;
115 for (
auto a : abundances_) {
119 if (std::abs(abundance_sum) < 1e-6) {
120 ldmx_log(error) <<
"abundances list sums to zero? " << abundance_sum;
124 if (std::abs(abundance_sum - 1.0) > 2e-2) {
125 ldmx_log(info) <<
"abundances list sums is not unity (" << abundance_sum
126 <<
" instead.) Will renormalize abundances to unity!";
129 for (
size_t i_a = 0; i_a < abundances_.size(); ++i_a) {
130 abundances_[i_a] = abundances_[i_a] / abundance_sum;
132 ldmx_log(debug) <<
"Target=" << targets_[i_a]
133 <<
", Abundance=" << abundances_[i_a];
136 float dir_total_sq = 0;
137 for (
auto d : direction_) dir_total_sq += d * d;
139 if (dir_total_sq < 1e-6) {
140 ldmx_log(error) <<
"direction vector is zero or negative? " <<
"("
141 << direction_[0] <<
"," << direction_[1] <<
","
142 << direction_[2] <<
")";
145 for (
size_t i_d = 0; i_d < direction_.size(); ++i_d)
146 direction_[i_d] = direction_[i_d] / std::sqrt(dir_total_sq);
148 xsec_by_target_.resize(targets_.size(), -999.);
149 n_events_by_target_.resize(targets_.size(), 0);
157 char* in_arr[3] = {
const_cast<char*
>(
""),
158 const_cast<char*
>(
"--event-generator-list"),
159 const_cast<char*
>(
"EM")};
160 genie::RunOpt::Instance()->ReadFromCommandLine(3, in_arr);
164 genie::utils::app_init::MesgThresholds(message_threshold_file_);
167 genie::RunOpt::Instance()->SetTuneName(tune_);
168 if (!genie::RunOpt::Instance()->Tune()) {
169 EXCEPTION_RAISE(
"ConfigurationException",
"No TuneId in RunOption.");
171 genie::RunOpt::Instance()->BuildTune();
174 genie::utils::app_init::XSecTable(spline_file_,
true);
177 genie::GHepRecord::SetPrintLevel(0);
183 ev_weighting_integral_.resize(targets_.size(), 0.0);
187 for (
size_t i_t = 0; i_t < targets_.size(); ++i_t) {
188 genie::InitialState initial_state(targets_[i_t], 11);
190 genie::RunOpt::Instance()->EventGeneratorList());
192 *genie::RunOpt::Instance()->UnphysEventMask());
198 initial_e.SetPdgCode(11);
199 auto elec_i_p = std::sqrt(energy_ * energy_ -
200 initial_e.GetMass() * initial_e.GetMass());
201 initial_e.SetMomentum(elec_i_p * direction_[0], elec_i_p * direction_[1],
202 elec_i_p * direction_[2], energy_);
204 initial_e.Momentum(e_p4);
207 xsec_total_ += xsec_by_target_[i_t] * abundances_[i_t];
209 ev_weighting_integral_[i_t] = xsec_total_;
212 ldmx_log(debug) <<
"Target=" << targets_[i_t]
213 <<
"\tAbundance=" << abundances_[i_t] <<
"\tXSEC="
214 << xsec_by_target_[i_t] / genie::units::millibarn <<
"mb";
216 ldmx_log(debug) <<
"Total XSEC = " << xsec_total_ / genie::units::millibarn
220 for (
size_t i_t = 0; i_t < ev_weighting_integral_.size(); ++i_t)
221 ev_weighting_integral_[i_t] = ev_weighting_integral_[i_t] / xsec_total_;
238 ldmx_log(info) <<
"--- GENIE Generation Summary BEGIN ---";
239 double total_xsec = 0;
240 for (
size_t i_t = 0; i_t < targets_.size(); ++i_t) {
241 ldmx_log(info) <<
"Target=" << targets_[i_t]
242 <<
"\tAbundance=" << abundances_[i_t] <<
"\tXSEC="
243 << xsec_by_target_[i_t] / genie::units::millibarn <<
" mb"
244 <<
"\tEvents=" << n_events_by_target_[i_t];
245 if (n_events_by_target_[i_t] > 0)
246 total_xsec += xsec_by_target_[i_t] * abundances_[i_t];
249 ldmx_log(info) <<
"Total events generated = " << n_events_generated_
250 <<
"\nTotal XSEC = " << total_xsec / genie::units::millibarn
253 ldmx_log(info) <<
"--- GENIE Generation Summary *END* ---";
257 if (n_events_generated_ == 0) {
261 auto seed = G4Random::getTheEngine()->getSeed();
262 ldmx_log(debug) <<
"Initializing GENIE with seed " << seed;
263 genie::utils::app_init::RandGen(seed);
266 auto nucl_target_i = 0;
268 if (targets_.size() > 0) {
269 double rand_uniform = G4Random::getTheGenerator()->flat();
271 nucl_target_i = std::distance(
272 ev_weighting_integral_.begin(),
273 std::lower_bound(ev_weighting_integral_.begin(),
274 ev_weighting_integral_.end(), rand_uniform));
276 ldmx_log(debug) <<
"Random number = " << rand_uniform <<
", target picked "
277 << targets_.at(nucl_target_i);
280 auto x_pos = position_[0] +
281 (G4Random::getTheGenerator()->flat() - 0.5) * beam_size_[0];
282 auto y_pos = position_[1] +
283 (G4Random::getTheGenerator()->flat() - 0.5) * beam_size_[1];
284 auto z_pos = position_[2] +
285 (G4Random::getTheGenerator()->flat() - 0.5) * target_thickness_;
287 ldmx_log(debug) <<
"Generating interaction at (x_,y_,z_)=" <<
"(" << x_pos
288 <<
"," << y_pos <<
"," << z_pos <<
")";
292 initial_e.SetPdgCode(11);
294 std::sqrt(energy_ * energy_ - initial_e.GetMass() * initial_e.GetMass());
295 initial_e.SetMomentum(elec_i_p * direction_[0], elec_i_p * direction_[1],
296 elec_i_p * direction_[2], energy_);
298 initial_e.Momentum(e_p4);
300 ldmx_log(debug) <<
"Generating interation with (px,py,pz,e)=" <<
"("
301 << e_p4.Px() <<
"," << e_p4.Py() <<
"," << e_p4.Pz() <<
","
304 n_events_by_target_[nucl_target_i] += 1;
307 genie::EventRecord* genie_event = NULL;
309 genie_event =
evg_drivers_[nucl_target_i].GenerateEvent(e_p4);
312 auto hepmc3_genie = hep_mc3_converter_.ConvertToHepMC3(*genie_event);
314 hepmc3_genie->write_data(hepmc3_ldmx_genie);
315 ev_info->addHepMC3GenEvent(hepmc3_ldmx_genie);
316 event->SetUserInformation(ev_info);
320 G4PrimaryVertex* vertex =
new G4PrimaryVertex();
321 vertex->SetPosition(x_pos, y_pos, z_pos);
322 vertex->SetWeight(genie_event->Weight());
325 int n_entries = genie_event->GetEntries();
327 ldmx_log(debug) <<
"---------- " <<
"Generated Event "
328 << n_events_generated_ + 1 <<
" ----------";
330 for (
int i_p = 0; i_p < n_entries; ++i_p) {
331 genie::GHepParticle* p = (genie::GHepParticle*)(*genie_event)[i_p];
334 if (p->Status() != 1)
continue;
336 ldmx_log(debug) <<
"\tAdding particle " << p->Pdg() <<
" with status "
337 << p->Status() <<
" energy " << p->E() <<
" ...";
339 G4PrimaryParticle* primary =
new G4PrimaryParticle();
340 primary->SetPDGcode(p->Pdg());
348 primary->SetMomentum(p->Px() * CLHEP::GeV, p->Py() * CLHEP::GeV,
349 p->Pz() * CLHEP::GeV);
351 primary->SetProperTime(time_ * CLHEP::ns);
356 primary->SetUserInformation(primary_info);
358 vertex->SetPrimary(primary);
362 event->AddPrimaryVertex(vertex);
369 ++n_events_generated_;