MARLEY (Model of Argon Reaction Low Energy Yields) v2.0.0
A Monte Carlo event generator for tens-of-MeV neutrino interactions
Loading...
Searching...
No Matches
Reaction.cc
1
4//
5// This file is part of MARLEY (Model of Argon Reaction Low Energy Yields)
6//
7// MARLEY is free software: you can redistribute it and/or modify it under the
8// terms of version 3 of the GNU General Public License as published by the
9// Free Software Foundation.
10//
11// For the full text of the license please see COPYING or
12// visit http://opensource.org/licenses/GPL-3.0
13//
14// Please respect the MCnet academic usage guidelines. See GUIDELINES
15// or visit https://www.montecarlonet.org/GUIDELINES for details.
16
17// Standard library includes
18#include <limits>
19#include <map>
20
21// HepMC3 includes
22#include "HepMC3/Attribute.h"
23#include "HepMC3/GenEvent.h"
24#include "HepMC3/GenVertex.h"
25#include "HepMC3/GenParticle.h"
26
27// MARLEY includes
28#include "marley/DiscreteNuclearReaction.hh"
29#include "marley/ElectronReaction.hh"
30#include "marley/HauserFeshbachDecay.hh"
31#include "marley/JSON.hh"
32#include "marley/Logger.hh"
33#include "marley/MatrixElement.hh"
34#include "marley/Reaction.hh"
35#include "marley/StructureDatabase.hh"
36#include "marley/hepmc3_utils.hh"
37#include "marley/ContinuumNuclearReaction.hh"
38#include "marley/marley_kinematics.hh"
39#include "marley/marley_utils.hh"
40
41using ProcType = marley::Reaction::ProcessType;
43
44namespace {
45
46 using namespace marley_utils;
47
48 std::map<ProcType, std::string> proc_type_to_string_map {
49 { ProcType::Unknown, "Unknown" },
50 { ProcType::NeutrinoCC_Discrete, "\u03BD CC (Discrete)" },
51 { ProcType::AntiNeutrinoCC_Discrete, "anti-\u03BD CC (Discrete)" },
52 { ProcType::NC_Discrete, "NC (Discrete)" },
53 { ProcType::NuElectronElastic, "(anti-)\u03BD + e- ES" },
54 { ProcType::NeutrinoCC_Continuum, "\u03BD CC (Continuum)" },
55 { ProcType::AntiNeutrinoCC_Continuum, "anti-\u03BD CC (Continuum)" },
56 { ProcType::NC_Continuum, "NC (Continuum)" },
57 { ProcType::StandaloneDecay, "Standalone Decay" },
58 };
59
60 // Defines the neutrino species that can participate in each type
61 // of scattering process
62 std::map<ProcType, std::vector<int> > proc_type_to_nu_pdg = {
63
64 { ProcType::NeutrinoCC_Discrete,
65 { ELECTRON_NEUTRINO, MUON_NEUTRINO, TAU_NEUTRINO }
66 },
67
68 { ProcType::AntiNeutrinoCC_Discrete,
69 { ELECTRON_ANTINEUTRINO, MUON_ANTINEUTRINO, TAU_ANTINEUTRINO }
70 },
71
72 { ProcType::NC_Discrete,
73 { ELECTRON_NEUTRINO, MUON_NEUTRINO, TAU_NEUTRINO,
74 ELECTRON_ANTINEUTRINO, MUON_ANTINEUTRINO, TAU_ANTINEUTRINO }
75 },
76
77 { ProcType::NuElectronElastic,
78 { ELECTRON_NEUTRINO, MUON_NEUTRINO, TAU_NEUTRINO,
79 ELECTRON_ANTINEUTRINO, MUON_ANTINEUTRINO, TAU_ANTINEUTRINO }
80 },
81
82 { ProcType::NeutrinoCC_Continuum,
83 { ELECTRON_NEUTRINO, MUON_NEUTRINO, TAU_NEUTRINO }
84 },
85
86 { ProcType::AntiNeutrinoCC_Continuum,
87 { ELECTRON_ANTINEUTRINO, MUON_ANTINEUTRINO, TAU_ANTINEUTRINO }
88 },
89
90 { ProcType::NC_Continuum,
91 { ELECTRON_NEUTRINO, MUON_NEUTRINO, TAU_NEUTRINO,
92 ELECTRON_ANTINEUTRINO, MUON_ANTINEUTRINO, TAU_ANTINEUTRINO }
93 },
94
95 };
96
97 // Helper function that assigns Level pointers to MatrixElement objects
98 // that represent transitions to discrete nuclear levels
99 void set_level_ptrs(std::vector<marley::MatrixElement>& matrix_elements,
100 int pdg_b, int pdg_d, marley::StructureDatabase& db)
101 {
102 // If discrete level data are available for the residual nucleus, use them
103 // to assign values to the level pointers and refine the level energies. If
104 // not, just return without doing anything. This will keep all of the level
105 // pointers nullptr (treating them just like unbound levels) and have the
106 // matrix elements use the energies given in the reaction dataset.
107 marley::DecayScheme* ds = db.get_decay_scheme( pdg_d );
108 if ( !ds ) return;
109
110 // Check to see if the decay scheme being associated with this
111 // reaction is for the correct nuclide. If the PDG code in the decay
112 // scheme object does not match the one we'd expect for this reaction's
113 // final state nucleus, complain
114 int scheme_pdg = marley_utils::get_nucleus_pid( ds->Z(), ds->A() );
115 if ( pdg_d != scheme_pdg ) throw marley::Error( "Nuclear data mismatch:"
116 " attempted to associate a decay scheme object that has PDG code "
117 + std::to_string(scheme_pdg) + " with a reaction object that has"
118 " PDG code " + std::to_string(pdg_d) );
119
120 // Use the smallest nuclear fragment emission threshold to check for
121 // unbound levels.
122 const auto& mt = marley::MassTable::Instance();
123 double unbound_threshold = mt.unbound_threshold( pdg_d );
124
125 // Get the spin-parity of the ground state of the initial nucleus.
126 // This will be used below to check the matchups between MatrixElement and
127 // Level objects based on spin-parity selection rules.
128 int twoJi;
131
132 // Cycle through each of the level energies given in the reaction dataset.
133 for ( auto& mat_el : matrix_elements ) {
134
135 // Get the excitation energy for the level accessed by the transition
136 // represented by this matrix element. Use the value from the reaction
137 // data file rather than that owned by any previous discrete level
138 // assignment. We'll use that value because we need to (re-)assign
139 // levels to each matrix element using the DecayScheme ds.
140 double en = mat_el.tabulated_level_energy();
141
142 // If the level is above the fragment emission threshold, assign it a null
143 // level pointer. Such levels will be handled by a fragment evaporation
144 // routine and therefore do not need pointers to level objects describing
145 // their de-excitation gammas.
146 if ( en > unbound_threshold ) {
147 mat_el.set_level(nullptr);
148 continue;
149 }
150
151 // For each energy, find a pointer to the level with the closest energy
152 // owned by the decay scheme object.
154 MARLEY_LOG( DEBUG, "physics.reaction" ) << "reaction level at " << en
155 << " MeV was matched to the decay scheme level at "
156 << plevel->energy() << " MeV";
157
158 // Print a warning if the spin-parity of the matched level does not
159 // satisfy the expected selection rules for a transition from the nuclear
160 // ground state
161
162 // Retrieve the final nuclear spin (multiplied by two) and parity
163 int twoJf = plevel->twoJ();
164 marley::Parity Pf = plevel->parity();
165
166 // Check the relevant selection rules
167 bool rules_ok = true;
168 ME_Type mtype = mat_el.type();
169 if ( mtype == ME_Type::FERMI ) {
170 if ( twoJi != twoJf || Pi != Pf ) rules_ok = false;
171 }
172 else if ( mtype == ME_Type::GAMOW_TELLER ) {
173 if ( Pi != Pf ) rules_ok = false;
174 int twoJf_min = std::abs( twoJi - 2 );
175 int twoJf_max = twoJi + 2;
176 if ( twoJf < twoJf_min || twoJf > twoJf_max ) rules_ok = false;
177 }
178
179 // Print a warning message if there was a problem
180 if ( !rules_ok ) {
181
182 // Use TargetAtom objects for easy printing of the nuclear symbols
183 marley::TargetAtom nuc_b( pdg_b );
184 marley::TargetAtom nuc_d( pdg_d );
185
186 MARLEY_LOG( WARN, "physics.reaction" )
187 << "The tabulated " << nuc_d << " level at "
188 << plevel->energy() << " MeV does not satisfy the selection rules"
189 << " for a " << mat_el.type_str() << " transition from the " << nuc_b
190 << " ground state.\n Initial J\u03C0 = "
191 << static_cast<double>( twoJi ) / 2. << Pi
192 << "\n Final J\u03C0 = " << static_cast<double>( twoJf ) / 2.
193 << Pf;
194 }
195
196 // Complain if there are duplicates (if there are duplicates, we'll have
197 // two different B(F) + B(GT) values for the same level object)
198 const auto begin = matrix_elements.cbegin();
199 const auto end = matrix_elements.cend();
200 const auto found = std::find_if(begin, end,
201 [plevel](const marley::MatrixElement& me) -> bool
202 { return plevel == me.level(); });
203 if ( found != end )
204 {
205 // One of the matrix elements already uses a level pointer equal to
206 // plevel
207 throw marley::Error("Reaction dataset gives two level energies that"
208 " refer to the same DecayScheme level at "
209 + std::to_string( plevel->energy() ) + " MeV");
210 }
211
215
216 // Set the level pointer in the MatrixElement object
217 mat_el.set_level( plevel );
218 }
219 }
220
221} // Anonymous namespace
222
223
224// Performs kinematics calculations for a two-two scattering reaction
225// (a + b -> c + d)
226void marley::Reaction::two_two_scatter(double KEa, double& s, double& Ec_cm,
227 double& pc_cm, double& Ed_cm) const
228{
229 // Get the lab-frame total energy of the projectile
230 double Ea = KEa + ma_;
231
232 // Compute Mandelstam s (the square of the total CM frame energy)
233 s = ma_*ma_ + mb_*mb_ + 2.*mb_*Ea;
234 double sqrt_s = std::sqrt(s);
235
236 // Determine the CM frame energy and momentum of the ejectile
237 Ec_cm = (s + mc_*mc_ - md_*md_) / (2 * sqrt_s);
238 pc_cm = real_sqrt(std::pow(Ec_cm, 2) - mc_*mc_);
239
240 // Determine the residue's CM frame energy. Roundoff errors may cause Ed_cm to
241 // dip below md, which is unphysical. Prevent this from occurring by allowing
242 // md to be the minimum value of Ed_cm. Also note that, in the CM frame, the
243 // residue and ejectile have equal and opposite momenta.
244 Ed_cm = std::max(sqrt_s - Ec_cm, md_);
245}
246
247std::shared_ptr< HepMC3::GenEvent > marley::Reaction::make_event_object(
248 double KEa, double pc_cm, double cos_theta_c_cm, double phi_c_cm,
249 double Ec_cm, double Ed_cm, int residue_status ) const
250{
251 // Determine the Cartesian components of the ejectile's CM frame momentum
252 double sin_theta_c_cm = real_sqrt( 1. - std::pow(cos_theta_c_cm, 2) );
253
254 double pc_cm_x = sin_theta_c_cm * std::cos( phi_c_cm ) * pc_cm;
255 double pc_cm_y = sin_theta_c_cm * std::sin( phi_c_cm ) * pc_cm;
256 double pc_cm_z = cos_theta_c_cm * pc_cm;
257
258 // Create particle objects representing the ejectile and residue in the CM
259 // frame.
260 auto ejectile = marley_hepmc3::make_particle( pdg_c_, pc_cm_x, pc_cm_y,
261 pc_cm_z, Ec_cm, marley_hepmc3::NUHEPMC_FINAL_STATE_STATUS, mc_ );
262
263 auto residue = marley_hepmc3::make_particle( pdg_d_, -pc_cm_x, -pc_cm_y,
264 -pc_cm_z, Ed_cm, residue_status, md_ );
265
266 // Get the lab-frame total energy of the projectile
267 double Ea = KEa + ma_;
268
269 // Determine the magnitude of the lab-frame 3-momentum of the projectile
270 double pa = real_sqrt( KEa * (KEa + 2.*ma_) );
271
272 // Boost the ejectile and residue into the lab frame.
273 double beta_z = pa / (Ea + mb_);
274 marley_kinematics::lorentz_boost( 0., 0., -beta_z, *ejectile );
275 marley_kinematics::lorentz_boost( 0., 0., -beta_z, *residue );
276
277 // Now that we have the outgoing particles defined in the lab frame, delegate
278 // the remaining tasks for creation of the event to this overloaded version
279 // of the function
280 return this->make_event_object( KEa, ejectile, residue );
281}
282
283std::shared_ptr< HepMC3::GenEvent > marley::Reaction::make_event_object(
284 double KEa, const std::shared_ptr< HepMC3::GenParticle >& ejectile,
285 const std::shared_ptr< HepMC3::GenParticle >& residue ) const
286{
287 // NuHepMC E.R.4
288 auto event = std::make_shared< HepMC3::GenEvent >( HepMC3::Units::MEV,
289 HepMC3::Units::CM );
290
291 // NuHepMC E.R.3
292 int signal_process_id = marley_hepmc3::get_nuhepmc_proc_id( process_type_ );
293 event->add_attribute( "signal_process_id",
294 std::make_shared< HepMC3::IntAttribute >( signal_process_id )
295 );
296
297 // Create the primary vertex
298 // NuHepMC E.R.6
299 auto prim_vtx = std::make_shared< HepMC3::GenVertex >();
300 prim_vtx->set_status( marley_hepmc3::NUHEPMC_PRIMARY_VERTEX );
301
302 event->add_vertex( prim_vtx );
303
304 // Get the lab-frame total energy of the projectile
305 double Ea = KEa + ma_;
306
307 // Determine the magnitude of the lab-frame 3-momentum of the projectile
308 double pa = real_sqrt( KEa * (KEa + 2.*ma_) );
309
310 // Create particle objects representing the projectile and target in the lab
311 // frame
312 // @todo Allow for projectile directions other than along the z-axis
313 auto projectile = marley_hepmc3::make_particle( pdg_a_, 0., 0., pa, Ea,
314 marley_hepmc3::NUHEPMC_PROJECTILE_STATUS, ma_ );
315
316 auto target = marley_hepmc3::make_particle( pdg_b_,
317 marley_hepmc3::NUHEPMC_TARGET_STATUS, mb_ );
318
319 // Attach the particles to the primary vertex
320 prim_vtx->add_particle_in( projectile );
321 prim_vtx->add_particle_in( target );
322
323 prim_vtx->add_particle_out( ejectile );
324 prim_vtx->add_particle_out( residue );
325
326 return event;
327}
328
329int marley::Reaction::get_ejectile_pdg(int pdg_a, ProcType proc_type) {
330 int pdg_c = 0;
331
332 // First, check that the projectile PDG code is valid for the
333 // given process type
334 const auto& vec = proc_type_to_nu_pdg.at( proc_type );
335 if ( std::find(vec.cbegin(), vec.cend(), pdg_a) != vec.end() ) {
336 if ( proc_type == ProcType::NeutrinoCC_Discrete ||
337 proc_type == ProcType::NeutrinoCC_Continuum ) pdg_c = pdg_a - 1;
338 else if ( proc_type == ProcType::AntiNeutrinoCC_Discrete ||
339 proc_type == ProcType::AntiNeutrinoCC_Continuum ) pdg_c = pdg_a + 1;
340 else if ( proc_type == ProcType::NC_Discrete ||
341 proc_type == ProcType::NC_Continuum ) pdg_c = pdg_a;
342
343 else if ( proc_type == ProcType::NuElectronElastic ) pdg_c = pdg_a;
344 else throw marley::Error("Unrecognized ProcessType encountered in"
345 " marley::Reaction::get_ejectile_pdg()");
346 }
347 else throw marley::Error("A projectile with PDG code "
348 + std::to_string(pdg_a) + " cannot participate in reactions of type "
349 + proc_type_to_string_map.at(proc_type));
350
351 return pdg_c;
352}
353
354std::string marley::Reaction::proc_type_to_string(const ProcType& pt) {
355 return proc_type_to_string_map.at( pt );
356}
357
358const std::vector<int>& marley::Reaction::get_projectiles(ProcType pt) {
359 return proc_type_to_nu_pdg.at( pt );
360}
361
364
365std::vector< std::unique_ptr<marley::Reaction> >
366 marley::Reaction::load_from_file( const std::string& filename,
368 const marley::JSON& ff_config )
369{
370 // Create an empty vector to start
371 std::vector< std::unique_ptr<marley::Reaction> > loaded_reactions;
372
373 std::regex rx_comment("#.*"); // Matches comment lines
374
375 // Open the reaction data file for parsing
376 std::ifstream file_in( filename );
377
378 // If the file doesn't exist or some other error
379 // occurred, complain and give up.
380 if ( !file_in.good() ) {
381 throw marley::Error("Could not read from the file " + filename);
382 }
383
384 // String to store the current line of the reaction data file during parsing
385 std::string line;
386
388 line = marley_utils::get_next_line( file_in, rx_comment, false );
389
390 // Read in the ProcessType code and the target PDG code
391 std::istringstream iss( line );
392 int integer_proc_type;
393 iss >> integer_proc_type;
394
395 auto proc_type = static_cast<ProcType>( integer_proc_type );
396
397 // For neutrino-electron elastic scattering, we won't have a table of
398 // matrix elements. Instead, a table of atomic target PDG codes appears.
399 // Make Reaction objects for each atomic target for each of the possible
400 // projectiles (every neutrino species) and return the result.
401 if ( proc_type == ProcessType::NuElectronElastic ) {
402
403 do {
404 // Loop over target atoms
405 int target_pdg;
406 while ( iss >> target_pdg ) {
407 // Loop over neutrino species
408 for ( const int& pdg_a : get_projectiles(proc_type) ) {
409 loaded_reactions.emplace_back(
410 std::make_unique<marley::ElectronReaction>(pdg_a, target_pdg,
411 filename) );
412 }
413 }
414
415 line = marley_utils::get_next_line( file_in, rx_comment, false );
422 iss.str( line );
423 iss.clear();
424 } while ( !line.empty() );
425
426 return loaded_reactions;
427 }
428
429 // For nuclear reaction modes, there is a single target nucleus PDG code
430 // per file.
431 int pdg_b;
432 iss >> pdg_b;
433
434 // Multiple formats are allowed for the nuclear reaction modes. Get the
435 // format code from the current line in order to decide what to do next.
436 int integer_data_format;
437 iss >> integer_data_format;
438 auto df = static_cast< DataFormat >( integer_data_format );
439
440 if ( df == DiscreteStrengths ) {
441
442 // Read in all of the level energy (MeV), squared matrix element (B(F) or
443 // B(GT) strength), and matrix element type identifier (0 represents B(F),
444 // 1 represents B(GT)) triplets. Create a vector of MatrixElement objects
445 // based on this information. Use a shared pointer so that the vector can
446 // be re-used by multiple Reaction objects, one for each neutrino species
447 // for which the matrix elements are relevant. This avoids unnecessary
448 // duplication of storage for the matrix elements.
449 auto matrix_elements = std::make_shared<std::vector<
451
452 // Set the old energy entry to the lowest representable double
453 // value. This guarantees that we always read in the first energy
454 // value given in the reaction data file
455 double old_energy = std::numeric_limits<double>::lowest();
456 while (line = marley_utils::get_next_line(file_in, rx_comment, false),
457 file_in.good())
458 {
459 iss.str(line);
460 iss.clear();
461
464
465 // The order of the entries is important because later uses of the vector
466 // of matrix elements assume that they are sorted in order of ascending
467 // final level energy.
468 double energy, strength;
469 int integer_me_type;
470 iss >> energy >> strength >> integer_me_type;
471 if ( old_energy >= energy ) throw marley::Error( "Invalid reaction"
472 " dataset. Level energies must be unique and must be given in"
473 " ascending order." );
474
475 // Read optional uncertainty columns:
476 // 4 columns: symmetric uncertainty (err_low = err_high = err)
477 // 5 columns: asymmetric uncertainties (err_low, err_high)
478 // 3 columns (legacy): no uncertainty (both default to zero)
479 double err_low = 0., err_high = 0.;
480 if ( iss >> err_low ) {
481 err_high = err_low; // default to symmetric
482 iss >> err_high; // try for asymmetric (fails silently)
483 }
484
485 // @todo Right now, 0 corresponds to a Fermi transition, and 1
486 // corresponds to a Gamow-Teller transition. As you add new matrix
487 // element types, consider changing the convention and its
488 // implementation. All of the level pointers owned by the matrix elements
489 // will initially be set to nullptr. This may be changed later if
490 // discrete level data can be found for the residual nucleus.
491 matrix_elements->emplace_back( energy, strength,
492 static_cast<ME_Type>(integer_me_type), err_low, err_high,
493 nullptr );
494 old_energy = energy;
495 }
496
497 // We now have all the information that we need. Build Reaction objects for
498 // all neutrino species that can participate in the process described by
499 // the matrix elements in the table. Use the ProcessType code to figure
500 // this out
501 int pdg_d, q_d;
502 get_residue_pdg_and_charge( proc_type, pdg_b, pdg_d, q_d );
503
504 // Now that we know the PDG code for the final nucleus, look up discrete
505 // level data for it. Set the level pointers for matrix elements
506 // representing transitions to discrete nuclear levels
507 set_level_ptrs( *matrix_elements, pdg_b, pdg_d, db );
508
509 // Now loop over the projectile PDG codes that can participate in the
510 // scattering process of interest. For each one, decide what the ejectile
511 // PDG code should be, then produce a corresponding Reaction object
512 for ( const int& pdg_a : get_projectiles(proc_type) ) {
513 int pdg_c = get_ejectile_pdg( pdg_a, proc_type );
514
515 loaded_reactions.emplace_back(
516 std::make_unique< marley::DiscreteNuclearReaction >( proc_type,
517 pdg_a, pdg_b, pdg_c, pdg_d, q_d, matrix_elements, coulomb_mode,
518 ff_config, filename )
519 );
520 }
521 }
522 else if ( df == MultipoleResponses ) {
523
524 // An energy shift is provided following the data format code if we
525 // are working with multipole responses. This accounts for the energy
526 // difference between the ground state of the initial nucleus and the
527 // isobaric analog state in the daughter nucleus.
528 double delta_ias;
529 iss >> delta_ias;
530
531 // Create a shared pointer to a TabulatedXSec object that will manage
532 // the tables of nuclear responses. These can be re-used for multiple
533 // neutrino flavors by separate Reaction objects.
534 auto txsec = std::make_shared< marley::TabulatedXSec >(
535 pdg_b, proc_type, coulomb_mode, delta_ias );
536
537 // Each line contains a file name corresponding to a distinct table
538 // of nuclear responses. Add each one to the map managed by the
539 // TabulatedXSec object.
540 std::string table_file_name;
541 while ( table_file_name = marley_utils::get_next_line(file_in,
542 rx_comment, false), file_in.good() )
543 {
544 txsec->add_table( table_file_name );
545 }
546
547 // Get the PDG code and (net) charge of the final nucleus
548 int pdg_d, q_d;
549 get_residue_pdg_and_charge( proc_type, pdg_b, pdg_d, q_d );
550
551 // Now loop over the projectile PDG codes that can participate in the
552 // scattering process of interest. For each one, decide what the ejectile
553 // PDG code should be, then produce a corresponding Reaction object
554 for ( const int& pdg_a : get_projectiles(proc_type) ) {
555 int pdg_c = get_ejectile_pdg(pdg_a, proc_type);
556
557 // TODO: remove hard-coding here
558 txsec->optimize( pdg_a, 100. );
559
560 loaded_reactions.emplace_back(
561 std::make_unique< marley::ContinuumNuclearReaction >( proc_type, pdg_a,
562 pdg_b, pdg_c, pdg_d, q_d, txsec, filename )
563 );
564 }
565
566 }
567 else throw marley::Error( "Unrecognized reaction data format"
568 " encountered in marley::Reaction::load_from_file()" );
569
570 return loaded_reactions;
571}
572
574 marley::Reaction::ProcessType proc_type, int pdg_b, int& pdg_d, int& q_d )
575{
576 // First, figure out the PDG code for the final nucleus and its ionization
577 // state (net atomic charge after the 2->2 scatter)
578 int Zi = marley_utils::get_particle_Z( pdg_b );
579 int A = marley_utils::get_particle_A( pdg_b );
580
581 // NC scattering leaves the target nucleus the same
584 {
585 pdg_d = pdg_b;
586 q_d = 0;
587 }
588 // Neutrino CC scattering raises Z by one
591 {
592 // Check that the neutron number of the target is positive
593 int Ni = A - Zi;
594 if ( Ni <= 0 ) throw marley::Error("A NeutrinoCC process requires"
595 " a target nucleus with N > 0");
596 int Zf = Zi + 1;
597 pdg_d = marley_utils::get_nucleus_pid(Zf, A);
598 // Recoil ion has charge +1
599 q_d = 1;
600 }
601 // Antineutrino CC scattering lowers Z by one
604 {
605 // Check that the neutron number of the target is positive
606 if ( Zi <= 0 ) throw marley::Error("An AntiNeutrinoCC process requires"
607 " a target nucleus with Z > 0");
608 int Zf = Zi - 1;
609 pdg_d = marley_utils::get_nucleus_pid(Zf, A);
610 // Recoil ion has charge -1
611 q_d = -1;
612 }
613 else throw marley::Error( "Unrecognized ProcessType encountered in"
614 " marley::Reaction::get_residue_pdg_and_charge()" );
615}
CoulombMode
Enumerated type used to set the method for handling Coulomb corrections for CC nuclear reactions.
Discrete level and γ-ray data for a specific nuclide.
int A() const
Get the mass number.
int Z() const
Get the atomic number.
marley::Level * get_pointer_to_closest_level(double E_level)
Gets a pointer to the Level in the DecayScheme whose excitation energy is closest to E_level.
Base class for all exceptions thrown by MARLEY functions.
Definition Error.hh:26
A discrete nuclear energy level.
Definition Level.hh:29
marley::Parity parity() const
Get the level parity.
Definition Level.hh:141
int twoJ() const
Get two times the level spin.
Definition Level.hh:138
double energy() const
Get the excitation energy of this level (MeV)
Definition Level.hh:135
static const MassTable & Instance()
Get a const reference to the singleton instance of the MassTable.
Definition MassTable.cc:69
A reduced nuclear matrix element that represents a transition caused by a neutrino-nucleus reaction.
TransitionType
Enumerated type that represents the possible kinds of nuclear transitions recognized by MARLEY.
const marley::Level * level() const
Get a pointer to the final-state nuclear Level accessed by the matrix element, or nullptr if it is a ...
Type-safe representation of a parity value (either +1 or -1)
Definition Parity.hh:25
Reaction(const std::string &source_file)
Construct a Reaction with the resolved path of the data file.
Definition Reaction.cc:362
int pdg_a_
PDG code for the projectile.
Definition Reaction.hh:142
double md_
Residue mass (MeV)
Definition Reaction.hh:154
ProcessType process_type_
Type of scattering process (CC, NC) represented by this reaction.
Definition Reaction.hh:161
double mc_
Ejectile mass (MeV)
Definition Reaction.hh:149
static int get_ejectile_pdg(int pdg_a, ProcessType proc_type)
Definition Reaction.cc:329
void two_two_scatter(double KEa, double &s, double &Ec_cm, double &pc_cm, double &Ed_cm) const
Helper function that handles CM frame kinematics for the reaction.
Definition Reaction.cc:226
ProcessType
Enumerated type describing the kind of scattering process represented by a Reaction.
Definition Reaction.hh:58
@ NC_Continuum
Nuclear matrix elements contain for a transition to a continuum of nuclear levels.
Definition Reaction.hh:66
@ NC_Discrete
Nuclear matrix elements contain for a transition to a discrete nuclear level.
Definition Reaction.hh:62
@ AntiNeutrinoCC_Discrete
Nuclear matrix elements contain for a transition to a discrete nuclear level.
Definition Reaction.hh:61
@ NuElectronElastic
Neutrino-electron elastic scattering.
Definition Reaction.hh:63
@ NeutrinoCC_Discrete
Nuclear matrix elements contain for a transition to a discrete nuclear level.
Definition Reaction.hh:60
@ AntiNeutrinoCC_Continuum
Nuclear matrix elements contain for a transition to a continuum of nuclear levels.
Definition Reaction.hh:65
@ NeutrinoCC_Continuum
Nuclear matrix elements contain for a transition to a continuum of nuclear levels.
Definition Reaction.hh:64
DataFormat
Enumerated type describing the file format for reaction data.
Definition Reaction.hh:71
@ MultipoleResponses
Continuum nuclear responses are given for one or more multipoles.
Definition Reaction.hh:76
static const std::vector< int > & get_projectiles(ProcessType proc_type)
Definition Reaction.cc:358
const std::string & source_file() const
Get the resolved path of the reaction data file used to construct this Reaction.
Definition Reaction.hh:104
static void get_residue_pdg_and_charge(ProcessType proc_type, int pdg_b, int &pdg_d, int &q_d)
Definition Reaction.cc:573
virtual std::shared_ptr< HepMC3::GenEvent > make_event_object(double KEa, double pc_cm, double cos_theta_c_cm, double phi_c_cm, double Ec_cm, double Ed_cm, int residue_status) const
Helper function that makes an event object.
Definition Reaction.cc:247
static std::vector< std::unique_ptr< Reaction > > load_from_file(const std::string &filename, StructureDatabase &db, CoulombCorrector::CoulombMode coulomb_mode, const JSON &ff_config)
Definition Reaction.cc:366
int pdg_c_
PDG code for the ejectile.
Definition Reaction.hh:144
const std::string source_file_
Resolved path of the reaction data file.
Definition Reaction.hh:210
int pdg_d_
PDG code for the residue.
Definition Reaction.hh:145
int pdg_a() const
Get the projectile PDG code.
Definition Reaction.hh:109
int pdg_b_
PDG code for the target.
Definition Reaction.hh:143
double ma_
Projectile mass (MeV)
Definition Reaction.hh:147
int pdg_b() const
Get the target PDG code.
Definition Reaction.hh:112
double mb_
Target mass (MeV)
Definition Reaction.hh:148
Container for nuclear structure information organized by nuclide.
static void get_gs_spin_parity(int nuc_pdg, int &twoJ, marley::Parity &Pi)
Looks up the ground-state spin-parity for a particular nuclide.
marley::DecayScheme * get_decay_scheme(const int particle_id)
Retrieves discrete level data from the database.
An atomic target for a lepton scattering reaction.
Definition TargetAtom.hh:26