83 if (targets_.size() == 0 || abundances_.size() == 0) {
84 ldmx_log(error) <<
"targets and/or abundances sizes are zero." <<
" "
85 << targets_.size() <<
", " << abundances_.size();
88 if (targets_.size() != abundances_.size()) {
89 ldmx_log(error) <<
"targets and abundances sizes unequal." <<
" "
90 << targets_.size() <<
" != " << abundances_.size();
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();
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_);
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);
113 ldmx_log(error) <<
"beam size is set, but does not have size 2." <<
" "
114 << beam_size_.size();
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]);
126 float abundance_sum = 0;
127 for (
auto a : abundances_) {
131 if (std::abs(abundance_sum) < 1e-6) {
132 ldmx_log(error) <<
"abundances list sums to zero? " << abundance_sum;
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!";
141 for (
size_t i_a = 0; i_a < abundances_.size(); ++i_a) {
142 abundances_[i_a] = abundances_[i_a] / abundance_sum;
144 ldmx_log(debug) <<
"Target=" << targets_[i_a]
145 <<
", Abundance=" << abundances_[i_a];
148 float dir_total_sq = 0;
149 for (
auto d : direction_) dir_total_sq += d * d;
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] <<
")";
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);
160 xsec_by_target_.resize(targets_.size(), -999.);
161 n_events_by_target_.resize(targets_.size(), 0);
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);
176 genie::utils::app_init::MesgThresholds(message_threshold_file_);
179 genie::RunOpt::Instance()->SetTuneName(tune_);
180 if (!genie::RunOpt::Instance()->Tune()) {
181 EXCEPTION_RAISE(
"ConfigurationException",
"No TuneId in RunOption.");
183 genie::RunOpt::Instance()->BuildTune();
186 genie::utils::app_init::XSecTable(spline_file_,
true);
189 genie::GHepRecord::SetPrintLevel(0);
193 genie::RunOpt::Instance()->EventGeneratorList());
194 evg_driver_.SetUnphysEventMask(*genie::RunOpt::Instance()->UnphysEventMask());
200 ev_weighting_integral_.resize(targets_.size(), 0.0);
203 for (
size_t i_t = 0; i_t < targets_.size(); ++i_t) {
204 genie::InitialState initial_state(targets_[i_t], 11);
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_);
216 initial_e.Momentum(e_p4);
219 xsec_total_ += xsec_by_target_[i_t] * abundances_[i_t];
221 ev_weighting_integral_[i_t] = xsec_total_;
224 ldmx_log(debug) <<
"Target=" << targets_[i_t]
225 <<
"\tAbundance=" << abundances_[i_t] <<
"\tXSEC="
226 << xsec_by_target_[i_t] / genie::units::millibarn <<
"mb";
228 ldmx_log(debug) <<
"Total XSEC = " << xsec_total_ / genie::units::millibarn
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_;
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];
261 std::cout <<
"Total events generated = " << n_events_generated_
262 <<
"\nTotal XSEC = " << total_xsec / genie::units::millibarn
263 <<
" mb" << std::endl;
265 std::cout <<
"--- GENIE Generation Summary *END* ---" << std::endl;
269 if (n_events_generated_ == 0) {
273 auto seed = G4Random::getTheEngine()->getSeed();
274 ldmx_log(debug) <<
"Initializing GENIE with seed " << seed;
275 genie::utils::app_init::RandGen(seed);
278 auto nucl_target_i = 0;
280 if (targets_.size() > 0) {
281 double rand_uniform = G4Random::getTheGenerator()->flat();
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));
288 ldmx_log(debug) <<
"Random number = " << rand_uniform <<
", target picked "
289 << targets_.at(nucl_target_i);
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_;
299 ldmx_log(debug) <<
"Generating interaction at (x_,y_,z_)=" <<
"(" << x_pos
300 <<
"," << y_pos <<
"," << z_pos <<
")";
302 genie::InitialState initial_state(targets_.at(nucl_target_i), 11);
308 initial_e.SetPdgCode(11);
310 std::sqrt(energy_ * energy_ - initial_e.GetMass() * initial_e.GetMass());
311 initial_e.SetMomentum(elec_i_p * direction_[0], elec_i_p * direction_[1],
312 elec_i_p * direction_[2], energy_);
314 initial_e.Momentum(e_p4);
316 ldmx_log(debug) <<
"Generating interation with (px,py,pz,e)=" <<
"("
317 << e_p4.Px() <<
"," << e_p4.Py() <<
"," << e_p4.Pz() <<
","
321 if (n_events_by_target_[nucl_target_i] == 0)
322 xsec_by_target_[nucl_target_i] =
evg_driver_.XSecSum(e_p4);
324 n_events_by_target_[nucl_target_i] += 1;
327 genie::EventRecord* genie_event = NULL;
328 while (!genie_event) genie_event =
evg_driver_.GenerateEvent(e_p4);
331 auto hepmc3_genie = hep_mc3_converter_.ConvertToHepMC3(*genie_event);
333 hepmc3_genie->write_data(hepmc3_ldmx_genie);
334 ev_info->addHepMC3GenEvent(hepmc3_ldmx_genie);
335 event->SetUserInformation(ev_info);
339 G4PrimaryVertex* vertex =
new G4PrimaryVertex();
340 vertex->SetPosition(x_pos, y_pos, z_pos);
341 vertex->SetWeight(genie_event->Weight());
344 int n_entries = genie_event->GetEntries();
346 ldmx_log(debug) <<
"---------- " <<
"Generated Event "
347 << n_events_generated_ + 1 <<
" ----------";
349 for (
int i_p = 0; i_p < n_entries; ++i_p) {
350 genie::GHepParticle* p = (genie::GHepParticle*)(*genie_event)[i_p];
353 if (p->Status() != 1)
continue;
355 ldmx_log(debug) <<
"\tAdding particle " << p->Pdg() <<
" with status "
356 << p->Status() <<
" energy " << p->E() <<
" ...";
358 G4PrimaryParticle* primary =
new G4PrimaryParticle();
359 primary->SetPDGcode(p->Pdg());
367 primary->SetMomentum(p->Px() * CLHEP::GeV, p->Py() * CLHEP::GeV,
368 p->Pz() * CLHEP::GeV);
370 primary->SetProperTime(time_ * CLHEP::ns);
375 primary->SetUserInformation(primary_info);
377 vertex->SetPrimary(primary);
381 event->AddPrimaryVertex(vertex);
383 ++n_events_generated_;