Version: SMASH-3.3
smash::CrossSections Class Reference

#include <crosssections.h>

The cross section class assembels everything that is needed to calculate the cross section and returns a list of all possible reactions for the incoming particles at the given energy with the calculated cross sections.

Definition at line 31 of file crosssections.h.

Public Member Functions

 CrossSections (const ParticleList &incoming_particles, double sqrt_s, const std::pair< FourVector, FourVector > potentials)
 Construct CrossSections instance. More...
 
CollisionBranchList generate_collision_list (const ScatterActionsFinderParameters &finder_parameters, StringProcess *string_process) const
 Generate a list of all possible collisions between the incoming particles with the given c.m. More...
 
double parametrized_total (const ScatterActionsFinderParameters &finder_parameters) const
 Select the parametrization for the total cross section, given the types of incoming particles. More...
 
CollisionBranchPtr elastic (const ScatterActionsFinderParameters &finder_parameters) const
 Determine the elastic cross section for this collision. More...
 
CollisionBranchList two_to_one () const
 Find all resonances that can be produced in a 2->1 collision of the two input particles and the production cross sections of these resonances. More...
 
double formation (const ParticleType &type_resonance, double cm_momentum_sqr) const
 Return the 2-to-1 resonance production cross section for a given resonance. More...
 
CollisionBranchList rare_two_to_two () const
 Find all 2->2 processes which are suppressed at high energies when strings are turned on with probabilites, but important for the production of rare species such as strange particles. More...
 
CollisionBranchList two_to_two (const ReactionsBitSet &included_2to2, double KN_offset) const
 Find all inelastic 2->2 processes for the given scattering. More...
 
CollisionBranchList two_to_three () const
 Find all 2->3 processes for the given scattering. More...
 
CollisionBranchList two_to_four () const
 Find all 2->4 processes for the given scattering. More...
 
CollisionBranchList string_excitation (double total_string_xs, StringProcess *string_process, const ScatterActionsFinderParameters &finder_parameters) const
 Determine the cross section for string excitations, which is given by the difference between the parametrized total cross section and all the explicitly implemented channels at low energy (elastic, resonance excitation, etc). More...
 
CollisionBranchPtr NNbar_annihilation (double current_xs, double scale_xs) const
 Determine the cross section for NNbar annihilation, which is given by the difference between the parametrized total cross section and all the explicitly implemented channels at low energy (in this case only elastic). More...
 
CollisionBranchList NNbar_creation () const
 Determine the cross section for NNbar creation, which is given by detailed balance from the reverse reaction. More...
 
CollisionBranchPtr NNbar_to_5pi (double scale_xs) const
 Create collision branch for NNbar annihilation going directly into 5 pions. More...
 
double high_energy (const ScatterActionsFinderParameters &finder_parameters) const
 Determine the parametrized total cross section at high energies for the given collision, which is non-zero for Baryon-Baryon and Nucleon-Pion scatterings currently. More...
 
double string_probability (const ScatterActionsFinderParameters &finder_parameters) const
 
double probability_transit_high (double region_lower, double region_upper) const
 

Static Public Member Functions

static double sum_xs_of (const CollisionBranchList &list)
 Helper function: Sum all cross sections of the given process list. More...
 
static double d_pi_inelastic_xs (double pion_kinetic_energy)
 Parametrization of deuteron-pion inelastic cross section. More...
 
static double d_N_inelastic_xs (double N_kinetic_energy)
 Parametrization of deuteron-nucleon inelastic cross section. More...
 
static double d_aN_inelastic_xs (double aN_kinetic_energy)
 Parametrization of deuteron-antinucleon inelastic cross section. More...
 
static double two_to_three_xs (const ParticleType &type_in1, const ParticleType &type_in2, double sqrts)
 Determine 2->3 cross section for the scattering of the given particle types. More...
 
static double two_to_four_xs (const ParticleType &type_in1, const ParticleType &type_in2, double sqrts)
 Determine 2->4 cross section for the scattering of the given particle types. More...
 

Private Member Functions

double elastic_parametrization (const ScatterActionsFinderParameters &finder_parameters) const
 Choose the appropriate parametrizations for given incoming particles and return the (parametrized) elastic cross section. More...
 
double nn_el () const
 Determine the (parametrized) elastic cross section for a nucleon-nucleon (NN) collision. More...
 
double npi_el () const
 Determine the elastic cross section for a nucleon-pion (Npi) collision. More...
 
double nk_el () const
 Determine the elastic cross section for a nucleon-kaon (NK) collision. More...
 
CollisionBranchList npi_yk () const
 Find all processes for Nucleon-Pion to Hyperon-Kaon Scattering. More...
 
CollisionBranchList bb_xx_except_nn (const ReactionsBitSet &included_2to2) const
 Find all inelastic 2->2 processes for Baryon-Baryon (BB) Scattering except the more specific Nucleon-Nucleon Scattering. More...
 
CollisionBranchList nn_xx (const ReactionsBitSet &included_2to2) const
 Find all inelastic 2->2 processes for Nucelon-Nucelon Scattering. More...
 
CollisionBranchList nk_xx (const ReactionsBitSet &included_2to2, double KN_offset) const
 Find all inelastic 2->2 background processes for Nucleon-Kaon (NK) Scattering. More...
 
CollisionBranchList deltak_xx (const ReactionsBitSet &included_2to2) const
 Find all inelastic 2->2 processes for Delta-Kaon (DeltaK) Scattering. More...
 
CollisionBranchList ypi_xx (const ReactionsBitSet &included_2to2) const
 Find all inelastic 2->2 processes for Hyperon-Pion (Ypi) Scattering. More...
 
CollisionBranchList dpi_xx (const ReactionsBitSet &included_2to2) const
 Find all inelastic 2->2 processes involving Pion and (anti-) Deuteron (dpi), specifically dπ→ NN, d̅π→ N̅N̅; πd→ πd' (mockup for πd→ πnp), πd̅→ πd̅' and reverse. More...
 
CollisionBranchList dn_xx (const ReactionsBitSet &included_2to2) const
 Find all inelastic 2->2 processes involving Nucleon and (anti-) Deuteron (dN), specifically Nd → Nd', N̅d → N̅d', N̅d̅→ N̅d̅', Nd̅→ Nd̅' and reverse (e.g. More...
 
double string_hard_cross_section () const
 Determine the (parametrized) hard non-diffractive string cross section for this collision. More...
 
CollisionBranchList bar_bar_to_nuc_nuc (const bool is_anti_particles) const
 Calculate cross sections for resonance absorption (i.e. More...
 
template<class IntegrationMethod >
CollisionBranchList find_nn_xsection_from_type (const ParticleTypePtrList &type_res_1, const ParticleTypePtrList &type_res_2, const IntegrationMethod integrator) const
 Utility function to avoid code replication in nn_xx(). More...
 
double cm_momentum () const
 Determine the momenta of the incoming particles in the center-of-mass system. More...
 
template<typename F >
void add_channel (CollisionBranchList &process_list, F &&get_xsection, double sqrts, const ParticleType &type_a, const ParticleType &type_b) const
 Helper function: Add a 2-to-2 channel to a collision branch list given a cross section. More...
 

Static Private Member Functions

static double xs_dpi_dprimepi (double sqrts, double cm_mom, ParticleTypePtr produced_nucleus, const ParticleType &type_pi)
 Parametrized cross section for πd→ πd' (mockup for πd→ πnp), πd̅→ πd̅' and reverse, see Oliinychenko:2018ugs [47] for details. More...
 
static double xs_dn_dprimen (double sqrts, double cm_mom, ParticleTypePtr produced_nucleus, const ParticleType &type_nucleus, const ParticleType &type_N)
 Parametrized cross section for Nd → Nd', N̅d → N̅d', N̅d̅→ N̅d̅', Nd̅→ Nd̅' and reverse (e.g. More...
 
static double nn_to_resonance_matrix_element (double sqrts, const ParticleType &type_a, const ParticleType &type_b, const int twoI)
 Scattering matrix amplitude squared (divided by 16π) for resonance production processes like NN → NR and NN → ΔR, where R is a baryon resonance (Δ, N*, Δ*). More...
 

Private Attributes

const ParticleList incoming_particles_
 List with data of scattering particles. More...
 
const double sqrt_s_
 Total energy in the center-of-mass frame. More...
 
const std::pair< FourVector, FourVectorpotentials_
 Potentials at the interacting point. More...
 
const bool is_BBbar_pair_
 Whether incoming particles are a pair of a baryon and an antibaryon (could be different baryon types) More...
 
const bool is_NNbar_pair_
 Whether incoming particles are a nulecon-antinucleon pair (same isospin) More...
 

Constructor & Destructor Documentation

◆ CrossSections()

smash::CrossSections::CrossSections ( const ParticleList &  incoming_particles,
double  sqrt_s,
const std::pair< FourVector, FourVector potentials 
)

Construct CrossSections instance.

Parameters
[in]incoming_particlesParticles that are reacting.
[in]sqrt_sCenter-of-mass energy of the reaction.
[in]potentialsPotentials at the interacting point. they are used to calculate the corrections on the thresholds.

Definition at line 117 of file crosssections.cc.

120  : incoming_particles_(incoming_particles),
121  sqrt_s_(sqrt_s),
122  potentials_(potentials),
123  is_BBbar_pair_(incoming_particles_[0].type().is_baryon() &&
124  incoming_particles_[1].type().is_baryon() &&
125  incoming_particles_[0].type().antiparticle_sign() ==
126  -incoming_particles_[1].type().antiparticle_sign()),
128  incoming_particles_[0].type().is_nucleon() &&
129  incoming_particles_[1].pdgcode() ==
130  incoming_particles_[0].type().get_antiparticle()->pdgcode()) {}
const double sqrt_s_
Total energy in the center-of-mass frame.
const std::pair< FourVector, FourVector > potentials_
Potentials at the interacting point.
const ParticleList incoming_particles_
List with data of scattering particles.
const bool is_BBbar_pair_
Whether incoming particles are a pair of a baryon and an antibaryon (could be different baryon types)
const bool is_NNbar_pair_
Whether incoming particles are a nulecon-antinucleon pair (same isospin)

Member Function Documentation

◆ generate_collision_list()

CollisionBranchList smash::CrossSections::generate_collision_list ( const ScatterActionsFinderParameters finder_parameters,
StringProcess string_process 
) const

Generate a list of all possible collisions between the incoming particles with the given c.m.

energy and the calculated cross sections. The string processes are not added at this step if it's not triggerd according to the probability. It will then be added in add_all_scatterings in scatteraction.cc

Parameters
[in]finder_parametersparameters for collision finding.
[in]string_processa pointer to the StringProcess object, which is used for string excitation and fragmentation.
Returns
List of all possible collisions.

Definition at line 132 of file crosssections.cc.

134  {
135  CollisionBranchList process_list;
136  const ParticleType& t1 = incoming_particles_[0].type();
137  const ParticleType& t2 = incoming_particles_[1].type();
138 
139  double p_pythia = 0.;
140  if (finder_parameters.strings_with_probability) {
141  p_pythia = string_probability(finder_parameters);
142  }
143 
144  /* Elastic collisions between two nucleons with sqrt_s below
145  * low_snn_cut can not happen. */
146  const bool reject_by_nucleon_elastic_cutoff =
147  t1.is_nucleon() && t2.is_nucleon() &&
148  t1.antiparticle_sign() == t2.antiparticle_sign() &&
149  sqrt_s_ < finder_parameters.low_snn_cut;
150  bool incl_elastic =
151  finder_parameters.included_2to2[IncludedReactions::Elastic];
152  if (incl_elastic && !reject_by_nucleon_elastic_cutoff) {
153  process_list.emplace_back(elastic(finder_parameters));
154  }
155  if (incoming_particles_[0].is_core() != incoming_particles_[1].is_core()) {
156  return process_list;
157  }
158  if (p_pythia > 0.) {
159  /* String-excitation cross section =
160  * Parametrized total cross - the contributions
161  * from all other present channels. */
162  const double sig_current = sum_xs_of(process_list);
163  const double sig_string = std::max(
164  0., finder_parameters.scale_xs * high_energy(finder_parameters) -
165  sig_current);
166  append_list(
167  process_list,
168  string_excitation(sig_string, string_process, finder_parameters),
169  p_pythia);
170  append_list(process_list, rare_two_to_two(),
171  p_pythia * finder_parameters.scale_xs);
172  }
173  if (p_pythia < 1.) {
174  if (finder_parameters.two_to_one) {
175  // resonance formation (2->1)
176  append_list(process_list, two_to_one(),
177  (1. - p_pythia) * finder_parameters.scale_xs);
178  }
179  if (finder_parameters.included_2to2.any()) {
180  // 2->2 (inelastic)
181  append_list(
182  process_list,
183  two_to_two(finder_parameters.included_2to2,
184  finder_parameters.transition_high_energy.KN_offset),
185  (1. - p_pythia) * finder_parameters.scale_xs);
186  }
187  if (finder_parameters
189  1) {
190  // 2->3 (deuterons only 2-to-3 reaction at the moment)
191  append_list(process_list, two_to_three(),
192  (1. - p_pythia) * finder_parameters.scale_xs);
193  }
194  if (finder_parameters
196  1) {
197  // 2->4
198  append_list(process_list, two_to_four(),
199  (1. - p_pythia) * finder_parameters.scale_xs);
200  }
201  }
202  if (finder_parameters.nnbar_treatment == NNbarTreatment::TwoToFive &&
203  is_NNbar_pair_) {
204  // NNbar directly to 5 pions (2-to-5)
205  process_list.emplace_back(NNbar_to_5pi(finder_parameters.scale_xs));
206  }
207 
208  /* NNbar annihilation thru NNbar → ρh₁(1170); combined with the decays
209  * ρ → ππ and h₁(1170) → πρ, this gives a final state of 5 pions.
210  * Only use in cases when detailed balance MUST happen, i.e. in a box! */
211  if (finder_parameters.nnbar_treatment == NNbarTreatment::Resonances) {
212  if (is_NNbar_pair_) {
213  /* Has to be called after the other processes are already determined,
214  * so that the sum of the cross sections includes all other processes. */
215  process_list.emplace_back(NNbar_annihilation(sum_xs_of(process_list),
216  finder_parameters.scale_xs));
217  } else {
218  append_list(process_list, NNbar_creation(), finder_parameters.scale_xs);
219  }
220  }
221  return process_list;
222 }
CollisionBranchList two_to_two(const ReactionsBitSet &included_2to2, double KN_offset) const
Find all inelastic 2->2 processes for the given scattering.
CollisionBranchPtr NNbar_to_5pi(double scale_xs) const
Create collision branch for NNbar annihilation going directly into 5 pions.
CollisionBranchList NNbar_creation() const
Determine the cross section for NNbar creation, which is given by detailed balance from the reverse r...
double high_energy(const ScatterActionsFinderParameters &finder_parameters) const
Determine the parametrized total cross section at high energies for the given collision,...
double string_probability(const ScatterActionsFinderParameters &finder_parameters) const
CollisionBranchList two_to_four() const
Find all 2->4 processes for the given scattering.
CollisionBranchPtr elastic(const ScatterActionsFinderParameters &finder_parameters) const
Determine the elastic cross section for this collision.
CollisionBranchList two_to_one() const
Find all resonances that can be produced in a 2->1 collision of the two input particles and the produ...
CollisionBranchList string_excitation(double total_string_xs, StringProcess *string_process, const ScatterActionsFinderParameters &finder_parameters) const
Determine the cross section for string excitations, which is given by the difference between the para...
CollisionBranchList rare_two_to_two() const
Find all 2->2 processes which are suppressed at high energies when strings are turned on with probabi...
static double sum_xs_of(const CollisionBranchList &list)
Helper function: Sum all cross sections of the given process list.
Definition: crosssections.h:76
CollisionBranchList two_to_three() const
Find all 2->3 processes for the given scattering.
CollisionBranchPtr NNbar_annihilation(double current_xs, double scale_xs) const
Determine the cross section for NNbar annihilation, which is given by the difference between the para...
@ TwoToFive
Directly create 5 pions, use with multi-particle reactions.
@ Resonances
Use intermediate Resonances.
@ A3_Nuclei_4to2
@ Deuteron_3to2
static void append_list(CollisionBranchList &main_list, CollisionBranchList in_list, double weight=1.)
Helper function: Append a list of processes to another (main) list of processes.

◆ parametrized_total()

double smash::CrossSections::parametrized_total ( const ScatterActionsFinderParameters finder_parameters) const

Select the parametrization for the total cross section, given the types of incoming particles.

Parameters
[in]finder_parametersParameters for collision finding, containing cut for low energy NN interactions.
Returns
The appropriate total cross section value.

Definition at line 224 of file crosssections.cc.

225  {
226  const PdgCode& pdg_a = incoming_particles_[0].type().pdgcode();
227  const PdgCode& pdg_b = incoming_particles_[1].type().pdgcode();
228  double total_xs = 0.;
229  if (pdg_a.is_baryon() && pdg_b.is_baryon() &&
230  sqrt_s_ > finder_parameters.low_snn_cut) {
231  if (pdg_a.antiparticle_sign() == pdg_b.antiparticle_sign()) {
232  // NN
233  total_xs = (pdg_a == pdg_b) ? pp_total(sqrt_s_ * sqrt_s_)
234  : np_total(sqrt_s_ * sqrt_s_);
235  } else {
236  // NNbar
237  total_xs = ppbar_total(sqrt_s_ * sqrt_s_);
238  }
239  total_xs *= finder_parameters.AQM_scaling_factor(pdg_a) *
240  finder_parameters.AQM_scaling_factor(pdg_b);
241  } else if ((pdg_a.is_baryon() && pdg_b.is_meson()) ||
242  (pdg_a.is_meson() && pdg_b.is_baryon())) {
243  const PdgCode& meson = pdg_a.is_meson() ? pdg_a : pdg_b;
244  const PdgCode& baryon = pdg_a.is_meson() ? pdg_b : pdg_a;
245  if (meson.is_kaon() && baryon.is_nucleon()) {
246  if ((meson.code() == pdg::K_p && baryon.code() == pdg::p) ||
247  (meson.code() == pdg::K_z && baryon.code() == pdg::n) ||
248  (meson.code() == pdg::K_m && baryon.code() == -pdg::p) ||
249  (meson.code() == pdg::Kbar_z && baryon.code() == -pdg::n)) {
250  // K⁺p, K⁰n, and anti-processes
251  total_xs = kplusp_total(sqrt_s_ * sqrt_s_);
252  } else if ((meson.code() == pdg::K_p && baryon.code() == -pdg::p) ||
253  (meson.code() == pdg::K_z && baryon.code() == -pdg::n) ||
254  (meson.code() == pdg::K_m && baryon.code() == pdg::p) ||
255  (meson.code() == pdg::Kbar_z && baryon.code() == pdg::n)) {
256  // K⁻p, K̅⁰n, and anti-processes
257  total_xs = kminusp_total(sqrt_s_ * sqrt_s_);
258  } else if ((meson.code() == pdg::K_p && baryon.code() == pdg::n) ||
259  (meson.code() == pdg::K_z && baryon.code() == pdg::p) ||
260  (meson.code() == pdg::K_m && baryon.code() == -pdg::n) ||
261  (meson.code() == pdg::Kbar_z && baryon.code() == -pdg::p)) {
262  // K⁺n, K⁰p, and anti-processes
263  total_xs = kplusn_total(sqrt_s_ * sqrt_s_);
264  } else if ((meson.code() == pdg::K_p && baryon.code() == -pdg::n) ||
265  (meson.code() == pdg::K_z && baryon.code() == -pdg::p) ||
266  (meson.code() == pdg::K_m && baryon.code() == pdg::n) ||
267  (meson.code() == pdg::Kbar_z && baryon.code() == pdg::p)) {
268  // K⁻n, K̅⁰p and anti-processes
269  total_xs = kminusn_total(sqrt_s_ * sqrt_s_);
270  }
271  } else if (meson.is_pion() && baryon.is_nucleon()) {
272  // π⁺(p,nbar), π⁻(n,pbar)
273  if ((meson.code() == pdg::pi_p &&
274  (baryon.code() == pdg::p || baryon.code() == -pdg::n)) ||
275  (meson.code() == pdg::pi_m &&
276  (baryon.code() == pdg::n || baryon.code() == -pdg::p))) {
277  total_xs = piplusp_total(sqrt_s_);
278  } else if (meson.code() == pdg::pi_z) {
279  // π⁰N
280  total_xs = 0.5 * (piplusp_total(sqrt_s_) + piminusp_total(sqrt_s_));
281  } else {
282  // π⁻(p,nbar), π⁺(n,pbar)
283  total_xs = piminusp_total(sqrt_s_);
284  }
285  } else {
286  // M*+B* goes to AQM high energy π⁻p
287  total_xs = piminusp_high_energy(sqrt_s_ * sqrt_s_) *
288  finder_parameters.AQM_scaling_factor(pdg_a) *
289  finder_parameters.AQM_scaling_factor(pdg_b);
290  }
291  } else if (pdg_a.is_meson() && pdg_b.is_meson()) {
292  if (pdg_a.is_pion() && pdg_b.is_pion()) {
293  switch (pdg_a.isospin3() * pdg_b.isospin3() / 4) {
294  // π⁺π⁻
295  case -1:
296  total_xs = pipluspiminus_total(sqrt_s_);
297  break;
298  case 0:
299  // π⁰π⁰
300  if (pdg_a.isospin3() + pdg_b.isospin3() == 0) {
301  total_xs = pizeropizero_total(sqrt_s_);
302  } else {
303  // π⁺π⁰: similar to π⁺π⁻
304  total_xs = pipluspiminus_total(sqrt_s_);
305  }
306  break;
307  // π⁺π⁺ goes to π⁻p AQM
308  case 1:
309  total_xs = (2. / 3.) * piminusp_high_energy(sqrt_s_ * sqrt_s_);
310  break;
311  default:
312  throw std::runtime_error("wrong isospin in ππ scattering");
313  }
314  } else {
315  // M*+M* goes to AQM high energy π⁻p
316  total_xs = (2. / 3.) * piminusp_high_energy(sqrt_s_ * sqrt_s_) *
317  finder_parameters.AQM_scaling_factor(pdg_a) *
318  finder_parameters.AQM_scaling_factor(pdg_b);
319  }
320  }
321  return (total_xs + finder_parameters.additional_el_xs) *
322  finder_parameters.scale_xs;
323 }
constexpr int pi_p
π⁺.
constexpr int K_p
K⁺.
constexpr int K_z
K⁰.
constexpr int p
Proton.
constexpr int K_m
K̄⁻.
constexpr int pi_z
π⁰.
constexpr int n
Neutron.
constexpr int pi_m
π⁻.
constexpr int Kbar_z
K̄⁰.
double kplusp_total(double mandelstam_s)
K+ p total cross section parametrization.
double pizeropizero_total(double sqrts)
pi0 pi0 total cross section parametrized from PDG2018, smoothed using the LOWESS algorithm.
double pipluspiminus_total(double sqrts)
pi+ pi- total cross section parametrized from PDG2018, smoothed using the LOWESS algorithm.
double ppbar_total(double mandelstam_s)
ppbar total cross section parametrization Source: Bass:1998ca
double np_total(double mandelstam_s)
np total cross section parametrization Sources: low-p: Cugnon:1996kh highest-p: Buss:2011mx
double piminusp_total(double sqrts)
pi- p total cross section parametrized from PDG2018, smoothed using the LOWESS algorithm.
double pp_total(double mandelstam_s)
pp total cross section parametrization Sources: low-p: Cugnon:1996kh highest-p: Buss:2011mx
double kplusn_total(double mandelstam_s)
K+ n total cross section parametrization.
double kminusp_total(double mandelstam_s)
K- p total cross section parametrization.
double piplusp_total(double sqrts)
pi+ p total cross section parametrized from PDG2018, smoothed using the LOWESS algorithm.
double piminusp_high_energy(double mandelstam_s)
pi-p total cross section at high energies
double kminusn_total(double mandelstam_s)
K- n total cross section parametrization.

◆ sum_xs_of()

static double smash::CrossSections::sum_xs_of ( const CollisionBranchList &  list)
inlinestatic

Helper function: Sum all cross sections of the given process list.

Definition at line 76 of file crosssections.h.

76  {
77  double xs_sum = 0.0;
78  for (auto& proc : list) {
79  xs_sum += proc->weight();
80  }
81  return xs_sum;
82  }

◆ elastic()

CollisionBranchPtr smash::CrossSections::elastic ( const ScatterActionsFinderParameters finder_parameters) const

Determine the elastic cross section for this collision.

If elastic_par is given (and positive), we just use a constant cross section of that size, otherwise a parametrization of the elastic cross section is used (if available). Optional a constant additional elastic cross section is added

Parameters
[in]finder_parametersparameters for collision finding, including cross section modifications from config file.
Note
The additional constant elastic cross section contribution is added after the scaling of the cross section.
Returns
A ProcessBranch object containing the cross section and final-state IDs.

Definition at line 325 of file crosssections.cc.

326  {
327  double elastic_xs = 0.;
328 
329  if (finder_parameters.elastic_parameter >= 0.) {
330  // use constant elastic cross section from config file
331  elastic_xs = finder_parameters.elastic_parameter;
332  } else {
333  // use parametrization
334  elastic_xs = elastic_parametrization(finder_parameters);
335  }
336  /* when using a factor to scale the cross section and an additional
337  * contribution to the elastic cross section, the contribution is added first
338  * and then everything is scaled */
339  return std::make_unique<CollisionBranch>(
340  incoming_particles_[0].type(), incoming_particles_[1].type(),
341  (elastic_xs + finder_parameters.additional_el_xs) *
342  finder_parameters.scale_xs,
344 }
double elastic_parametrization(const ScatterActionsFinderParameters &finder_parameters) const
Choose the appropriate parametrizations for given incoming particles and return the (parametrized) el...
@ Elastic
See here for a short description.

◆ two_to_one()

CollisionBranchList smash::CrossSections::two_to_one ( ) const

Find all resonances that can be produced in a 2->1 collision of the two input particles and the production cross sections of these resonances.

Given the data and type information of two colliding particles, create a list of possible resonance production processes and their cross sections.

Returns
A list of processes with resonance in the final state. Each element in the list contains the type of the final-state particle and the cross section for that particular process.

Definition at line 871 of file crosssections.cc.

871  {
872  CollisionBranchList resonance_process_list;
873  const ParticleType& type_particle_a = incoming_particles_[0].type();
874  const ParticleType& type_particle_b = incoming_particles_[1].type();
875 
876  const double m1 = incoming_particles_[0].effective_mass();
877  const double m2 = incoming_particles_[1].effective_mass();
878  const double p_cm_sqr = pCM_sqr(sqrt_s_, m1, m2);
879 
880  ParticleTypePtrList possible_resonances =
881  list_possible_resonances(&type_particle_a, &type_particle_b);
882 
883  // Find all the possible resonances
884  for (const ParticleTypePtr type_resonance : possible_resonances) {
885  double resonance_xsection = formation(*type_resonance, p_cm_sqr);
886 
887  // If cross section is non-negligible, add resonance to the list
888  if (resonance_xsection > really_small) {
889  resonance_process_list.push_back(std::make_unique<CollisionBranch>(
890  *type_resonance, resonance_xsection, ProcessType::TwoToOne));
891  logg[LCrossSections].debug("Found resonance: ", *type_resonance);
892  logg[LCrossSections].debug(type_particle_a.name(), type_particle_b.name(),
893  "->", type_resonance->name(),
894  " at sqrt(s)[GeV] = ", sqrt_s_,
895  " with xs[mb] = ", resonance_xsection);
896  }
897  }
898  return resonance_process_list;
899 }
double formation(const ParticleType &type_resonance, double cm_momentum_sqr) const
Return the 2-to-1 resonance production cross section for a given resonance.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:40
ParticleTypePtrList list_possible_resonances(const ParticleTypePtr type_a, const ParticleTypePtr type_b)
Lists the possible resonances that decay into two particles.
T pCM_sqr(const T sqrts, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:91
@ TwoToOne
See here for a short description.
static constexpr int LCrossSections
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:41

◆ formation()

double smash::CrossSections::formation ( const ParticleType type_resonance,
double  cm_momentum_sqr 
) const

Return the 2-to-1 resonance production cross section for a given resonance.

Parameters
[in]type_resonanceType information for the resonance to be produced.
[in]cm_momentum_sqrSquare of the center-of-mass momentum of the two initial particles.
Returns
The cross section for the process [initial particle a] + [initial particle b] -> resonance.

Calculate resonance production cross section using the Breit-Wigner distribution as probability amplitude. See Eq. (176) in Buss:2011mx [14].

Definition at line 901 of file crosssections.cc.

902  {
903  const ParticleType& type_particle_a = incoming_particles_[0].type();
904  const ParticleType& type_particle_b = incoming_particles_[1].type();
905 
906  // Calculate partial in-width.
907  const double partial_width = type_resonance.get_partial_in_width(
909  if (partial_width <= 0.) {
910  return 0.;
911  }
912 
913  assert(type_resonance.charge() ==
914  type_particle_a.charge() + type_particle_b.charge());
915  assert(type_resonance.baryon_number() ==
916  type_particle_a.baryon_number() + type_particle_b.baryon_number());
917 
918  // Calculate spin factor
919  const double spinfactor =
920  static_cast<double>(type_resonance.spin() + 1) /
921  ((type_particle_a.spin() + 1) * (type_particle_b.spin() + 1));
922  const int sym_factor =
923  (type_particle_a.pdgcode() == type_particle_b.pdgcode()) ? 2 : 1;
927  return spinfactor * sym_factor * 2. * M_PI * M_PI / cm_momentum_sqr *
928  type_resonance.spectral_function(sqrt_s_) * partial_width * hbarc *
929  hbarc / fm2_mb;
930 }
constexpr double hbarc
GeV <-> fm conversion factor.
Definition: constants.h:29
constexpr double fm2_mb
mb <-> fm^2 conversion factor.
Definition: constants.h:32

◆ rare_two_to_two()

CollisionBranchList smash::CrossSections::rare_two_to_two ( ) const

Find all 2->2 processes which are suppressed at high energies when strings are turned on with probabilites, but important for the production of rare species such as strange particles.

This function should call the different, more specific functions for the different scatterings. But so far, only Nucleon-Pion to Hyperon- Kaon scattering is implemented.

Returns
List of all possible rare 2->2 processes.

Definition at line 346 of file crosssections.cc.

346  {
347  CollisionBranchList process_list;
348  const ParticleData& data_a = incoming_particles_[0];
349  const ParticleData& data_b = incoming_particles_[1];
350  const auto& pdg_a = data_a.pdgcode();
351  const auto& pdg_b = data_b.pdgcode();
352  if ((pdg_a.is_nucleon() && pdg_b.is_pion()) ||
353  (pdg_b.is_nucleon() && pdg_a.is_pion())) {
354  process_list = npi_yk();
355  }
356  return process_list;
357 }
CollisionBranchList npi_yk() const
Find all processes for Nucleon-Pion to Hyperon-Kaon Scattering.

◆ two_to_two()

CollisionBranchList smash::CrossSections::two_to_two ( const ReactionsBitSet included_2to2,
double  KN_offset 
) const

Find all inelastic 2->2 processes for the given scattering.

This function calls the different, more specific functions for the different scatterings.

Parameters
[in]included_2to2Which 2->2 reactions are enabled?
[in]KN_offsetOffset to the minimum energy for string production in KN scatterings
Returns
List of all possible inelastic 2->2 processes.

Definition at line 932 of file crosssections.cc.

933  {
934  CollisionBranchList process_list;
935  const ParticleData& data_a = incoming_particles_[0];
936  const ParticleData& data_b = incoming_particles_[1];
937  const ParticleType& type_a = data_a.type();
938  const ParticleType& type_b = data_b.type();
939  const auto& pdg_a = data_a.pdgcode();
940  const auto& pdg_b = data_b.pdgcode();
941 
942  if (data_a.is_baryon() && data_b.is_baryon()) {
943  if (pdg_a.is_nucleon() && pdg_b.is_nucleon() &&
944  pdg_a.antiparticle_sign() == pdg_b.antiparticle_sign()) {
945  // Nucleon Nucleon Scattering
946  process_list = nn_xx(included_2to2);
947  } else {
948  // Baryon Baryon Scattering
949  process_list = bb_xx_except_nn(included_2to2);
950  }
951  } else if ((type_a.is_baryon() && type_b.is_meson()) ||
952  (type_a.is_meson() && type_b.is_baryon())) {
953  // Baryon Meson Scattering
954  if ((pdg_a.is_nucleon() && pdg_b.is_kaon()) ||
955  (pdg_b.is_nucleon() && pdg_a.is_kaon())) {
956  // Nucleon Kaon Scattering
957  process_list = nk_xx(included_2to2, KN_offset);
958  } else if ((pdg_a.is_hyperon() && pdg_b.is_pion()) ||
959  (pdg_b.is_hyperon() && pdg_a.is_pion())) {
960  // Hyperon Pion Scattering
961  process_list = ypi_xx(included_2to2);
962  } else if ((pdg_a.is_Delta() && pdg_b.is_kaon()) ||
963  (pdg_b.is_Delta() && pdg_a.is_kaon())) {
964  // Delta Kaon Scattering
965  process_list = deltak_xx(included_2to2);
966  }
967  } else if (type_a.is_nucleus() || type_b.is_nucleus()) {
968  if ((type_a.is_nucleon() && type_b.is_nucleus()) ||
969  (type_b.is_nucleon() && type_a.is_nucleus())) {
970  // Nucleon Deuteron and Nucleon d' Scattering
971  process_list = dn_xx(included_2to2);
972  } else if (((type_a.is_deuteron() || type_a.is_dprime()) &&
973  pdg_b.is_pion()) ||
974  ((type_b.is_deuteron() || type_b.is_dprime()) &&
975  pdg_a.is_pion())) {
976  // Pion Deuteron and Pion d' Scattering
977  process_list = dpi_xx(included_2to2);
978  }
979  }
980  return process_list;
981 }
CollisionBranchList dpi_xx(const ReactionsBitSet &included_2to2) const
Find all inelastic 2->2 processes involving Pion and (anti-) Deuteron (dpi), specifically dπ→ NN,...
CollisionBranchList bb_xx_except_nn(const ReactionsBitSet &included_2to2) const
Find all inelastic 2->2 processes for Baryon-Baryon (BB) Scattering except the more specific Nucleon-...
CollisionBranchList deltak_xx(const ReactionsBitSet &included_2to2) const
Find all inelastic 2->2 processes for Delta-Kaon (DeltaK) Scattering.
CollisionBranchList nk_xx(const ReactionsBitSet &included_2to2, double KN_offset) const
Find all inelastic 2->2 background processes for Nucleon-Kaon (NK) Scattering.
CollisionBranchList dn_xx(const ReactionsBitSet &included_2to2) const
Find all inelastic 2->2 processes involving Nucleon and (anti-) Deuteron (dN), specifically Nd → Nd',...
CollisionBranchList ypi_xx(const ReactionsBitSet &included_2to2) const
Find all inelastic 2->2 processes for Hyperon-Pion (Ypi) Scattering.
CollisionBranchList nn_xx(const ReactionsBitSet &included_2to2) const
Find all inelastic 2->2 processes for Nucelon-Nucelon Scattering.

◆ two_to_three()

CollisionBranchList smash::CrossSections::two_to_three ( ) const

Find all 2->3 processes for the given scattering.

This function calls the different, more specific functions for the different scatterings.

Returns
List of all possible 2->3 processes.

Definition at line 983 of file crosssections.cc.

983  {
984  CollisionBranchList process_list;
985  const ParticleType& type_a = incoming_particles_[0].type();
986  const ParticleType& type_b = incoming_particles_[1].type();
987 
988  if ((type_a.is_deuteron() && type_b.pdgcode().is_pion()) ||
989  (type_b.is_deuteron() && type_a.pdgcode().is_pion())) {
990  const ParticleType& type_pi = type_a.pdgcode().is_pion() ? type_a : type_b;
991  const ParticleType& type_nucleus = type_a.is_nucleus() ? type_a : type_b;
992 
993  if (type_nucleus.baryon_number() > 0) {
994  // πd → πpn
995  const auto& type_p = ParticleType::find(pdg::p);
996  const auto& type_n = ParticleType::find(pdg::n);
997 
998  process_list.push_back(std::make_unique<CollisionBranch>(
999  type_pi, type_p, type_n, two_to_three_xs(type_a, type_b, sqrt_s_),
1001  } else {
1002  // πd̅ → πp̅n̅
1003  const auto& type_anti_p = ParticleType::find(-pdg::p);
1004  const auto& type_anti_n = ParticleType::find(-pdg::n);
1005 
1006  process_list.push_back(std::make_unique<CollisionBranch>(
1007  type_pi, type_anti_p, type_anti_n,
1008  two_to_three_xs(type_a, type_b, sqrt_s_), ProcessType::TwoToThree));
1009  }
1010  }
1011 
1012  if ((type_a.is_nucleon() && type_b.is_deuteron()) ||
1013  (type_b.is_nucleon() && type_a.is_deuteron())) {
1014  const ParticleType& type_N = type_a.is_nucleon() ? type_a : type_b;
1015  const ParticleType& type_nucleus = type_a.is_deuteron() ? type_a : type_b;
1016 
1017  if (type_nucleus.baryon_number() > 0) {
1018  // Nd → Nnp, N̅d → N̅np
1019  const auto& type_p = ParticleType::find(pdg::p);
1020  const auto& type_n = ParticleType::find(pdg::n);
1021 
1022  process_list.push_back(std::make_unique<CollisionBranch>(
1023  type_N, type_p, type_n, two_to_three_xs(type_a, type_b, sqrt_s_),
1025  } else {
1026  // Nd̅ → Np̅n̅, N̅d̅ → N̅p̅n̅
1027  const auto& type_anti_p = ParticleType::find(-pdg::p);
1028  const auto& type_anti_n = ParticleType::find(-pdg::n);
1029 
1030  process_list.push_back(std::make_unique<CollisionBranch>(
1031  type_N, type_anti_p, type_anti_n,
1032  two_to_three_xs(type_a, type_b, sqrt_s_), ProcessType::TwoToThree));
1033  }
1034  }
1035  return process_list;
1036 }
static double two_to_three_xs(const ParticleType &type_in1, const ParticleType &type_in2, double sqrts)
Determine 2->3 cross section for the scattering of the given particle types.
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
Definition: particletype.cc:99
@ TwoToThree
See here for a short description.

◆ two_to_four()

CollisionBranchList smash::CrossSections::two_to_four ( ) const

Find all 2->4 processes for the given scattering.

This function calls the different, more specific functions for the different scatterings.

Returns
List of all possible 2->4 processes.

Definition at line 1038 of file crosssections.cc.

1038  {
1039  CollisionBranchList process_list;
1040  ParticleTypePtr type_nucleus = &(incoming_particles_[0].type());
1041  ParticleTypePtr type_catalyzer = &(incoming_particles_[1].type());
1042  if (!type_nucleus->is_nucleus()) {
1043  type_nucleus = &(incoming_particles_[1].type());
1044  type_catalyzer = &(incoming_particles_[0].type());
1045  }
1046 
1047  if (type_nucleus->is_nucleus() &&
1048  std::abs(type_nucleus->baryon_number()) == 3 &&
1049  (type_catalyzer->is_pion() || type_catalyzer->is_nucleon())) {
1050  const ParticleTypePtr type_p = ParticleType::try_find(pdg::p);
1051  const ParticleTypePtr type_n = ParticleType::try_find(pdg::n);
1052  const ParticleTypePtr type_anti_p = ParticleType::try_find(-pdg::p);
1053  const ParticleTypePtr type_anti_n = ParticleType::try_find(-pdg::n);
1054  const ParticleTypePtr type_la = ParticleType::try_find(pdg::Lambda);
1055  const ParticleTypePtr type_anti_la = ParticleType::try_find(-pdg::Lambda);
1056 
1057  // Find nucleus components
1058  ParticleTypePtrList components;
1059  components.reserve(3);
1060  const PdgCode nucleus_pdg = type_nucleus->pdgcode();
1061  for (int i = 0; i < nucleus_pdg.nucleus_p(); i++) {
1062  components.push_back(type_p);
1063  }
1064  for (int i = 0; i < nucleus_pdg.nucleus_n(); i++) {
1065  components.push_back(type_n);
1066  }
1067  for (int i = 0; i < nucleus_pdg.nucleus_ap(); i++) {
1068  components.push_back(type_anti_p);
1069  }
1070  for (int i = 0; i < nucleus_pdg.nucleus_an(); i++) {
1071  components.push_back(type_anti_n);
1072  }
1073  for (int i = 0; i < nucleus_pdg.nucleus_La(); i++) {
1074  components.push_back(type_la);
1075  }
1076  for (int i = 0; i < nucleus_pdg.nucleus_aLa(); i++) {
1077  components.push_back(type_anti_la);
1078  }
1079  if (sqrt_s_ > type_catalyzer->mass() + components[0]->mass() +
1080  components[1]->mass() + components[2]->mass()) {
1081  process_list.push_back(std::make_unique<CollisionBranch>(
1082  *type_catalyzer, *(components[0]), *(components[1]), *(components[2]),
1083  two_to_four_xs(*type_nucleus, *type_catalyzer, sqrt_s_),
1085  }
1086  }
1087  return process_list;
1088 }
static double two_to_four_xs(const ParticleType &type_in1, const ParticleType &type_in2, double sqrts)
Determine 2->4 cross section for the scattering of the given particle types.
static const ParticleTypePtr try_find(PdgCode pdgcode)
Returns the ParticleTypePtr for the given pdgcode.
Definition: particletype.cc:89
constexpr int Lambda
Λ.
@ TwoToFour
See here for a short description.

◆ string_excitation()

CollisionBranchList smash::CrossSections::string_excitation ( double  total_string_xs,
StringProcess string_process,
const ScatterActionsFinderParameters finder_parameters 
) const

Determine the cross section for string excitations, which is given by the difference between the parametrized total cross section and all the explicitly implemented channels at low energy (elastic, resonance excitation, etc).

Parameters
[in]total_string_xsTotal cross section for the string process [mb]
[in]string_processa pointer to the StringProcess object, which is used for string excitation and fragmentation
[in]finder_parametersparameters for collision finding and cross sections
Returns
List of subprocesses (single-diffractive, double-diffractive and non-diffractive) with their cross sections
Exceptions
std::runtime_errorif string_process is a null pointer

This method has to be called after all other processes have been determined.

Todo:
Same assumption made by NNbar_annihilation. Resolve.

Definition at line 2489 of file crosssections.cc.

2491  {
2492  if (!string_process) {
2493  throw std::runtime_error("string_process should be initialized.");
2494  }
2495 
2496  CollisionBranchList channel_list;
2497  if (total_string_xs <= 0.) {
2498  return channel_list;
2499  }
2500 
2501  double mandelstam_s = sqrt_s_ * sqrt_s_;
2502  /* Get mapped PDG id for evaluation of the parametrized cross sections
2503  * for diffractive processes.
2504  * This must be rescaled according to additive quark model
2505  * in the case of exotic hadrons.
2506  * Also calculate the multiplicative factor for AQM
2507  * based on the quark contents. */
2508  std::array<int, 2> pdgid;
2509  double AQM_scaling = 1.;
2510  for (int i = 0; i < 2; i++) {
2511  PdgCode pdg = incoming_particles_[i].type().pdgcode();
2512  pdgid[i] = StringProcess::pdg_map_for_pythia(pdg);
2513  AQM_scaling *= finder_parameters.AQM_scaling_factor(pdg);
2514  }
2515 
2516  /* Determine if the initial state is a baryon-antibaryon pair,
2517  * which can annihilate. */
2518  bool can_annihilate = false;
2519  if (is_BBbar_pair_) {
2520  int n_q_types = 5; // u, d, s, c, b
2521  for (int iq = 1; iq <= n_q_types; iq++) {
2522  std::array<int, 2> nquark;
2523  for (int i = 0; i < 2; i++) {
2524  nquark[i] =
2525  incoming_particles_[i].type().pdgcode().net_quark_number(iq);
2526  }
2527  if (nquark[0] != 0 && nquark[1] != 0) {
2528  can_annihilate = true;
2529  break;
2530  }
2531  }
2532  }
2533 
2534  /* The case for baryon/anti-baryon annihilation is treated separately,
2535  * as in this case we use only one way to break up the particles, namely
2536  * into 2 mesonic strings of equal mass after annihilating one quark-
2537  * anti-quark pair. See StringProcess::next_BBbarAnn() */
2538  double sig_annihilation = 0.0;
2539  if (can_annihilate) {
2540  /* In the case of baryon-antibaryon pair,
2541  * the parametrized cross section for annihilation will be added.
2542  * See xs_ppbar_annihilation(). */
2543  mandelstam_s = effective_AQM_s(
2544  mandelstam_s, incoming_particles_[0].effective_mass(),
2545  incoming_particles_[1].effective_mass(), nucleon_mass, nucleon_mass);
2546  double xs_param = xs_ppbar_annihilation(mandelstam_s);
2547  if (finder_parameters.use_AQM) {
2548  xs_param *= AQM_scaling;
2549  }
2550  sig_annihilation = std::min(total_string_xs, xs_param);
2551  }
2552 
2553  /* Total parametrized cross-section (I) and pythia-produced total
2554  * cross-section (II) do not necessarily coincide. If I > II then
2555  * non-diffractive cross-section is reinforced to get I == II.
2556  * If I < II then partial cross-sections are drained one-by-one
2557  * to reduce II until I == II:
2558  * first non-diffractive, then double-diffractive, then
2559  * single-diffractive AB->AX and AB->XB in equal proportion.
2560  * The way it is done here is not unique. I (ryu) think that at high energy
2561  * collision this is not an issue, but at sqrt_s < 10 GeV it may
2562  * matter. */
2563  std::array<double, 3> xs = string_process->cross_sections_diffractive(
2564  pdgid[0], pdgid[1], std::sqrt(mandelstam_s));
2565  if (finder_parameters.use_AQM) {
2566  for (int ip = 0; ip < 3; ip++) {
2567  xs[ip] *= AQM_scaling;
2568  }
2569  }
2570  double single_diffr_AX = xs[0], single_diffr_XB = xs[1], double_diffr = xs[2];
2571  double single_diffr = single_diffr_AX + single_diffr_XB;
2572  double diffractive = single_diffr + double_diffr;
2573 
2574  const double nondiffractive_all =
2575  std::max(0., total_string_xs - sig_annihilation - diffractive);
2576  diffractive = total_string_xs - sig_annihilation - nondiffractive_all;
2577  double_diffr = std::max(0., diffractive - single_diffr);
2578  const double a = (diffractive - double_diffr) / single_diffr;
2579  single_diffr_AX *= a;
2580  single_diffr_XB *= a;
2581  assert(std::abs(single_diffr_AX + single_diffr_XB + double_diffr +
2582  sig_annihilation + nondiffractive_all - total_string_xs) <
2583  1.e-6);
2584 
2585  double nondiffractive_soft = 0.;
2586  double nondiffractive_hard = 0.;
2587  if (nondiffractive_all > 0.) {
2588  /* Hard string process is added by hard cross section
2589  * in conjunction with multipartion interaction picture
2590  * \iref{Sjostrand:1987su}. */
2591  const double hard_xsec = AQM_scaling * string_hard_cross_section();
2592  nondiffractive_soft =
2593  nondiffractive_all * std::exp(-hard_xsec / nondiffractive_all);
2594  nondiffractive_hard = nondiffractive_all - nondiffractive_soft;
2595  }
2596  logg[LCrossSections].debug("String cross sections [mb] are");
2597  logg[LCrossSections].debug("Single-diffractive AB->AX: ", single_diffr_AX);
2598  logg[LCrossSections].debug("Single-diffractive AB->XB: ", single_diffr_XB);
2599  logg[LCrossSections].debug("Double-diffractive AB->XX: ", double_diffr);
2600  logg[LCrossSections].debug("Soft non-diffractive: ", nondiffractive_soft);
2601  logg[LCrossSections].debug("Hard non-diffractive: ", nondiffractive_hard);
2602  logg[LCrossSections].debug("B-Bbar annihilation: ", sig_annihilation);
2603 
2604  /* cross section of soft string excitation including annihilation */
2605  const double sig_string_soft = total_string_xs - nondiffractive_hard;
2606 
2607  /* fill the list of process channels */
2608  if (sig_string_soft > 0.) {
2609  channel_list.push_back(std::make_unique<CollisionBranch>(
2610  single_diffr_AX, ProcessType::StringSoftSingleDiffractiveAX));
2611  channel_list.push_back(std::make_unique<CollisionBranch>(
2612  single_diffr_XB, ProcessType::StringSoftSingleDiffractiveXB));
2613  channel_list.push_back(std::make_unique<CollisionBranch>(
2615  channel_list.push_back(std::make_unique<CollisionBranch>(
2616  nondiffractive_soft, ProcessType::StringSoftNonDiffractive));
2617  if (can_annihilate) {
2618  channel_list.push_back(std::make_unique<CollisionBranch>(
2619  sig_annihilation, ProcessType::StringSoftAnnihilation));
2620  }
2621  }
2622  if (nondiffractive_hard > 0.) {
2623  channel_list.push_back(std::make_unique<CollisionBranch>(
2624  nondiffractive_hard, ProcessType::StringHard));
2625  }
2626  return channel_list;
2627 }
double string_hard_cross_section() const
Determine the (parametrized) hard non-diffractive string cross section for this collision.
static int pdg_map_for_pythia(PdgCode &pdg)
Take pdg code and map onto particle specie which can be handled by PYTHIA.
@ StringSoftDoubleDiffractive
See here for a short description.
@ StringSoftSingleDiffractiveXB
See here for a short description.
@ StringSoftAnnihilation
See here for a short description.
@ StringSoftNonDiffractive
See here for a short description.
@ StringSoftSingleDiffractiveAX
See here for a short description.
@ StringHard
See here for a short description.
constexpr double nucleon_mass
Nucleon mass in GeV.
Definition: constants.h:62
double xs_ppbar_annihilation(double mandelstam_s)
parametrized cross-section for proton-antiproton annihilation used in the UrQMD model
static double effective_AQM_s(double mandelstam_s, double m1, double m2, double m1_ref, double m2_ref)
Helper function: Shift the energy of a collision for AQM rescaled cross sections.

◆ NNbar_annihilation()

CollisionBranchPtr smash::CrossSections::NNbar_annihilation ( double  current_xs,
double  scale_xs 
) const

Determine the cross section for NNbar annihilation, which is given by the difference between the parametrized total cross section and all the explicitly implemented channels at low energy (in this case only elastic).

Parameters
[in]current_xsSum of all cross sections of already determined processes
[in]scale_xsFactor by which all (partial) cross sections are scaled
Returns
Collision Branch with NNbar annihilation process and its cross section

This method has to be called after all other processes have been determined.

Todo:
Same assumption made by string_excitation. Resolve.

Definition at line 2741 of file crosssections.cc.

2742  {
2743  /* Calculate NNbar cross section:
2744  * Parametrized total minus all other present channels.*/
2745  const double s = sqrt_s_ * sqrt_s_;
2746  double nnbar_xsec = std::max(0., ppbar_total(s) * scale_xs - current_xs);
2747  logg[LCrossSections].debug("NNbar cross section is: ", nnbar_xsec);
2748  // Make collision channel NNbar -> ρh₁(1170); eventually decays into 5π
2749  return std::make_unique<CollisionBranch>(ParticleType::find(pdg::h1),
2751  nnbar_xsec, ProcessType::TwoToTwo);
2752 }
constexpr int h1
h₁(1170).
constexpr int rho_z
ρ⁰.
@ TwoToTwo
See here for a short description.

◆ NNbar_creation()

CollisionBranchList smash::CrossSections::NNbar_creation ( ) const

Determine the cross section for NNbar creation, which is given by detailed balance from the reverse reaction.

See NNbar_annihilation.

Returns
Collision Branch with NNbar creation process and its cross section

Definition at line 2754 of file crosssections.cc.

2754  {
2755  CollisionBranchList channel_list;
2756  const ParticleType& type_a = incoming_particles_[0].type();
2757  const ParticleType& type_b = incoming_particles_[1].type();
2758  if ((type_a.pdgcode() == pdg::rho_z && type_b.pdgcode() == pdg::h1) ||
2759  (type_a.pdgcode() == pdg::h1 && type_b.pdgcode() == pdg::rho_z)) {
2760  /* Calculate NNbar reverse cross section:
2761  * from reverse reaction (see NNbar_annihilation_cross_section).*/
2762  const double s = sqrt_s_ * sqrt_s_;
2763  const double pcm = cm_momentum();
2764 
2765  const auto& type_N = ParticleType::find(pdg::p);
2766  const auto& type_Nbar = ParticleType::find(-pdg::p);
2767 
2768  // Check available energy
2769  if (sqrt_s_ - 2 * type_N.mass() < 0) {
2770  return channel_list;
2771  }
2772 
2773  double xsection = detailed_balance_factor_RR(sqrt_s_, pcm, type_a, type_b,
2774  type_N, type_Nbar) *
2775  std::max(0., ppbar_total(s) - ppbar_elastic(s));
2776  logg[LCrossSections].debug("NNbar reverse cross section is: ", xsection);
2777  channel_list.push_back(std::make_unique<CollisionBranch>(
2778  type_N, type_Nbar, xsection, ProcessType::TwoToTwo));
2779  channel_list.push_back(std::make_unique<CollisionBranch>(
2782  }
2783  return channel_list;
2784 }
double cm_momentum() const
Determine the momenta of the incoming particles in the center-of-mass system.
static double detailed_balance_factor_RR(double sqrts, double pcm, const ParticleType &a, const ParticleType &b, const ParticleType &c, const ParticleType &d)
Helper function: Calculate the detailed balance factor R such that.
double ppbar_elastic(double mandelstam_s)
ppbar elastic cross section parametrization Source: Bass:1998ca

◆ NNbar_to_5pi()

CollisionBranchPtr smash::CrossSections::NNbar_to_5pi ( double  scale_xs) const

Create collision branch for NNbar annihilation going directly into 5 pions.

The cross section is given by the parametrized ppbar cross section, which is also used for the reverse 5-to-2 process.

Parameters
[in]scale_xsFactor by which all (partial) cross sections are scaled
Returns
Collision Branch with NNbar annihilation process

Definition at line 2724 of file crosssections.cc.

2724  {
2725  const double s = sqrt_s_ * sqrt_s_;
2726  /* Use difference between total and elastic in order to conserve detailed
2727  * balance for all inelastoc NNbar processes. */
2728  const double nnbar_xsec = std::max(0., ppbar_total(s) - ppbar_elastic(s));
2729  logg[LCrossSections].debug("NNbar cross section for 2-to-5 is: ", nnbar_xsec);
2730 
2731  /* Make collision channel NNbar -> 5π (with same final state as resonance
2732  * approach). */
2733  const auto& type_piz = ParticleType::find(pdg::pi_z);
2734  const auto& type_pip = ParticleType::find(pdg::pi_p);
2735  const auto& type_pim = ParticleType::find(pdg::pi_m);
2736  return std::make_unique<CollisionBranch>(
2737  type_pip, type_pim, type_pip, type_pim, type_piz, nnbar_xsec * scale_xs,
2739 }
@ TwoToFive
See here for a short description.

◆ d_pi_inelastic_xs()

double smash::CrossSections::d_pi_inelastic_xs ( double  pion_kinetic_energy)
static

Parametrization of deuteron-pion inelastic cross section.

Parameters
[in]pion_kinetic_energypion kinetic energy [GeV] in the deuteron rest frame
Returns
cross section [mb]

Definition at line 1090 of file crosssections.cc.

1090  {
1091  const double x = pion_kinetic_energy;
1092  return x * (4.3 + 10.0 * x) / ((x - 0.16) * (x - 0.16) + 0.007);
1093 }

◆ d_N_inelastic_xs()

double smash::CrossSections::d_N_inelastic_xs ( double  N_kinetic_energy)
static

Parametrization of deuteron-nucleon inelastic cross section.

Parameters
[in]N_kinetic_energyNucleon kinetic energy [GeV] in the deuteron rest frame
Returns
cross section [mb]

Definition at line 1095 of file crosssections.cc.

1095  {
1096  const double x = N_kinetic_energy;
1097  return x * (1.0 + 50 * x) / (x * x + 0.01) +
1098  4 * x / ((x - 0.008) * (x - 0.008) + 0.0004);
1099 }

◆ d_aN_inelastic_xs()

double smash::CrossSections::d_aN_inelastic_xs ( double  aN_kinetic_energy)
static

Parametrization of deuteron-antinucleon inelastic cross section.

Parameters
[in]aN_kinetic_energy[GeV] Anti-nucleon kinetic energy in the deuteron rest frame
Returns
cross section [mb]

Definition at line 1101 of file crosssections.cc.

1101  {
1102  return 55.0 / (aN_kinetic_energy + 0.17);
1103 }

◆ two_to_three_xs()

double smash::CrossSections::two_to_three_xs ( const ParticleType type_in1,
const ParticleType type_in2,
double  sqrts 
)
static

Determine 2->3 cross section for the scattering of the given particle types.

That the function only depends on the types of particles (plus sqrt(s)) and not on the specific particles, is an assumption needed in order to treat the 3->2 back-reaction with the stochastic criterion, where this function also needs to be called for 3-to-2 collision probability with only types and sqrt(s) known at this point. Therefore the function is also made static.

Parameters
[in]type_in1first scatterning particle type
[in]type_in2second scatterning particle type
[in]sqrtscenter-of-mass energy of scattering
Returns
cross section for 2->3 process

Definition at line 1105 of file crosssections.cc.

1107  {
1108  double xs = 0.0;
1109  ParticleTypePtr type_nucleus = &type_a, type_catalyzer = &type_b;
1110  if (!type_nucleus->is_nucleus()) {
1111  type_nucleus = &type_b;
1112  type_catalyzer = &type_a;
1113  }
1114 
1115  bool nonzero_xs = type_nucleus->is_nucleus() &&
1116  (type_catalyzer->is_pion() || type_catalyzer->is_nucleon());
1117  if (!nonzero_xs) {
1118  return 0.0;
1119  }
1120 
1121  const double md = type_nucleus->mass(), mcat = type_catalyzer->mass();
1122  const double Tkin = (sqrts * sqrts - (md + mcat) * (md + mcat)) / (2.0 * md);
1123 
1124  // Should normally never happen, but may be a useful safeguard
1125  if (Tkin <= 0.0) {
1126  return 0.0;
1127  }
1128 
1129  if (type_catalyzer->is_pion()) {
1130  xs = d_pi_inelastic_xs(Tkin);
1131  } else if (type_catalyzer->is_nucleon()) {
1132  if (type_nucleus->pdgcode().antiparticle_sign() ==
1133  type_catalyzer->pdgcode().antiparticle_sign()) {
1134  // Nd and N̅d̅
1135  xs = d_N_inelastic_xs(Tkin);
1136  } else {
1137  // N̅d and Nd̅
1138  xs = d_aN_inelastic_xs(Tkin);
1139  }
1140  }
1141  return xs;
1142 }
static double d_N_inelastic_xs(double N_kinetic_energy)
Parametrization of deuteron-nucleon inelastic cross section.
static double d_aN_inelastic_xs(double aN_kinetic_energy)
Parametrization of deuteron-antinucleon inelastic cross section.
static double d_pi_inelastic_xs(double pion_kinetic_energy)
Parametrization of deuteron-pion inelastic cross section.

◆ two_to_four_xs()

double smash::CrossSections::two_to_four_xs ( const ParticleType type_in1,
const ParticleType type_in2,
double  sqrts 
)
static

Determine 2->4 cross section for the scattering of the given particle types.

Same assumptions as for 2->3 cross section, see respective documentation.

Parameters
[in]type_in1first scatterning particle type
[in]type_in2second scatterning particle type
[in]sqrtscenter-of-mass energy of scattering
Returns
cross section for 2->4 process

Definition at line 1144 of file crosssections.cc.

1145  {
1146  double xs = 0.0;
1147  ParticleTypePtr type_nucleus = &type_a, type_catalyzer = &type_b;
1148  if (!type_nucleus->is_nucleus()) {
1149  type_nucleus = &type_b;
1150  type_catalyzer = &type_a;
1151  }
1152  bool nonzero_xs = type_nucleus->is_nucleus() &&
1153  (type_catalyzer->is_pion() || type_catalyzer->is_nucleon());
1154  if (!nonzero_xs) {
1155  return 0.0;
1156  }
1157 
1158  const double mA = type_nucleus->mass(), mcat = type_catalyzer->mass();
1159  const double Tkin = (sqrts * sqrts - (mA + mcat) * (mA + mcat)) / (2.0 * mA);
1160  const int A = type_nucleus->pdgcode().nucleus_A();
1161  // Should normally never happen, but may be a useful safeguard
1162  if (A != 3 || Tkin <= 0.0) {
1163  return 0.0;
1164  }
1165 
1166  if (type_catalyzer->is_pion()) {
1167  xs = A / 2. * d_pi_inelastic_xs(Tkin);
1168  } else if (type_catalyzer->is_nucleon()) {
1169  if (type_nucleus->pdgcode().antiparticle_sign() ==
1170  type_catalyzer->pdgcode().antiparticle_sign()) {
1171  // N + A, anti-N + anti-A
1172  xs = A / 2. * d_N_inelastic_xs(Tkin);
1173  } else {
1174  // N̅ + A and N + anti-A
1175  xs = A / 2. * d_aN_inelastic_xs(Tkin);
1176  }
1177  }
1178  return xs;
1179 }

◆ high_energy()

double smash::CrossSections::high_energy ( const ScatterActionsFinderParameters finder_parameters) const

Determine the parametrized total cross section at high energies for the given collision, which is non-zero for Baryon-Baryon and Nucleon-Pion scatterings currently.

This is rescaled by AQM factors.

Parameters
[in]finder_parametersparameters for collision finding and cross sections.

Definition at line 2629 of file crosssections.cc.

2630  {
2631  const PdgCode& pdg_a = incoming_particles_[0].type().pdgcode();
2632  const PdgCode& pdg_b = incoming_particles_[1].type().pdgcode();
2633 
2634  const double s = sqrt_s_ * sqrt_s_;
2635  double xs = 0.;
2636 
2637  // Currently all BB collisions use the nucleon-nucleon parametrizations.
2638  if (pdg_a.is_baryon() && pdg_b.is_baryon()) {
2639  const double eff_s = effective_AQM_s(
2640  s, incoming_particles_[0].effective_mass(),
2641  incoming_particles_[1].effective_mass(), nucleon_mass, nucleon_mass);
2642  if (pdg_a == pdg_b) {
2643  xs = pp_high_energy(eff_s); // pp, nn
2644  } else if (pdg_a.antiparticle_sign() * pdg_b.antiparticle_sign() == 1) {
2645  xs = np_high_energy(eff_s); // np, nbarpbar
2646  } else if (pdg_a.antiparticle_sign() * pdg_b.antiparticle_sign() == -1) {
2647  /* In the case of baryon-antibaryon interactions,
2648  * the low-energy cross section must be involved
2649  * due to annihilation processes (via strings). */
2650  double xs_l = ppbar_total(eff_s);
2651  double xs_h = 0.;
2652  if (pdg_a.is_antiparticle_of(pdg_b)) {
2653  xs_h = ppbar_high_energy(eff_s); // ppbar, nnbar
2654  } else {
2655  xs_h = npbar_high_energy(eff_s); // npbar, nbarp
2656  }
2657  /* Transition between low and high energy is set to be consistent with
2658  * that defined in string_probability(). */
2659  auto [region_lower, region_upper] =
2660  finder_parameters.transition_high_energy.sqrts_range_NN;
2661  double prob_high = probability_transit_high(region_lower, region_upper);
2662  xs = xs_l * (1. - prob_high) + xs_h * prob_high;
2663  }
2664  }
2665 
2666  // Pion nucleon interaction / baryon-meson
2667  if ((pdg_a == pdg::pi_p && pdg_b == pdg::p) ||
2668  (pdg_b == pdg::pi_p && pdg_a == pdg::p) ||
2669  (pdg_a == pdg::pi_m && pdg_b == pdg::n) ||
2670  (pdg_b == pdg::pi_m && pdg_a == pdg::n)) {
2671  xs = piplusp_high_energy(s); // pi+ p, pi- n
2672  } else if ((pdg_a == pdg::pi_m && pdg_b == pdg::p) ||
2673  (pdg_b == pdg::pi_m && pdg_a == pdg::p) ||
2674  (pdg_a == pdg::pi_p && pdg_b == pdg::n) ||
2675  (pdg_b == pdg::pi_p && pdg_a == pdg::n)) {
2676  xs = piminusp_high_energy(s); // pi- p, pi+ n
2677  } else if ((pdg_a.is_meson() && pdg_b.is_baryon()) ||
2678  (pdg_b.is_meson() && pdg_a.is_baryon())) {
2679  xs = piminusp_high_energy(s); // default for baryon-meson
2680  }
2681 
2682  /* Meson-meson interaction goes through AQM from pi+p,
2683  * see user guide "Use_AQM"*/
2684  if (pdg_a.is_meson() && pdg_b.is_meson()) {
2685  /* 2/3 factor since difference of 1 meson between meson-meson
2686  * and baryon-meson */
2687  xs = 2. / 3. * piplusp_high_energy(s);
2688  }
2689 
2690  // AQM scaling for cross-sections
2691  xs *= finder_parameters.AQM_scaling_factor(pdg_a) *
2692  finder_parameters.AQM_scaling_factor(pdg_b);
2693 
2694  return xs;
2695 }
double probability_transit_high(double region_lower, double region_upper) const
double npbar_high_energy(double mandelstam_s)
npbar total cross section at high energies
double np_high_energy(double mandelstam_s)
np total cross section at high energies
double ppbar_high_energy(double mandelstam_s)
ppbar total cross section at high energies
double pp_high_energy(double mandelstam_s)
pp total cross section at high energies
double piplusp_high_energy(double mandelstam_s)
pi+p total cross section at high energies

◆ string_probability()

double smash::CrossSections::string_probability ( const ScatterActionsFinderParameters finder_parameters) const
Returns
the probability whether the scattering between the incoming particles is via string fragmentation or not.

If use_transition_probability is true: The string fragmentation is implemented in the same way in GiBUU (Physics Reports 512(2012), 1-124, pg. 33). If the center of mass energy is low, two particles scatter through the resonance channels. If high, the outgoing particles are generated by string fragmentation. If in between, the out- going particles are generated either through the resonance channels or string fragmentation by chance. In detail, the low energy region is from the threshold to (mix_scatter_type_energy - mix_scatter_type_window_width), while the high energy region is from (mix_scatter_type_energy + mix_scatter_type_window_width) to infinity. In between, the probability for string fragmentation increases smoothly from 0 to 1 as the c.m. energy.

If use_transition_probability is false: The string fragmentation is implemented similarly to what is in UrQMD (Bass:1998ca [6]). If sqrts is lower than some cutoff value, there are no strings. If higher, strings are allowed, with the cross-section being the difference between some parametrized total cross-section and the sum of all other channels, if this parametrization is larger than the sum of the channels. If not, strings are not allowed (this cross-section check is performed directly after the function is called, for technical reasons).

Both of these methods are initially implemented for NN and Npi cross- sections, and extended using the AQM to all BB, BM and MM interactions.

Baryon-antibaryon annihilation also uses this function to decide whether to produce strings or not. Since there are no other contributions for this process, there are no cutoffs or gradual increase in the probability of this process happening or not, it just requires the proper combination of incoming particles and config parameters.

Parameters
[in]finder_parametersparameters for collision finding and cross sections.

Definition at line 3014 of file crosssections.cc.

3015  {
3016  /* string fragmentation is enabled when strings_switch is on and the process
3017  * is included in pythia. */
3018  if (!finder_parameters.strings_switch) {
3019  return 0.;
3020  }
3021 
3022  const ParticleType& t1 = incoming_particles_[0].type();
3023  const ParticleType& t2 = incoming_particles_[1].type();
3024  const bool treat_BBbar_with_strings =
3025  (finder_parameters.nnbar_treatment == NNbarTreatment::Strings);
3026  const bool is_NN_scattering =
3027  t1.is_nucleon() && t2.is_nucleon() &&
3028  t1.antiparticle_sign() == t2.antiparticle_sign();
3029  const bool is_BBbar_scattering =
3030  (treat_BBbar_with_strings && is_BBbar_pair_ &&
3031  finder_parameters.use_AQM) ||
3032  (t1.is_nucleon() && t2.is_nucleon() &&
3033  t1.antiparticle_sign() != t2.antiparticle_sign());
3034  const bool is_Npi_scattering = (t1.pdgcode().is_pion() && t2.is_nucleon()) ||
3035  (t1.is_nucleon() && t2.pdgcode().is_pion());
3036  /* True for baryon-baryon, anti-baryon-anti-baryon, baryon-meson,
3037  * anti-baryon-meson and meson-meson*/
3038  const bool is_AQM_scattering =
3039  finder_parameters.use_AQM &&
3040  ((t1.is_baryon() && t2.is_baryon() &&
3041  t1.antiparticle_sign() == t2.antiparticle_sign()) ||
3042  ((t1.is_baryon() && t2.is_meson()) ||
3043  (t2.is_baryon() && t1.is_meson())) ||
3044  (t1.is_meson() && t2.is_meson()));
3045  const double mass_sum =
3046  incoming_particles_[0].pole_mass() + incoming_particles_[1].pole_mass();
3047 
3048  if (!is_NN_scattering && !is_BBbar_scattering && !is_Npi_scattering &&
3049  !is_AQM_scattering) {
3050  return 0.;
3051  } else if (is_NNbar_pair_ && !treat_BBbar_with_strings) {
3052  return 0.;
3053  } else if (is_BBbar_scattering) {
3054  // BBbar only goes through strings, so there are no "window" considerations
3055  return 1.;
3056  } else {
3057  /* true for K+ p and K0 p (+ antiparticles), which have special treatment
3058  * to fit data */
3059  const PdgCode pdg1 = t1.pdgcode(), pdg2 = t2.pdgcode();
3060  const bool is_KplusP =
3061  ((pdg1 == pdg::K_p || pdg1 == pdg::K_z) && (pdg2 == pdg::p)) ||
3062  ((pdg2 == pdg::K_p || pdg2 == pdg::K_z) && (pdg1 == pdg::p)) ||
3063  ((pdg1 == -pdg::K_p || pdg1 == -pdg::K_z) && (pdg2 == -pdg::p)) ||
3064  ((pdg2 == -pdg::K_p || pdg2 == -pdg::K_z) && (pdg1 == -pdg::p));
3065  // where to start the AQM strings above mass sum
3066  double aqm_offset =
3067  finder_parameters.transition_high_energy.sqrts_add_lower;
3068  if (is_KplusP) {
3069  /* for this specific case we have data. This corresponds to the point
3070  * where the AQM parametrization is smaller than the current 2to2
3071  * parametrization, which starts growing and diverges from exp. data */
3072  aqm_offset = finder_parameters.transition_high_energy.KN_offset;
3073  } else if (pdg1.is_pion() && pdg2.is_pion()) {
3074  aqm_offset = finder_parameters.transition_high_energy.pipi_offset;
3075  }
3076  /* if we do not use the probability transition algorithm, this is always a
3077  * string contribution if the energy is large enough */
3078  if (!finder_parameters.strings_with_probability) {
3079  return static_cast<double>(sqrt_s_ > mass_sum + aqm_offset);
3080  }
3081  /* No strings at low energy, only strings at high energy and
3082  * a transition region in the middle. Determine transition region: */
3083  double region_lower, region_upper;
3084  if (is_Npi_scattering) {
3085  std::tie(region_lower, region_upper) =
3086  finder_parameters.transition_high_energy.sqrts_range_Npi;
3087  } else if (is_NN_scattering) {
3088  std::tie(region_lower, region_upper) =
3089  finder_parameters.transition_high_energy.sqrts_range_NN;
3090  } else { // AQM - Additive Quark Model
3091  /* Transition region around 0.9 larger than the sum of pole masses;
3092  * highly arbitrary, feel free to improve */
3093  region_lower = mass_sum + aqm_offset;
3094  region_upper = mass_sum + aqm_offset +
3095  finder_parameters.transition_high_energy.sqrts_range_width;
3096  }
3097 
3098  if (sqrt_s_ > region_upper) {
3099  return 1.;
3100  } else if (sqrt_s_ < region_lower) {
3101  return 0.;
3102  } else {
3103  // Rescale transition region to [-1, 1]
3104  return probability_transit_high(region_lower, region_upper);
3105  }
3106  }
3107 }
@ Strings
Use string fragmentation.

◆ probability_transit_high()

double smash::CrossSections::probability_transit_high ( double  region_lower,
double  region_upper 
) const
Parameters
[in]region_lowerthe lowest sqrts in the transition region [GeV]
[in]region_upperthe highest sqrts in the transition region [GeV]
Returns
probability to have the high energy interaction (via string)

Definition at line 3109 of file crosssections.cc.

3110  {
3111  if (sqrt_s_ < region_lower) {
3112  return 0.;
3113  }
3114 
3115  if (sqrt_s_ > region_upper) {
3116  return 1.;
3117  }
3118 
3119  double x = (sqrt_s_ - 0.5 * (region_lower + region_upper)) /
3120  (region_upper - region_lower);
3121  assert(x >= -0.5 && x <= 0.5);
3122  double prob = 0.5 * (std::sin(M_PI * x) + 1.0);
3123  assert(prob >= 0. && prob <= 1.);
3124 
3125  return prob;
3126 }

◆ elastic_parametrization()

double smash::CrossSections::elastic_parametrization ( const ScatterActionsFinderParameters finder_parameters) const
private

Choose the appropriate parametrizations for given incoming particles and return the (parametrized) elastic cross section.

Parameters
[in]finder_parametersparameters for collision finding and cross sections, containing whether to extend string cross-sections with AQM and the offset to the minimum energy for string production in \(\pi\pi \) scatterings
Returns
Elastic cross section

Definition at line 359 of file crosssections.cc.

360  {
361  const bool use_AQM = finder_parameters.use_AQM;
362  const double pipi_offset =
363  finder_parameters.transition_high_energy.pipi_offset;
364  const PdgCode& pdg_a = incoming_particles_[0].type().pdgcode();
365  const PdgCode& pdg_b = incoming_particles_[1].type().pdgcode();
366  double elastic_xs = 0.0;
367  if ((pdg_a.is_nucleon() && pdg_b.is_pion()) ||
368  (pdg_b.is_nucleon() && pdg_a.is_pion())) {
369  // Elastic Nucleon Pion Scattering
370  elastic_xs = npi_el();
371  } else if ((pdg_a.is_nucleon() && pdg_b.is_kaon()) ||
372  (pdg_b.is_nucleon() && pdg_a.is_kaon())) {
373  // Elastic Nucleon Kaon Scattering
374  elastic_xs = nk_el();
375  } else if (pdg_a.is_nucleon() && pdg_b.is_nucleon() &&
376  pdg_a.antiparticle_sign() == pdg_b.antiparticle_sign()) {
377  // Elastic Nucleon Nucleon Scattering
378  elastic_xs = nn_el();
379  } else if (pdg_a.is_nucleon() && pdg_b.is_nucleon() &&
380  pdg_a.antiparticle_sign() == -pdg_b.antiparticle_sign()) {
381  // Elastic Nucleon anti-Nucleon Scattering
382  elastic_xs = ppbar_elastic(sqrt_s_ * sqrt_s_);
383  } else if (pdg_a.is_nucleus() || pdg_b.is_nucleus()) {
384  const PdgCode& pdg_nucleus = pdg_a.is_nucleus() ? pdg_a : pdg_b;
385  const PdgCode& pdg_other = pdg_a.is_nucleus() ? pdg_b : pdg_a;
386  const bool is_deuteron = pdg_nucleus.is_deuteron(); // d or anti-d
387  if (is_deuteron && pdg_other.is_pion()) {
388  // Elastic (Anti-)deuteron Pion Scattering
389  elastic_xs = deuteron_pion_elastic(sqrt_s_ * sqrt_s_);
390  } else if (is_deuteron && pdg_other.is_nucleon()) {
391  // Elastic (Anti-)deuteron (Anti-)Nucleon Scattering
392  elastic_xs = deuteron_nucleon_elastic(sqrt_s_ * sqrt_s_);
393  }
394  } else if (use_AQM) {
395  const double m1 = incoming_particles_[0].effective_mass();
396  const double m2 = incoming_particles_[1].effective_mass();
397  const double s = sqrt_s_ * sqrt_s_;
398  if (pdg_a.is_baryon() && pdg_b.is_baryon()) {
399  elastic_xs = nn_el(); // valid also for annihilation
400  } else if ((pdg_a.is_meson() && pdg_b.is_baryon()) ||
401  (pdg_b.is_meson() && pdg_a.is_baryon())) {
402  elastic_xs = piplusp_elastic_high_energy(s, m1, m2);
403  } else if (pdg_a.is_meson() && pdg_b.is_meson()) {
404  /* Special case: the pi+pi- elastic cross-section goes through resonances
405  * at low sqrt_s, so we turn it off for this region so as not to destroy
406  * the agreement with experimental data; this does not
407  * apply to other pi pi cross-sections, which do not have any data */
408  if (((pdg_a == pdg::pi_p && pdg_b == pdg::pi_m) ||
409  (pdg_a == pdg::pi_m && pdg_b == pdg::pi_p)) &&
410  (m1 + m2 + pipi_offset) > sqrt_s_) {
411  elastic_xs = 0.0;
412  } else {
413  // meson-meson goes through scaling from π+p parametrization
414  elastic_xs = 2. / 3. * piplusp_elastic_AQM(s, m1, m2);
415  }
416  }
417  elastic_xs *= finder_parameters.AQM_scaling_factor(pdg_a) *
418  finder_parameters.AQM_scaling_factor(pdg_b);
419  }
420  return elastic_xs;
421 }
double nk_el() const
Determine the elastic cross section for a nucleon-kaon (NK) collision.
double npi_el() const
Determine the elastic cross section for a nucleon-pion (Npi) collision.
double nn_el() const
Determine the (parametrized) elastic cross section for a nucleon-nucleon (NN) collision.
double piplusp_elastic_high_energy(double mandelstam_s, double m1, double m2)
pi+p elactic cross section parametrization.
double deuteron_nucleon_elastic(double mandelstam_s)
Deuteron nucleon elastic cross-section [mb] parametrized by Oh:2009gx .
double deuteron_pion_elastic(double mandelstam_s)
Deuteron pion elastic cross-section [mb] parametrized to fit pi-d elastic scattering data (the data c...
double piplusp_elastic_AQM(double mandelstam_s, double m1, double m2)
An overload of piplusp_elastic_high_energy in which the very low part is replaced by a flat 5 mb cros...

◆ nn_el()

double smash::CrossSections::nn_el ( ) const
private

Determine the (parametrized) elastic cross section for a nucleon-nucleon (NN) collision.

Returns
Elastic cross section for NN
Exceptions
std::runtime_errorif positive cross section cannot be specified.

Definition at line 423 of file crosssections.cc.

423  {
424  const PdgCode& pdg_a = incoming_particles_[0].type().pdgcode();
425  const PdgCode& pdg_b = incoming_particles_[1].type().pdgcode();
426 
427  // Use parametrized cross sections.
428  double sig_el = -1.;
429  const double s = sqrt_s_ * sqrt_s_;
430  const bool is_NN_pair = pdg_a.is_nucleon() && pdg_b.is_nucleon();
431  if (is_NN_pair) {
432  if (is_BBbar_pair_) {
433  // npbar and ppbar
434  sig_el = ppbar_elastic(s);
435  } else {
436  sig_el = (pdg_a == pdg_b) ? pp_elastic(s) : np_elastic(s);
437  }
438  } else {
439  // AQM - Additive Quark Model
440  const double m1 = incoming_particles_[0].effective_mass();
441  const double m2 = incoming_particles_[1].effective_mass();
442  if (is_BBbar_pair_) {
443  sig_el =
445  } else {
446  sig_el = pp_elastic_high_energy(s, m1, m2);
447  }
448  }
449 
450  if (sig_el > 0.) {
451  return sig_el;
452  } else {
453  std::stringstream ss;
454  const auto name_a = incoming_particles_[0].type().name();
455  const auto name_b = incoming_particles_[1].type().name();
456  ss << "problem in CrossSections::elastic: a=" << name_a << " b=" << name_b
457  << " j_a=" << pdg_a.spin() << " j_b=" << pdg_b.spin()
458  << " sigma=" << sig_el << " s=" << s;
459  throw std::runtime_error(ss.str());
460  }
461 }
double pp_elastic_high_energy(double mandelstam_s, double m1, double m2)
pp elastic cross section parametrization, with only the high energy part generalized to all energy re...
double np_elastic(double mandelstam_s)
np elastic cross section parametrization Source: Weil:2013mya , eq.
double pp_elastic(double mandelstam_s)
pp elastic cross section parametrization Source: Weil:2013mya , eq.

◆ npi_el()

double smash::CrossSections::npi_el ( ) const
private

Determine the elastic cross section for a nucleon-pion (Npi) collision.

It is given by a parametrization of experimental data.

Returns
Elastic cross section for Npi
Exceptions
std::runtime_errorif incoming particles are not nucleon+pion.
std::runtime_errorif positive cross section cannot be specified.

Definition at line 463 of file crosssections.cc.

463  {
464  const PdgCode& pdg_a = incoming_particles_[0].type().pdgcode();
465  const PdgCode& pdg_b = incoming_particles_[1].type().pdgcode();
466 
467  const PdgCode& nucleon = pdg_a.is_nucleon() ? pdg_a : pdg_b;
468  const PdgCode& pion = pdg_a.is_nucleon() ? pdg_b : pdg_a;
469  assert(pion != nucleon);
470 
471  const double s = sqrt_s_ * sqrt_s_;
472 
473  double sig_el = 0.;
474  switch (nucleon.code()) {
475  case pdg::p:
476  switch (pion.code()) {
477  case pdg::pi_p:
478  sig_el = piplusp_elastic(s);
479  break;
480  case pdg::pi_m:
481  sig_el = piminusp_elastic(s);
482  break;
483  case pdg::pi_z:
484  sig_el = 0.5 * (piplusp_elastic(s) + piminusp_elastic(s));
485  break;
486  }
487  break;
488  case pdg::n:
489  switch (pion.code()) {
490  case pdg::pi_p:
491  sig_el = piminusp_elastic(s);
492  break;
493  case pdg::pi_m:
494  sig_el = piplusp_elastic(s);
495  break;
496  case pdg::pi_z:
497  sig_el = 0.5 * (piplusp_elastic(s) + piminusp_elastic(s));
498  break;
499  }
500  break;
501  case -pdg::p:
502  switch (pion.code()) {
503  case pdg::pi_p:
504  sig_el = piminusp_elastic(s);
505  break;
506  case pdg::pi_m:
507  sig_el = piplusp_elastic(s);
508  break;
509  case pdg::pi_z:
510  sig_el = 0.5 * (piplusp_elastic(s) + piminusp_elastic(s));
511  break;
512  }
513  break;
514  case -pdg::n:
515  switch (pion.code()) {
516  case pdg::pi_p:
517  sig_el = piplusp_elastic(s);
518  break;
519  case pdg::pi_m:
520  sig_el = piminusp_elastic(s);
521  break;
522  case pdg::pi_z:
523  sig_el = 0.5 * (piplusp_elastic(s) + piminusp_elastic(s));
524  break;
525  }
526  break;
527  default:
528  throw std::runtime_error(
529  "only the elastic cross section for proton-pion "
530  "is implemented");
531  }
532 
533  if (sig_el > 0) {
534  return sig_el;
535  } else {
536  std::stringstream ss;
537  const auto name_a = incoming_particles_[0].type().name();
538  const auto name_b = incoming_particles_[1].type().name();
539  ss << "problem in CrossSections::elastic: a=" << name_a << " b=" << name_b
540  << " j_a=" << pdg_a.spin() << " j_b=" << pdg_b.spin()
541  << " sigma=" << sig_el << " s=" << s;
542  throw std::runtime_error(ss.str());
543  }
544 }
double piminusp_elastic(double mandelstam_s)
pi-p elastic cross section parametrization Source: GiBUU:parametrizationBarMes_HighEnergy....
double piplusp_elastic(double mandelstam_s)
pi+p elastic cross section parametrization, PDG data.

◆ nk_el()

double smash::CrossSections::nk_el ( ) const
private

Determine the elastic cross section for a nucleon-kaon (NK) collision.

It is given by a parametrization of experimental data.

Returns
Elastic cross section for NK
Exceptions
std::runtime_errorif incoming particles are not nucleon+kaon.
std::runtime_errorif positive cross section cannot be specified.

Definition at line 776 of file crosssections.cc.

776  {
777  const PdgCode& pdg_a = incoming_particles_[0].type().pdgcode();
778  const PdgCode& pdg_b = incoming_particles_[1].type().pdgcode();
779 
780  const PdgCode& nucleon = pdg_a.is_nucleon() ? pdg_a : pdg_b;
781  const PdgCode& kaon = pdg_a.is_nucleon() ? pdg_b : pdg_a;
782  assert(kaon != nucleon);
783 
784  const double s = sqrt_s_ * sqrt_s_;
785 
786  double sig_el = 0.;
787  switch (nucleon.code()) {
788  case pdg::p:
789  switch (kaon.code()) {
790  case pdg::K_p:
791  sig_el = kplusp_elastic_background(s);
792  break;
793  case pdg::K_m:
794  sig_el = kminusp_elastic_background(s);
795  break;
796  case pdg::K_z:
797  sig_el = k0p_elastic_background(s);
798  break;
799  case pdg::Kbar_z:
800  sig_el = kbar0p_elastic_background(s);
801  break;
802  }
803  break;
804  case pdg::n:
805  switch (kaon.code()) {
806  case pdg::K_p:
807  sig_el = kplusn_elastic_background(s);
808  break;
809  case pdg::K_m:
810  sig_el = kminusn_elastic_background(s);
811  break;
812  case pdg::K_z:
813  sig_el = k0n_elastic_background(s);
814  break;
815  case pdg::Kbar_z:
816  sig_el = kbar0n_elastic_background(s);
817  break;
818  }
819  break;
820  case -pdg::p:
821  switch (kaon.code()) {
822  case pdg::K_p:
823  sig_el = kminusp_elastic_background(s);
824  break;
825  case pdg::K_m:
826  sig_el = kplusp_elastic_background(s);
827  break;
828  case pdg::K_z:
829  sig_el = kbar0p_elastic_background(s);
830  break;
831  case pdg::Kbar_z:
832  sig_el = k0p_elastic_background(s);
833  break;
834  }
835  break;
836  case -pdg::n:
837  switch (kaon.code()) {
838  case pdg::K_p:
839  sig_el = kminusn_elastic_background(s);
840  break;
841  case pdg::K_m:
842  sig_el = kplusn_elastic_background(s);
843  break;
844  case pdg::K_z:
845  sig_el = kbar0n_elastic_background(s);
846  break;
847  case pdg::Kbar_z:
848  sig_el = k0n_elastic_background(s);
849  break;
850  }
851  break;
852  default:
853  throw std::runtime_error(
854  "elastic cross section for antinucleon-kaon "
855  "not implemented");
856  }
857 
858  if (sig_el > 0) {
859  return sig_el;
860  } else {
861  std::stringstream ss;
862  const auto name_a = incoming_particles_[0].type().name();
863  const auto name_b = incoming_particles_[1].type().name();
864  ss << "problem in CrossSections::elastic: a=" << name_a << " b=" << name_b
865  << " j_a=" << pdg_a.spin() << " j_b=" << pdg_b.spin()
866  << " sigma=" << sig_el << " s=" << s;
867  throw std::runtime_error(ss.str());
868  }
869 }
double kbar0p_elastic_background(double mandelstam_s)
Kbar0 p elastic background cross section parametrization Source: Buss:2011mx , B.3....
double kminusp_elastic_background(double mandelstam_s)
K- p elastic background cross section parametrization Source: Buss:2011mx , B.3.9.
double k0p_elastic_background(double mandelstam_s)
K0 p elastic background cross section parametrization Source: Buss:2011mx , B.3.9.
double kplusn_elastic_background(double mandelstam_s)
K+ n elastic background cross section parametrization sigma(K+n->K+n) = sigma(K+n->K0p) = 0....
double k0n_elastic_background(double mandelstam_s)
K0 n elastic background cross section parametrization Source: Buss:2011mx , B.3.9.
double kbar0n_elastic_background(double mandelstam_s)
Kbar0 n elastic background cross section parametrization Source: Buss:2011mx , B.3....
double kminusn_elastic_background(double mandelstam_s)
K- n elastic background cross section parametrization Source: Buss:2011mx , B.3.9.
double kplusp_elastic_background(double mandelstam_s)
K+ p elastic background cross section parametrization.

◆ npi_yk()

CollisionBranchList smash::CrossSections::npi_yk ( ) const
private

Find all processes for Nucleon-Pion to Hyperon-Kaon Scattering.

These scatterings are suppressed at high energies when strings are turned on with probabilities, so they need to be added back manually.

Returns
List of all possible Npi -> YK reactions with their cross sections

Definition at line 546 of file crosssections.cc.

546  {
547  const ParticleType& a = incoming_particles_[0].type();
548  const ParticleType& b = incoming_particles_[1].type();
549  const ParticleType& type_nucleon = a.pdgcode().is_nucleon() ? a : b;
550  const ParticleType& type_pion = a.pdgcode().is_nucleon() ? b : a;
551 
552  const auto pdg_nucleon = type_nucleon.pdgcode().code();
553  const auto pdg_pion = type_pion.pdgcode().code();
554 
555  const double s = sqrt_s_ * sqrt_s_;
556 
557  /* The cross sections are paramectrized for four isospin channels. The
558  * cross sections of the rest isospin channels are obtained using
559  * Clebsch-Gordan coefficients */
560 
561  CollisionBranchList process_list;
562  switch (pdg_nucleon) {
563  case pdg::p: {
564  switch (pdg_pion) {
565  case pdg::pi_p: {
566  const auto& type_Sigma_p = ParticleType::find(pdg::Sigma_p);
567  const auto& type_K_p = ParticleType::find(pdg::K_p);
568  add_channel(
569  process_list, [&] { return piplusp_sigmapluskplus_pdg(s); },
570  sqrt_s_, type_K_p, type_Sigma_p);
571  break;
572  }
573  case pdg::pi_m: {
574  const auto& type_Sigma_m = ParticleType::find(pdg::Sigma_m);
575  const auto& type_Sigma_z = ParticleType::find(pdg::Sigma_z);
576  const auto& type_Lambda = ParticleType::find(pdg::Lambda);
577  const auto& type_K_p = ParticleType::find(pdg::K_p);
578  const auto& type_K_z = ParticleType::find(pdg::K_z);
579  add_channel(
580  process_list, [&] { return piminusp_sigmaminuskplus_pdg(s); },
581  sqrt_s_, type_K_p, type_Sigma_m);
582  add_channel(
583  process_list, [&] { return piminusp_sigma0k0_res(s); }, sqrt_s_,
584  type_K_z, type_Sigma_z);
585  add_channel(
586  process_list, [&] { return piminusp_lambdak0_pdg(s); }, sqrt_s_,
587  type_K_z, type_Lambda);
588  break;
589  }
590  case pdg::pi_z: {
591  const auto& type_Sigma_p = ParticleType::find(pdg::Sigma_p);
592  const auto& type_Sigma_z = ParticleType::find(pdg::Sigma_z);
593  const auto& type_Lambda = ParticleType::find(pdg::Lambda);
594  const auto& type_K_p = ParticleType::find(pdg::K_p);
595  const auto& type_K_z = ParticleType::find(pdg::K_z);
596  add_channel(
597  process_list,
598  [&] {
599  return 0.5 * (piplusp_sigmapluskplus_pdg(s) -
602  },
603  sqrt_s_, type_K_p, type_Sigma_z);
604  add_channel(
605  process_list, [&] { return piminusp_sigma0k0_res(s); }, sqrt_s_,
606  type_K_z, type_Sigma_p);
607  add_channel(
608  process_list, [&] { return 0.5 * piminusp_lambdak0_pdg(s); },
609  sqrt_s_, type_K_p, type_Lambda);
610  break;
611  }
612  }
613  break;
614  }
615  case pdg::n: {
616  switch (pdg_pion) {
617  case pdg::pi_p: {
618  const auto& type_Sigma_p = ParticleType::find(pdg::Sigma_p);
619  const auto& type_Sigma_z = ParticleType::find(pdg::Sigma_z);
620  const auto& type_Lambda = ParticleType::find(pdg::Lambda);
621  const auto& type_K_p = ParticleType::find(pdg::K_p);
622  const auto& type_K_z = ParticleType::find(pdg::K_z);
623  add_channel(
624  process_list, [&] { return piminusp_sigmaminuskplus_pdg(s); },
625  sqrt_s_, type_K_z, type_Sigma_p);
626  add_channel(
627  process_list, [&] { return piminusp_sigma0k0_res(s); }, sqrt_s_,
628  type_K_p, type_Sigma_z);
629  add_channel(
630  process_list, [&] { return piminusp_lambdak0_pdg(s); }, sqrt_s_,
631  type_K_p, type_Lambda);
632  break;
633  }
634  case pdg::pi_m: {
635  const auto& type_Sigma_m = ParticleType::find(pdg::Sigma_m);
636  const auto& type_K_z = ParticleType::find(pdg::K_z);
637  add_channel(
638  process_list, [&] { return piplusp_sigmapluskplus_pdg(s); },
639  sqrt_s_, type_K_z, type_Sigma_m);
640  break;
641  }
642  case pdg::pi_z: {
643  const auto& type_Sigma_m = ParticleType::find(pdg::Sigma_m);
644  const auto& type_Sigma_z = ParticleType::find(pdg::Sigma_z);
645  const auto& type_Lambda = ParticleType::find(pdg::Lambda);
646  const auto& type_K_p = ParticleType::find(pdg::K_p);
647  const auto& type_K_z = ParticleType::find(pdg::K_z);
648  add_channel(
649  process_list,
650  [&] {
651  return 0.5 * (piplusp_sigmapluskplus_pdg(s) -
654  },
655  sqrt_s_, type_K_z, type_Sigma_z);
656  add_channel(
657  process_list, [&] { return piminusp_sigma0k0_res(s); }, sqrt_s_,
658  type_K_p, type_Sigma_m);
659  add_channel(
660  process_list, [&] { return 0.5 * piminusp_lambdak0_pdg(s); },
661  sqrt_s_, type_K_z, type_Lambda);
662  break;
663  }
664  }
665  break;
666  }
667  case -pdg::p: {
668  switch (pdg_pion) {
669  case pdg::pi_p: {
670  const auto& type_Sigma_m_bar = ParticleType::find(-pdg::Sigma_m);
671  const auto& type_Sigma_z_bar = ParticleType::find(-pdg::Sigma_z);
672  const auto& type_Lambda_bar = ParticleType::find(-pdg::Lambda);
673  const auto& type_K_m = ParticleType::find(-pdg::K_p);
674  const auto& type_Kbar_z = ParticleType::find(-pdg::K_z);
675  add_channel(
676  process_list, [&] { return piminusp_sigmaminuskplus_pdg(s); },
677  sqrt_s_, type_K_m, type_Sigma_m_bar);
678  add_channel(
679  process_list, [&] { return piminusp_sigma0k0_res(s); }, sqrt_s_,
680  type_Kbar_z, type_Sigma_z_bar);
681  add_channel(
682  process_list, [&] { return piminusp_lambdak0_pdg(s); }, sqrt_s_,
683  type_Kbar_z, type_Lambda_bar);
684  break;
685  }
686  case pdg::pi_m: {
687  const auto& type_Sigma_p_bar = ParticleType::find(-pdg::Sigma_p);
688  const auto& type_K_m = ParticleType::find(-pdg::K_p);
689  add_channel(
690  process_list, [&] { return piplusp_sigmapluskplus_pdg(s); },
691  sqrt_s_, type_K_m, type_Sigma_p_bar);
692  break;
693  }
694  case pdg::pi_z: {
695  const auto& type_Sigma_p_bar = ParticleType::find(-pdg::Sigma_p);
696  const auto& type_Sigma_z_bar = ParticleType::find(-pdg::Sigma_z);
697  const auto& type_Lambda_bar = ParticleType::find(-pdg::Lambda);
698  const auto& type_K_m = ParticleType::find(-pdg::K_p);
699  const auto& type_Kbar_z = ParticleType::find(-pdg::K_z);
700  add_channel(
701  process_list,
702  [&] {
703  return 0.5 * (piplusp_sigmapluskplus_pdg(s) -
706  },
707  sqrt_s_, type_K_m, type_Sigma_z_bar);
708  add_channel(
709  process_list, [&] { return piminusp_sigma0k0_res(s); }, sqrt_s_,
710  type_Kbar_z, type_Sigma_p_bar);
711  add_channel(
712  process_list, [&] { return 0.5 * piminusp_lambdak0_pdg(s); },
713  sqrt_s_, type_K_m, type_Lambda_bar);
714  break;
715  }
716  }
717  break;
718  }
719  case -pdg::n: {
720  switch (pdg_pion) {
721  case pdg::pi_p: {
722  const auto& type_Sigma_m_bar = ParticleType::find(-pdg::Sigma_m);
723  const auto& type_Kbar_z = ParticleType::find(-pdg::K_z);
724  add_channel(
725  process_list, [&] { return piplusp_sigmapluskplus_pdg(s); },
726  sqrt_s_, type_Kbar_z, type_Sigma_m_bar);
727  break;
728  }
729  case pdg::pi_m: {
730  const auto& type_Sigma_p_bar = ParticleType::find(-pdg::Sigma_p);
731  const auto& type_Sigma_z_bar = ParticleType::find(-pdg::Sigma_z);
732  const auto& type_Lambda_bar = ParticleType::find(-pdg::Lambda);
733  const auto& type_K_m = ParticleType::find(-pdg::K_p);
734  const auto& type_Kbar_z = ParticleType::find(-pdg::K_z);
735  add_channel(
736  process_list, [&] { return piminusp_sigmaminuskplus_pdg(s); },
737  sqrt_s_, type_Kbar_z, type_Sigma_p_bar);
738  add_channel(
739  process_list, [&] { return piminusp_sigma0k0_res(s); }, sqrt_s_,
740  type_K_m, type_Sigma_z_bar);
741  add_channel(
742  process_list, [&] { return piminusp_lambdak0_pdg(s); }, sqrt_s_,
743  type_K_m, type_Lambda_bar);
744  break;
745  }
746  case pdg::pi_z: {
747  const auto& type_Sigma_m_bar = ParticleType::find(-pdg::Sigma_m);
748  const auto& type_Sigma_z_bar = ParticleType::find(-pdg::Sigma_z);
749  const auto& type_Lambda_bar = ParticleType::find(-pdg::Lambda);
750  const auto& type_K_m = ParticleType::find(-pdg::K_p);
751  const auto& type_Kbar_z = ParticleType::find(-pdg::K_z);
752  add_channel(
753  process_list,
754  [&] {
755  return 0.5 * (piplusp_sigmapluskplus_pdg(s) -
758  },
759  sqrt_s_, type_Kbar_z, type_Sigma_z_bar);
760  add_channel(
761  process_list, [&] { return piminusp_sigma0k0_res(s); }, sqrt_s_,
762  type_K_m, type_Sigma_m_bar);
763  add_channel(
764  process_list, [&] { return 0.5 * piminusp_lambdak0_pdg(s); },
765  sqrt_s_, type_Kbar_z, type_Lambda_bar);
766  break;
767  }
768  }
769  break;
770  }
771  }
772 
773  return process_list;
774 }
void add_channel(CollisionBranchList &process_list, F &&get_xsection, double sqrts, const ParticleType &type_a, const ParticleType &type_b) const
Helper function: Add a 2-to-2 channel to a collision branch list given a cross section.
constexpr int Sigma_m
Σ⁻.
constexpr int Sigma_p
Σ⁺.
constexpr int Sigma_z
Σ⁰.
double piminusp_sigma0k0_res(double mandelstam_s)
pi- p -> Sigma0 K0 cross section parametrization, resonance contribution.
double piplusp_sigmapluskplus_pdg(double mandelstam_s)
pi+ p to Sigma+ K+ cross section parametrization, PDG data.
double piminusp_sigmaminuskplus_pdg(double mandelstam_s)
pi- p -> Sigma- K+ cross section parametrization, PDG data.
double piminusp_lambdak0_pdg(double mandelstam_s)
pi- p -> Lambda K0 cross section parametrization, PDG data.

◆ bb_xx_except_nn()

CollisionBranchList smash::CrossSections::bb_xx_except_nn ( const ReactionsBitSet included_2to2) const
private

Find all inelastic 2->2 processes for Baryon-Baryon (BB) Scattering except the more specific Nucleon-Nucleon Scattering.

Parameters
[in]included_2to2Which 2->2 reactions are enabled?
Returns
List of all possible BB reactions with their cross sections

Definition at line 1181 of file crosssections.cc.

1182  {
1183  CollisionBranchList process_list;
1184  const ParticleType& type_a = incoming_particles_[0].type();
1185  const ParticleType& type_b = incoming_particles_[1].type();
1186 
1187  bool same_sign = type_a.antiparticle_sign() == type_b.antiparticle_sign();
1188  bool any_nucleus = type_a.is_nucleus() || type_b.is_nucleus();
1189  if (!same_sign && !any_nucleus) {
1190  return process_list;
1191  }
1192  bool anti_particles = type_a.antiparticle_sign() == -1;
1193  if (type_a.is_nucleon() || type_b.is_nucleon()) {
1194  // N R → N N, N̅ R → N̅ N̅
1195  if (included_2to2[IncludedReactions::NN_to_NR] == 1) {
1196  process_list = bar_bar_to_nuc_nuc(anti_particles);
1197  }
1198  } else if (type_a.is_Delta() || type_b.is_Delta()) {
1199  // Δ R → N N, Δ̅ R → N̅ N̅
1200  if (included_2to2[IncludedReactions::NN_to_DR] == 1) {
1201  process_list = bar_bar_to_nuc_nuc(anti_particles);
1202  }
1203  }
1204 
1205  return process_list;
1206 }
CollisionBranchList bar_bar_to_nuc_nuc(const bool is_anti_particles) const
Calculate cross sections for resonance absorption (i.e.
@ NN_to_NR
@ NN_to_DR

◆ nn_xx()

CollisionBranchList smash::CrossSections::nn_xx ( const ReactionsBitSet included_2to2) const
private

Find all inelastic 2->2 processes for Nucelon-Nucelon Scattering.

Calculate cross sections for resonance production from nucleon-nucleon collisions (i.e. N N -> N R, N N -> Delta R).

Checks are processed in the following order:

  1. Charge conservation
  2. Isospin factors (Clebsch-Gordan)
  3. Enough energy for all decay channels to be available for the resonance
Parameters
[in]included_2to2Which 2->2 reactions are enabled?
Returns
List of resonance production processes possible in the collision of the two nucleons. Each element in the list contains the type(s) of the final state particle(s) and the cross section for that particular process.

Definition at line 1208 of file crosssections.cc.

1209  {
1210  CollisionBranchList process_list, channel_list;
1211 
1212  const double sqrts = sqrt_s_;
1213 
1214  /* Find whether colliding particles are nucleons or anti-nucleons;
1215  * adjust lists of produced particles. */
1216  bool both_antinucleons =
1217  (incoming_particles_[0].type().antiparticle_sign() == -1) &&
1218  (incoming_particles_[1].type().antiparticle_sign() == -1);
1219  const ParticleTypePtrList& nuc_or_anti_nuc =
1220  both_antinucleons ? ParticleType::list_anti_nucleons()
1221  : ParticleType::list_nucleons();
1222  const ParticleTypePtrList& delta_or_anti_delta =
1223  both_antinucleons ? ParticleType::list_anti_Deltas()
1224  : ParticleType::list_Deltas();
1225  // Find N N → N R channels.
1226  if (included_2to2[IncludedReactions::NN_to_NR] == 1) {
1227  channel_list = find_nn_xsection_from_type(
1228  ParticleType::list_baryon_resonances(), nuc_or_anti_nuc,
1229  [&sqrts](const ParticleType& type_res_1, const ParticleType&) {
1230  return type_res_1.iso_multiplet()->get_integral_NR(sqrts);
1231  });
1232  process_list.reserve(process_list.size() + channel_list.size());
1233  std::move(channel_list.begin(), channel_list.end(),
1234  std::inserter(process_list, process_list.end()));
1235  channel_list.clear();
1236  }
1237 
1238  // Find N N → Δ R channels.
1239  if (included_2to2[IncludedReactions::NN_to_DR] == 1) {
1240  channel_list = find_nn_xsection_from_type(
1241  ParticleType::list_baryon_resonances(), delta_or_anti_delta,
1242  [&sqrts](const ParticleType& type_res_1,
1243  const ParticleType& type_res_2) {
1244  return type_res_1.iso_multiplet()->get_integral_RR(
1245  type_res_2.iso_multiplet(), sqrts);
1246  });
1247  process_list.reserve(process_list.size() + channel_list.size());
1248  std::move(channel_list.begin(), channel_list.end(),
1249  std::inserter(process_list, process_list.end()));
1250  channel_list.clear();
1251  }
1252 
1253  // Find N N → dπ and N̅ N̅→ d̅π channels.
1254  ParticleTypePtr deuteron = ParticleType::try_find(pdg::deuteron);
1255  ParticleTypePtr antideutron = ParticleType::try_find(pdg::antideuteron);
1256  ParticleTypePtr pim = ParticleType::try_find(pdg::pi_m);
1257  ParticleTypePtr pi0 = ParticleType::try_find(pdg::pi_z);
1258  ParticleTypePtr pip = ParticleType::try_find(pdg::pi_p);
1259  // Make sure all the necessary particle types are found
1260  if (deuteron && antideutron && pim && pi0 && pip &&
1261  included_2to2[IncludedReactions::PiDeuteron_to_NN] == 1) {
1262  const ParticleTypePtrList deutron_list = {deuteron};
1263  const ParticleTypePtrList antideutron_list = {antideutron};
1264  const ParticleTypePtrList pion_list = {pim, pi0, pip};
1265  channel_list = find_nn_xsection_from_type(
1266  (both_antinucleons ? antideutron_list : deutron_list), pion_list,
1267  [&sqrts](const ParticleType& type_res_1,
1268  const ParticleType& type_res_2) {
1269  return pCM(sqrts, type_res_1.mass(), type_res_2.mass());
1270  });
1271  process_list.reserve(process_list.size() + channel_list.size());
1272  std::move(channel_list.begin(), channel_list.end(),
1273  std::inserter(process_list, process_list.end()));
1274  channel_list.clear();
1275  }
1276 
1277  return process_list;
1278 }
CollisionBranchList find_nn_xsection_from_type(const ParticleTypePtrList &type_res_1, const ParticleTypePtrList &type_res_2, const IntegrationMethod integrator) const
Utility function to avoid code replication in nn_xx().
static ParticleTypePtrList & list_anti_nucleons()
Definition: particletype.cc:71
static ParticleTypePtrList & list_anti_Deltas()
Definition: particletype.cc:77
static ParticleTypePtrList & list_baryon_resonances()
Definition: particletype.cc:81
@ PiDeuteron_to_NN
constexpr int64_t antideuteron
Anti-deuteron in decimal digits.
constexpr int64_t deuteron
Deuteron.
T pCM(const T sqrts, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:79

◆ nk_xx()

CollisionBranchList smash::CrossSections::nk_xx ( const ReactionsBitSet included_2to2,
double  KN_offset 
) const
private

Find all inelastic 2->2 background processes for Nucleon-Kaon (NK) Scattering.

Parameters
[in]included_2to2Which 2->2 reactions are enabled?
[in]KN_offsetOffset to the minimum energy for string production in KN scatterings
Returns
List of all possible NK reactions with their cross sections

Definition at line 1280 of file crosssections.cc.

1281  {
1282  const ParticleType& a = incoming_particles_[0].type();
1283  const ParticleType& b = incoming_particles_[1].type();
1284  const ParticleType& type_nucleon = a.pdgcode().is_nucleon() ? a : b;
1285  const ParticleType& type_kaon = a.pdgcode().is_nucleon() ? b : a;
1286 
1287  const auto pdg_nucleon = type_nucleon.pdgcode().code();
1288  const auto pdg_kaon = type_kaon.pdgcode().code();
1289 
1290  const double s = sqrt_s_ * sqrt_s_;
1291 
1292  // Some variable declarations for frequently used quantities
1293  const auto sigma_kplusp = kplusp_inelastic_background(s);
1294  const auto sigma_kplusn = kplusn_inelastic_background(s);
1295 
1296  /* At high energy, the parametrization we use diverges from experimental
1297  * data. This cutoff represents the point where the AQM cross section
1298  * becomes smaller than this parametrization, so we cut it here, and fully
1299  * switch to AQM beyond this point. */
1300  const double KN_to_KDelta_cutoff = KN_offset +
1301  incoming_particles_[0].pole_mass() +
1302  incoming_particles_[1].pole_mass();
1303 
1304  bool incl_KN_to_KN = included_2to2[IncludedReactions::KN_to_KN] == 1;
1305  bool incl_KN_to_KDelta =
1306  included_2to2[IncludedReactions::KN_to_KDelta] == 1 &&
1307  sqrt_s_ < KN_to_KDelta_cutoff;
1308  bool incl_Strangeness_exchange =
1309  included_2to2[IncludedReactions::Strangeness_exchange] == 1;
1310 
1311  CollisionBranchList process_list;
1312  switch (pdg_kaon) {
1313  case pdg::K_m: {
1314  /* All inelastic K- N channels here are strangeness exchange, plus one
1315  * charge exchange. */
1316  switch (pdg_nucleon) {
1317  case pdg::p: {
1318  if (incl_Strangeness_exchange) {
1319  const auto& type_pi_z = ParticleType::find(pdg::pi_z);
1320  const auto& type_pi_m = ParticleType::find(pdg::pi_m);
1321  const auto& type_pi_p = ParticleType::find(pdg::pi_p);
1322  const auto& type_Sigma_p = ParticleType::find(pdg::Sigma_p);
1323  const auto& type_Sigma_m = ParticleType::find(pdg::Sigma_m);
1324  const auto& type_Sigma_z = ParticleType::find(pdg::Sigma_z);
1325  const auto& type_Lambda = ParticleType::find(pdg::Lambda);
1326  add_channel(
1327  process_list, [&] { return kminusp_piminussigmaplus(sqrt_s_); },
1328  sqrt_s_, type_pi_m, type_Sigma_p);
1329  add_channel(
1330  process_list, [&] { return kminusp_piplussigmaminus(sqrt_s_); },
1331  sqrt_s_, type_pi_p, type_Sigma_m);
1332  add_channel(
1333  process_list, [&] { return kminusp_pi0sigma0(sqrt_s_); },
1334  sqrt_s_, type_pi_z, type_Sigma_z);
1335  add_channel(
1336  process_list, [&] { return kminusp_pi0lambda(sqrt_s_); },
1337  sqrt_s_, type_pi_z, type_Lambda);
1338  }
1339  if (incl_KN_to_KN) {
1340  const auto& type_n = ParticleType::find(pdg::n);
1341  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
1342  add_channel(
1343  process_list, [&] { return kminusp_kbar0n(s); }, sqrt_s_,
1344  type_Kbar_z, type_n);
1345  }
1346  break;
1347  }
1348  case pdg::n: {
1349  if (incl_Strangeness_exchange) {
1350  const auto& type_pi_z = ParticleType::find(pdg::pi_z);
1351  const auto& type_pi_m = ParticleType::find(pdg::pi_m);
1352  const auto& type_Sigma_m = ParticleType::find(pdg::Sigma_m);
1353  const auto& type_Sigma_z = ParticleType::find(pdg::Sigma_z);
1354  const auto& type_Lambda = ParticleType::find(pdg::Lambda);
1355  add_channel(
1356  process_list, [&] { return kminusn_piminussigma0(sqrt_s_); },
1357  sqrt_s_, type_pi_m, type_Sigma_z);
1358  add_channel(
1359  process_list, [&] { return kminusn_piminussigma0(sqrt_s_); },
1360  sqrt_s_, type_pi_z, type_Sigma_m);
1361  add_channel(
1362  process_list, [&] { return kminusn_piminuslambda(sqrt_s_); },
1363  sqrt_s_, type_pi_m, type_Lambda);
1364  }
1365  break;
1366  }
1367  case -pdg::p: {
1368  if (incl_KN_to_KDelta) {
1369  const auto& type_K_m = ParticleType::find(pdg::K_m);
1370  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
1371  const auto& type_Delta_pp_bar = ParticleType::find(-pdg::Delta_pp);
1372  const auto& type_Delta_p_bar = ParticleType::find(-pdg::Delta_p);
1373  add_channel(
1374  process_list,
1375  [&] {
1376  return sigma_kplusp * kaon_nucleon_ratios.get_ratio(
1377  type_nucleon, type_kaon,
1378  type_Kbar_z, type_Delta_pp_bar);
1379  },
1380  sqrt_s_, type_Kbar_z, type_Delta_pp_bar);
1381  add_channel(
1382  process_list,
1383  [&] {
1384  return sigma_kplusp * kaon_nucleon_ratios.get_ratio(
1385  type_nucleon, type_kaon, type_K_m,
1386  type_Delta_p_bar);
1387  },
1388  sqrt_s_, type_K_m, type_Delta_p_bar);
1389  }
1390  break;
1391  }
1392  case -pdg::n: {
1393  if (incl_KN_to_KDelta) {
1394  const auto& type_K_m = ParticleType::find(pdg::K_m);
1395  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
1396  const auto& type_Delta_p_bar = ParticleType::find(-pdg::Delta_p);
1397  const auto& type_Delta_z_bar = ParticleType::find(-pdg::Delta_z);
1398  add_channel(
1399  process_list,
1400  [&] {
1401  return sigma_kplusn * kaon_nucleon_ratios.get_ratio(
1402  type_nucleon, type_kaon,
1403  type_Kbar_z, type_Delta_p_bar);
1404  },
1405  sqrt_s_, type_Kbar_z, type_Delta_p_bar);
1406  add_channel(
1407  process_list,
1408  [&] {
1409  return sigma_kplusn * kaon_nucleon_ratios.get_ratio(
1410  type_nucleon, type_kaon, type_K_m,
1411  type_Delta_z_bar);
1412  },
1413  sqrt_s_, type_K_m, type_Delta_z_bar);
1414  }
1415  if (incl_KN_to_KN) {
1416  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
1417  const auto& type_p_bar = ParticleType::find(-pdg::p);
1418  add_channel(
1419  process_list, [&] { return kplusn_k0p(s); }, sqrt_s_,
1420  type_Kbar_z, type_p_bar);
1421  }
1422  break;
1423  }
1424  }
1425  break;
1426  }
1427  case pdg::K_p: {
1428  /* All inelastic channels are K+ N -> K Delta -> K pi N, with identical
1429  * cross section, weighted by the isospin factor. */
1430  switch (pdg_nucleon) {
1431  case pdg::p: {
1432  if (incl_KN_to_KDelta) {
1433  const auto& type_K_p = ParticleType::find(pdg::K_p);
1434  const auto& type_K_z = ParticleType::find(pdg::K_z);
1435  const auto& type_Delta_pp = ParticleType::find(pdg::Delta_pp);
1436  const auto& type_Delta_p = ParticleType::find(pdg::Delta_p);
1437  add_channel(
1438  process_list,
1439  [&] {
1440  return sigma_kplusp *
1441  kaon_nucleon_ratios.get_ratio(type_nucleon, type_kaon,
1442  type_K_z, type_Delta_pp);
1443  },
1444  sqrt_s_, type_K_z, type_Delta_pp);
1445  add_channel(
1446  process_list,
1447  [&] {
1448  return sigma_kplusp *
1449  kaon_nucleon_ratios.get_ratio(type_nucleon, type_kaon,
1450  type_K_p, type_Delta_p);
1451  },
1452  sqrt_s_, type_K_p, type_Delta_p);
1453  }
1454  break;
1455  }
1456  case pdg::n: {
1457  if (incl_KN_to_KDelta) {
1458  const auto& type_K_p = ParticleType::find(pdg::K_p);
1459  const auto& type_K_z = ParticleType::find(pdg::K_z);
1460  const auto& type_Delta_p = ParticleType::find(pdg::Delta_p);
1461  const auto& type_Delta_z = ParticleType::find(pdg::Delta_z);
1462  add_channel(
1463  process_list,
1464  [&] {
1465  return sigma_kplusn *
1466  kaon_nucleon_ratios.get_ratio(type_nucleon, type_kaon,
1467  type_K_z, type_Delta_p);
1468  },
1469  sqrt_s_, type_K_z, type_Delta_p);
1470  add_channel(
1471  process_list,
1472  [&] {
1473  return sigma_kplusn *
1474  kaon_nucleon_ratios.get_ratio(type_nucleon, type_kaon,
1475  type_K_p, type_Delta_z);
1476  },
1477  sqrt_s_, type_K_p, type_Delta_z);
1478  }
1479  if (incl_KN_to_KN) {
1480  const auto& type_K_z = ParticleType::find(pdg::K_z);
1481  const auto& type_p = ParticleType::find(pdg::p);
1482  add_channel(
1483  process_list, [&] { return kplusn_k0p(s); }, sqrt_s_, type_K_z,
1484  type_p);
1485  }
1486  break;
1487  }
1488  case -pdg::p: {
1489  if (incl_Strangeness_exchange) {
1490  const auto& type_pi_z = ParticleType::find(pdg::pi_z);
1491  const auto& type_pi_m = ParticleType::find(pdg::pi_m);
1492  const auto& type_pi_p = ParticleType::find(pdg::pi_p);
1493  const auto& type_Sigma_p_bar = ParticleType::find(-pdg::Sigma_p);
1494  const auto& type_Sigma_m_bar = ParticleType::find(-pdg::Sigma_m);
1495  const auto& type_Sigma_z_bar = ParticleType::find(-pdg::Sigma_z);
1496  const auto& type_Lambda_bar = ParticleType::find(-pdg::Lambda);
1497  add_channel(
1498  process_list, [&] { return kminusp_piminussigmaplus(sqrt_s_); },
1499  sqrt_s_, type_pi_p, type_Sigma_p_bar);
1500  add_channel(
1501  process_list, [&] { return kminusp_piplussigmaminus(sqrt_s_); },
1502  sqrt_s_, type_pi_m, type_Sigma_m_bar);
1503  add_channel(
1504  process_list, [&] { return kminusp_pi0sigma0(sqrt_s_); },
1505  sqrt_s_, type_pi_z, type_Sigma_z_bar);
1506  add_channel(
1507  process_list, [&] { return kminusp_pi0lambda(sqrt_s_); },
1508  sqrt_s_, type_pi_z, type_Lambda_bar);
1509  }
1510  if (incl_KN_to_KN) {
1511  const auto& type_n_bar = ParticleType::find(-pdg::n);
1512  const auto& type_K_z = ParticleType::find(pdg::K_z);
1513  add_channel(
1514  process_list, [&] { return kminusp_kbar0n(s); }, sqrt_s_,
1515  type_K_z, type_n_bar);
1516  }
1517  break;
1518  }
1519  case -pdg::n: {
1520  if (incl_Strangeness_exchange) {
1521  const auto& type_pi_z = ParticleType::find(pdg::pi_z);
1522  const auto& type_pi_p = ParticleType::find(pdg::pi_p);
1523  const auto& type_Sigma_m_bar = ParticleType::find(-pdg::Sigma_m);
1524  const auto& type_Sigma_z_bar = ParticleType::find(-pdg::Sigma_z);
1525  const auto& type_Lambda_bar = ParticleType::find(-pdg::Lambda);
1526  add_channel(
1527  process_list, [&] { return kminusn_piminussigma0(sqrt_s_); },
1528  sqrt_s_, type_pi_p, type_Sigma_z_bar);
1529  add_channel(
1530  process_list, [&] { return kminusn_piminussigma0(sqrt_s_); },
1531  sqrt_s_, type_pi_z, type_Sigma_m_bar);
1532  add_channel(
1533  process_list, [&] { return kminusn_piminuslambda(sqrt_s_); },
1534  sqrt_s_, type_pi_p, type_Lambda_bar);
1535  }
1536  break;
1537  }
1538  }
1539  break;
1540  }
1541  case pdg::K_z: {
1542  // K+ and K0 have the same mass and spin, so their cross sections are
1543  // assumed to only differ in isospin factors. For the initial state, we
1544  // assume that K0 p is equivalent to K+ n and K0 n equivalent to K+ p,
1545  // like for the elastic background.
1546 
1547  switch (pdg_nucleon) {
1548  case pdg::p: {
1549  if (incl_KN_to_KDelta) {
1550  const auto& type_K_p = ParticleType::find(pdg::K_p);
1551  const auto& type_K_z = ParticleType::find(pdg::K_z);
1552  const auto& type_Delta_p = ParticleType::find(pdg::Delta_p);
1553  const auto& type_Delta_z = ParticleType::find(pdg::Delta_z);
1554  add_channel(
1555  process_list,
1556  [&] {
1557  return sigma_kplusn *
1558  kaon_nucleon_ratios.get_ratio(type_nucleon, type_kaon,
1559  type_K_z, type_Delta_p);
1560  },
1561  sqrt_s_, type_K_z, type_Delta_p);
1562  add_channel(
1563  process_list,
1564  [&] {
1565  return sigma_kplusn *
1566  kaon_nucleon_ratios.get_ratio(type_nucleon, type_kaon,
1567  type_K_p, type_Delta_z);
1568  },
1569  sqrt_s_, type_K_p, type_Delta_z);
1570  }
1571  if (incl_KN_to_KN) {
1572  const auto& type_K_p = ParticleType::find(pdg::K_p);
1573  const auto& type_n = ParticleType::find(pdg::n);
1574  add_channel(
1575  process_list,
1576  [&] {
1577  // The isospin factor is 1, see the parametrizations
1578  // tests.
1579  return kplusn_k0p(s);
1580  },
1581  sqrt_s_, type_K_p, type_n);
1582  }
1583  break;
1584  }
1585  case pdg::n: {
1586  if (incl_KN_to_KDelta) {
1587  const auto& type_K_p = ParticleType::find(pdg::K_p);
1588  const auto& type_K_z = ParticleType::find(pdg::K_z);
1589  const auto& type_Delta_z = ParticleType::find(pdg::Delta_z);
1590  const auto& type_Delta_m = ParticleType::find(pdg::Delta_m);
1591  add_channel(
1592  process_list,
1593  [&] {
1594  return sigma_kplusp *
1595  kaon_nucleon_ratios.get_ratio(type_nucleon, type_kaon,
1596  type_K_z, type_Delta_z);
1597  },
1598  sqrt_s_, type_K_z, type_Delta_z);
1599  add_channel(
1600  process_list,
1601  [&] {
1602  return sigma_kplusp *
1603  kaon_nucleon_ratios.get_ratio(type_nucleon, type_kaon,
1604  type_K_p, type_Delta_m);
1605  },
1606  sqrt_s_, type_K_p, type_Delta_m);
1607  }
1608  break;
1609  }
1610  case -pdg::p: {
1611  if (incl_Strangeness_exchange) {
1612  const auto& type_pi_z = ParticleType::find(pdg::pi_z);
1613  const auto& type_pi_m = ParticleType::find(pdg::pi_m);
1614  const auto& type_Sigma_p_bar = ParticleType::find(-pdg::Sigma_p);
1615  const auto& type_Sigma_z_bar = ParticleType::find(-pdg::Sigma_z);
1616  const auto& type_Lambda_bar = ParticleType::find(-pdg::Lambda);
1617  add_channel(
1618  process_list, [&] { return kminusn_piminussigma0(sqrt_s_); },
1619  sqrt_s_, type_pi_m, type_Sigma_z_bar);
1620  add_channel(
1621  process_list, [&] { return kminusn_piminussigma0(sqrt_s_); },
1622  sqrt_s_, type_pi_z, type_Sigma_p_bar);
1623  add_channel(
1624  process_list, [&] { return kminusn_piminuslambda(sqrt_s_); },
1625  sqrt_s_, type_pi_m, type_Lambda_bar);
1626  }
1627  break;
1628  }
1629  case -pdg::n: {
1630  if (incl_Strangeness_exchange) {
1631  const auto& type_pi_z = ParticleType::find(pdg::pi_z);
1632  const auto& type_pi_m = ParticleType::find(pdg::pi_m);
1633  const auto& type_pi_p = ParticleType::find(pdg::pi_p);
1634  const auto& type_Sigma_p_bar = ParticleType::find(-pdg::Sigma_p);
1635  const auto& type_Sigma_m_bar = ParticleType::find(-pdg::Sigma_m);
1636  const auto& type_Sigma_z_bar = ParticleType::find(-pdg::Sigma_z);
1637  const auto& type_Lambda_bar = ParticleType::find(-pdg::Lambda);
1638  add_channel(
1639  process_list, [&] { return kminusp_piminussigmaplus(sqrt_s_); },
1640  sqrt_s_, type_pi_m, type_Sigma_m_bar);
1641  add_channel(
1642  process_list, [&] { return kminusp_piplussigmaminus(sqrt_s_); },
1643  sqrt_s_, type_pi_p, type_Sigma_p_bar);
1644  add_channel(
1645  process_list, [&] { return kminusp_pi0sigma0(sqrt_s_); },
1646  sqrt_s_, type_pi_z, type_Sigma_z_bar);
1647  add_channel(
1648  process_list, [&] { return kminusp_pi0lambda(sqrt_s_); },
1649  sqrt_s_, type_pi_z, type_Lambda_bar);
1650  }
1651  if (incl_KN_to_KN) {
1652  const auto& type_K_p = ParticleType::find(pdg::K_p);
1653  const auto& type_p_bar = ParticleType::find(-pdg::p);
1654  add_channel(
1655  process_list, [&] { return kminusp_kbar0n(s); }, sqrt_s_,
1656  type_K_p, type_p_bar);
1657  }
1658  break;
1659  }
1660  }
1661  break;
1662  }
1663  case pdg::Kbar_z:
1664  switch (pdg_nucleon) {
1665  case pdg::p: {
1666  if (incl_Strangeness_exchange) {
1667  const auto& type_pi_z = ParticleType::find(pdg::pi_z);
1668  const auto& type_pi_p = ParticleType::find(pdg::pi_p);
1669  const auto& type_Sigma_p = ParticleType::find(pdg::Sigma_p);
1670  const auto& type_Sigma_z = ParticleType::find(pdg::Sigma_z);
1671  const auto& type_Lambda = ParticleType::find(pdg::Lambda);
1672  add_channel(
1673  process_list, [&] { return kminusn_piminussigma0(sqrt_s_); },
1674  sqrt_s_, type_pi_z, type_Sigma_p);
1675  add_channel(
1676  process_list, [&] { return kminusn_piminussigma0(sqrt_s_); },
1677  sqrt_s_, type_pi_p, type_Sigma_z);
1678  add_channel(
1679  process_list, [&] { return kminusn_piminuslambda(sqrt_s_); },
1680  sqrt_s_, type_pi_p, type_Lambda);
1681  }
1682  break;
1683  }
1684  case pdg::n: {
1685  if (incl_Strangeness_exchange) {
1686  const auto& type_pi_z = ParticleType::find(pdg::pi_z);
1687  const auto& type_pi_m = ParticleType::find(pdg::pi_m);
1688  const auto& type_pi_p = ParticleType::find(pdg::pi_p);
1689  const auto& type_Sigma_p = ParticleType::find(pdg::Sigma_p);
1690  const auto& type_Sigma_m = ParticleType::find(pdg::Sigma_m);
1691  const auto& type_Sigma_z = ParticleType::find(pdg::Sigma_z);
1692  const auto& type_Lambda = ParticleType::find(pdg::Lambda);
1693  add_channel(
1694  process_list, [&] { return kminusp_piminussigmaplus(sqrt_s_); },
1695  sqrt_s_, type_pi_p, type_Sigma_m);
1696  add_channel(
1697  process_list, [&] { return kminusp_piplussigmaminus(sqrt_s_); },
1698  sqrt_s_, type_pi_m, type_Sigma_p);
1699  add_channel(
1700  process_list, [&] { return kminusp_pi0sigma0(sqrt_s_); },
1701  sqrt_s_, type_pi_z, type_Sigma_z);
1702  add_channel(
1703  process_list, [&] { return kminusp_pi0lambda(sqrt_s_); },
1704  sqrt_s_, type_pi_z, type_Lambda);
1705  }
1706  if (incl_KN_to_KN) {
1707  const auto& type_p = ParticleType::find(pdg::p);
1708  const auto& type_K_m = ParticleType::find(pdg::K_m);
1709  add_channel(
1710  process_list, [&] { return kminusp_kbar0n(s); }, sqrt_s_,
1711  type_K_m, type_p);
1712  }
1713  break;
1714  }
1715  case -pdg::p: {
1716  if (incl_KN_to_KDelta) {
1717  const auto& type_K_m = ParticleType::find(pdg::K_m);
1718  const auto& type_Kbar_z = type_kaon;
1719  const auto& type_Delta_bar_m = ParticleType::find(-pdg::Delta_p);
1720  const auto& type_Delta_bar_z = ParticleType::find(-pdg::Delta_z);
1721  add_channel(
1722  process_list,
1723  [&] {
1724  return sigma_kplusn * kaon_nucleon_ratios.get_ratio(
1725  type_nucleon, type_kaon,
1726  type_Kbar_z, type_Delta_bar_m);
1727  },
1728  sqrt_s_, type_Kbar_z, type_Delta_bar_m);
1729  add_channel(
1730  process_list,
1731  [&] {
1732  return sigma_kplusn * kaon_nucleon_ratios.get_ratio(
1733  type_nucleon, type_kaon, type_K_m,
1734  type_Delta_bar_z);
1735  },
1736  sqrt_s_, type_K_m, type_Delta_bar_z);
1737  }
1738  if (incl_KN_to_KN) {
1739  const auto& type_K_m = ParticleType::find(pdg::K_m);
1740  const auto& type_n_bar = ParticleType::find(-pdg::n);
1741  add_channel(
1742  process_list,
1743  [&] {
1744  // The isospin factor is 1, see the parametrizations
1745  // tests.
1746  return kplusn_k0p(s);
1747  },
1748  sqrt_s_, type_K_m, type_n_bar);
1749  }
1750  break;
1751  }
1752  case -pdg::n: {
1753  if (incl_KN_to_KDelta) {
1754  const auto& type_K_m = ParticleType::find(pdg::K_m);
1755  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
1756  const auto& type_Delta_z_bar = ParticleType::find(-pdg::Delta_z);
1757  const auto& type_Delta_m_bar = ParticleType::find(-pdg::Delta_m);
1758  add_channel(
1759  process_list,
1760  [&] {
1761  return sigma_kplusp * kaon_nucleon_ratios.get_ratio(
1762  type_nucleon, type_kaon,
1763  type_Kbar_z, type_Delta_z_bar);
1764  },
1765  sqrt_s_, type_Kbar_z, type_Delta_z_bar);
1766  add_channel(
1767  process_list,
1768  [&] {
1769  return sigma_kplusp * kaon_nucleon_ratios.get_ratio(
1770  type_nucleon, type_kaon, type_K_m,
1771  type_Delta_m_bar);
1772  },
1773  sqrt_s_, type_K_m, type_Delta_m_bar);
1774  }
1775  break;
1776  }
1777  }
1778  break;
1779  }
1780 
1781  return process_list;
1782 }
double get_ratio(const ParticleType &a, const ParticleType &b, const ParticleType &c, const ParticleType &d) const
Return the isospin ratio of the given K N -> K Delta cross section.
@ KN_to_KDelta
@ KN_to_KN
@ Strangeness_exchange
constexpr int Delta_p
Δ⁺.
constexpr int Delta_pp
Δ⁺⁺.
constexpr int Delta_m
Δ⁻.
constexpr int Delta_z
Δ⁰.
double kplusn_k0p(double mandelstam_s)
K+ n charge exchange cross section parametrization.
double kminusp_pi0lambda(double sqrts)
K- p <-> pi0 Lambda cross section parametrization Fit to Landolt-Börnstein instead of UrQMD values.
double kminusn_piminussigma0(double sqrts)
K- n <-> pi- Sigma0 cross section parametrization Follow from the parametrization with the same stran...
KaonNucleonRatios kaon_nucleon_ratios
double kminusn_piminuslambda(double sqrts)
K- n <-> pi- Lambda cross section parametrization Follow from the parametrization with the same stran...
double kminusp_piminussigmaplus(double sqrts)
K- p <-> pi- Sigma+ cross section parametrization Taken from UrQMD (Graef:2014mra ).
double kplusp_inelastic_background(double mandelstam_s)
K+ p inelastic background cross section parametrization Source: Buss:2011mx , B.3....
double kminusp_pi0sigma0(double sqrts)
K- p <-> pi0 Sigma0 cross section parametrization Fit to Landolt-Börnstein instead of UrQMD values.
double kminusp_piplussigmaminus(double sqrts)
K- p <-> pi+ Sigma- cross section parametrization Taken from UrQMD (Graef:2014mra ).
double kminusp_kbar0n(double mandelstam_s)
K- p <-> Kbar0 n cross section parametrization.
double kplusn_inelastic_background(double mandelstam_s)
K+ n inelastic background cross section parametrization Source: Buss:2011mx , B.3....

◆ deltak_xx()

CollisionBranchList smash::CrossSections::deltak_xx ( const ReactionsBitSet included_2to2) const
private

Find all inelastic 2->2 processes for Delta-Kaon (DeltaK) Scattering.

Parameters
[in]included_2to2Which 2->2 reactions are enabled?
Returns
List of all possible DeltaK reactions with their cross sections

Definition at line 1784 of file crosssections.cc.

1785  {
1786  CollisionBranchList process_list;
1787  if (included_2to2[IncludedReactions::KN_to_KDelta] == 0) {
1788  return process_list;
1789  }
1790  const ParticleType& a = incoming_particles_[0].type();
1791  const ParticleType& b = incoming_particles_[1].type();
1792  const ParticleType& type_delta = a.pdgcode().is_Delta() ? a : b;
1793  const ParticleType& type_kaon = a.pdgcode().is_Delta() ? b : a;
1794 
1795  const auto pdg_delta = type_delta.pdgcode().code();
1796  const auto pdg_kaon = type_kaon.pdgcode().code();
1797 
1798  const double s = sqrt_s_ * sqrt_s_;
1799  const double pcm = cm_momentum();
1800  /* The cross sections are determined from the backward reactions via
1801  * detailed balance. The same isospin factors as for the backward reaction
1802  * are used. */
1803  switch (pack(pdg_delta, pdg_kaon)) {
1804  case pack(pdg::Delta_pp, pdg::K_z):
1805  case pack(pdg::Delta_p, pdg::K_p): {
1806  const auto& type_p = ParticleType::find(pdg::p);
1807  const auto& type_K_p = ParticleType::find(pdg::K_p);
1808  add_channel(
1809  process_list,
1810  [&] {
1811  return detailed_balance_factor_RK(sqrt_s_, pcm, type_delta,
1812  type_kaon, type_p, type_K_p) *
1813  kaon_nucleon_ratios.get_ratio(type_p, type_K_p, type_kaon,
1814  type_delta) *
1816  },
1817  sqrt_s_, type_p, type_K_p);
1818  break;
1819  }
1820  case pack(-pdg::Delta_pp, pdg::Kbar_z):
1821  case pack(-pdg::Delta_p, pdg::K_m): {
1822  const auto& type_p_bar = ParticleType::find(-pdg::p);
1823  const auto& type_K_m = ParticleType::find(pdg::K_m);
1824  add_channel(
1825  process_list,
1826  [&] {
1827  return detailed_balance_factor_RK(sqrt_s_, pcm, type_delta,
1828  type_kaon, type_p_bar, type_K_m) *
1829  kaon_nucleon_ratios.get_ratio(type_p_bar, type_K_m,
1830  type_kaon, type_delta) *
1832  },
1833  sqrt_s_, type_p_bar, type_K_m);
1834  break;
1835  }
1836  case pack(pdg::Delta_p, pdg::K_z):
1837  case pack(pdg::Delta_z, pdg::K_p): {
1838  const auto& type_n = ParticleType::find(pdg::n);
1839  const auto& type_p = ParticleType::find(pdg::p);
1840  const auto& type_K_p = ParticleType::find(pdg::K_p);
1841  const auto& type_K_z = ParticleType::find(pdg::K_z);
1842  add_channel(
1843  process_list,
1844  [&] {
1845  return detailed_balance_factor_RK(sqrt_s_, pcm, type_delta,
1846  type_kaon, type_n, type_K_p) *
1847  kaon_nucleon_ratios.get_ratio(type_n, type_K_p, type_kaon,
1848  type_delta) *
1850  },
1851  sqrt_s_, type_n, type_K_p);
1852 
1853  add_channel(
1854  process_list,
1855  [&] {
1856  return detailed_balance_factor_RK(sqrt_s_, pcm, type_delta,
1857  type_kaon, type_p, type_K_z) *
1858  kaon_nucleon_ratios.get_ratio(type_p, type_K_z, type_kaon,
1859  type_delta) *
1861  },
1862  sqrt_s_, type_p, type_K_z);
1863  break;
1864  }
1865  case pack(-pdg::Delta_p, pdg::Kbar_z):
1866  case pack(-pdg::Delta_z, pdg::K_m): {
1867  const auto& type_n_bar = ParticleType::find(-pdg::n);
1868  const auto& type_p_bar = ParticleType::find(-pdg::p);
1869  const auto& type_K_m = ParticleType::find(pdg::K_m);
1870  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
1871  add_channel(
1872  process_list,
1873  [&] {
1874  return detailed_balance_factor_RK(sqrt_s_, pcm, type_delta,
1875  type_kaon, type_n_bar, type_K_m) *
1876  kaon_nucleon_ratios.get_ratio(type_n_bar, type_K_m,
1877  type_kaon, type_delta) *
1879  },
1880  sqrt_s_, type_n_bar, type_K_m);
1881 
1882  add_channel(
1883  process_list,
1884  [&] {
1885  return detailed_balance_factor_RK(sqrt_s_, pcm, type_delta,
1886  type_kaon, type_p_bar,
1887  type_Kbar_z) *
1888  kaon_nucleon_ratios.get_ratio(type_p_bar, type_Kbar_z,
1889  type_kaon, type_delta) *
1891  },
1892  sqrt_s_, type_p_bar, type_Kbar_z);
1893  break;
1894  }
1895  case pack(pdg::Delta_z, pdg::K_z):
1896  case pack(pdg::Delta_m, pdg::K_p): {
1897  const auto& type_n = ParticleType::find(pdg::n);
1898  const auto& type_K_z = ParticleType::find(pdg::K_z);
1899  add_channel(
1900  process_list,
1901  [&] {
1902  return detailed_balance_factor_RK(sqrt_s_, pcm, type_delta,
1903  type_kaon, type_n, type_K_z) *
1904  kaon_nucleon_ratios.get_ratio(type_n, type_K_z, type_kaon,
1905  type_delta) *
1907  },
1908  sqrt_s_, type_n, type_K_z);
1909  break;
1910  }
1911  case pack(-pdg::Delta_z, pdg::Kbar_z):
1912  case pack(-pdg::Delta_m, pdg::K_m): {
1913  const auto& type_n_bar = ParticleType::find(-pdg::n);
1914  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
1915  add_channel(
1916  process_list,
1917  [&] {
1918  return detailed_balance_factor_RK(sqrt_s_, pcm, type_delta,
1919  type_kaon, type_n_bar,
1920  type_Kbar_z) *
1921  kaon_nucleon_ratios.get_ratio(type_n_bar, type_Kbar_z,
1922  type_kaon, type_delta) *
1924  },
1925  sqrt_s_, type_n_bar, type_Kbar_z);
1926  break;
1927  }
1928  default:
1929  break;
1930  }
1931 
1932  return process_list;
1933 }
constexpr uint64_t pack(int32_t x, int32_t y)
Pack two int32_t into an uint64_t.
static double detailed_balance_factor_RK(double sqrts, double pcm, const ParticleType &a, const ParticleType &b, const ParticleType &c, const ParticleType &d)
Helper function: Calculate the detailed balance factor R such that.

◆ ypi_xx()

CollisionBranchList smash::CrossSections::ypi_xx ( const ReactionsBitSet included_2to2) const
private

Find all inelastic 2->2 processes for Hyperon-Pion (Ypi) Scattering.

Parameters
[in]included_2to2Which 2->2 reactions are enabled?
Returns
List of all possible Ypi reactions with their cross sections

Definition at line 1935 of file crosssections.cc.

1936  {
1937  CollisionBranchList process_list;
1938  if (included_2to2[IncludedReactions::Strangeness_exchange] == 0) {
1939  return process_list;
1940  }
1941  const ParticleType& a = incoming_particles_[0].type();
1942  const ParticleType& b = incoming_particles_[1].type();
1943  const ParticleType& type_hyperon = a.pdgcode().is_hyperon() ? a : b;
1944  const ParticleType& type_pion = a.pdgcode().is_hyperon() ? b : a;
1945 
1946  const auto pdg_hyperon = type_hyperon.pdgcode().code();
1947  const auto pdg_pion = type_pion.pdgcode().code();
1948 
1949  const double s = sqrt_s_ * sqrt_s_;
1950 
1951  switch (pack(pdg_hyperon, pdg_pion)) {
1952  case pack(pdg::Sigma_z, pdg::pi_m): {
1953  const auto& type_n = ParticleType::find(pdg::n);
1954  const auto& type_K_m = ParticleType::find(pdg::K_m);
1955  add_channel(
1956  process_list,
1957  [&] {
1958  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
1959  type_n, type_K_m) *
1961  },
1962  sqrt_s_, type_n, type_K_m);
1963  break;
1964  }
1965  case pack(pdg::Sigma_z, pdg::pi_p): {
1966  const auto& type_p = ParticleType::find(pdg::p);
1967  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
1968  add_channel(
1969  process_list,
1970  [&] {
1971  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
1972  type_p, type_Kbar_z) *
1974  },
1975  sqrt_s_, type_p, type_Kbar_z);
1976  break;
1977  }
1978  case pack(-pdg::Sigma_z, pdg::pi_p): {
1979  const auto& type_n_bar = ParticleType::find(-pdg::n);
1980  const auto& type_K_p = ParticleType::find(pdg::K_p);
1981  add_channel(
1982  process_list,
1983  [&] {
1984  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
1985  type_n_bar, type_K_p) *
1987  },
1988  sqrt_s_, type_n_bar, type_K_p);
1989  break;
1990  }
1991  case pack(-pdg::Sigma_z, pdg::pi_m): {
1992  const auto& type_p_bar = ParticleType::find(-pdg::p);
1993  const auto& type_K_z = ParticleType::find(pdg::K_z);
1994  add_channel(
1995  process_list,
1996  [&] {
1997  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
1998  type_p_bar, type_K_z) *
2000  },
2001  sqrt_s_, type_p_bar, type_K_z);
2002  break;
2003  }
2004  case pack(pdg::Sigma_m, pdg::pi_z): {
2005  const auto& type_n = ParticleType::find(pdg::n);
2006  const auto& type_K_m = ParticleType::find(pdg::K_m);
2007  add_channel(
2008  process_list,
2009  [&] {
2010  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2011  type_n, type_K_m) *
2013  },
2014  sqrt_s_, type_n, type_K_m);
2015  break;
2016  }
2017  case pack(pdg::Sigma_p, pdg::pi_z): {
2018  const auto& type_p = ParticleType::find(pdg::p);
2019  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
2020  add_channel(
2021  process_list,
2022  [&] {
2023  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2024  type_p, type_Kbar_z) *
2026  },
2027  sqrt_s_, type_p, type_Kbar_z);
2028  break;
2029  }
2030  case pack(-pdg::Sigma_m, pdg::pi_z): {
2031  const auto& type_n_bar = ParticleType::find(-pdg::n);
2032  const auto& type_K_p = ParticleType::find(pdg::K_p);
2033  add_channel(
2034  process_list,
2035  [&] {
2036  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2037  type_n_bar, type_K_p) *
2039  },
2040  sqrt_s_, type_n_bar, type_K_p);
2041  break;
2042  }
2043  case pack(-pdg::Sigma_p, pdg::pi_z): {
2044  const auto& type_p_bar = ParticleType::find(-pdg::p);
2045  const auto& type_K_z = ParticleType::find(pdg::K_z);
2046  add_channel(
2047  process_list,
2048  [&] {
2049  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2050  type_p_bar, type_K_z) *
2052  },
2053  sqrt_s_, type_p_bar, type_K_z);
2054  break;
2055  }
2056  case pack(pdg::Lambda, pdg::pi_m): {
2057  const auto& type_n = ParticleType::find(pdg::n);
2058  const auto& type_K_m = ParticleType::find(pdg::K_m);
2059  add_channel(
2060  process_list,
2061  [&] {
2062  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2063  type_n, type_K_m) *
2065  },
2066  sqrt_s_, type_n, type_K_m);
2067  break;
2068  }
2069  case pack(pdg::Lambda, pdg::pi_p): {
2070  const auto& type_p = ParticleType::find(pdg::p);
2071  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
2072  add_channel(
2073  process_list,
2074  [&] {
2075  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2076  type_p, type_Kbar_z) *
2078  },
2079  sqrt_s_, type_p, type_Kbar_z);
2080  break;
2081  }
2082  case pack(-pdg::Lambda, pdg::pi_p): {
2083  const auto& type_n_bar = ParticleType::find(-pdg::n);
2084  const auto& type_K_p = ParticleType::find(pdg::K_p);
2085  add_channel(
2086  process_list,
2087  [&] {
2088  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2089  type_n_bar, type_K_p) *
2091  },
2092  sqrt_s_, type_n_bar, type_K_p);
2093  break;
2094  }
2095  case pack(-pdg::Lambda, pdg::pi_m): {
2096  const auto& type_p_bar = ParticleType::find(-pdg::p);
2097  const auto& type_K_z = ParticleType::find(pdg::K_z);
2098  add_channel(
2099  process_list,
2100  [&] {
2101  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2102  type_p_bar, type_K_z) *
2104  },
2105  sqrt_s_, type_p_bar, type_K_z);
2106  break;
2107  }
2108  case pack(pdg::Sigma_z, pdg::pi_z): {
2109  const auto& type_p = ParticleType::find(pdg::p);
2110  const auto& type_n = ParticleType::find(pdg::n);
2111  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
2112  const auto& type_K_m = ParticleType::find(pdg::K_m);
2113  add_channel(
2114  process_list,
2115  [&] {
2116  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2117  type_p, type_K_m) *
2119  },
2120  sqrt_s_, type_p, type_K_m);
2121  add_channel(
2122  process_list,
2123  [&] {
2124  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2125  type_n, type_Kbar_z) *
2127  },
2128  sqrt_s_, type_n, type_Kbar_z);
2129  break;
2130  }
2131  case pack(-pdg::Sigma_z, pdg::pi_z): {
2132  const auto& type_p_bar = ParticleType::find(-pdg::p);
2133  const auto& type_n_bar = ParticleType::find(-pdg::n);
2134  const auto& type_K_z = ParticleType::find(pdg::K_z);
2135  const auto& type_K_p = ParticleType::find(pdg::K_p);
2136  add_channel(
2137  process_list,
2138  [&] {
2139  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2140  type_p_bar, type_K_p) *
2142  },
2143  sqrt_s_, type_p_bar, type_K_p);
2144  add_channel(
2145  process_list,
2146  [&] {
2147  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2148  type_n_bar, type_K_z) *
2150  },
2151  sqrt_s_, type_n_bar, type_K_z);
2152  break;
2153  }
2154  case pack(pdg::Sigma_m, pdg::pi_p): {
2155  const auto& type_p = ParticleType::find(pdg::p);
2156  const auto& type_n = ParticleType::find(pdg::n);
2157  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
2158  const auto& type_K_m = ParticleType::find(pdg::K_m);
2159  add_channel(
2160  process_list,
2161  [&] {
2162  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2163  type_p, type_K_m) *
2165  },
2166  sqrt_s_, type_p, type_K_m);
2167  add_channel(
2168  process_list,
2169  [&] {
2170  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2171  type_n, type_Kbar_z) *
2173  },
2174  sqrt_s_, type_n, type_Kbar_z);
2175  break;
2176  }
2177  case pack(-pdg::Sigma_m, pdg::pi_m): {
2178  const auto& type_p_bar = ParticleType::find(-pdg::p);
2179  const auto& type_n_bar = ParticleType::find(-pdg::n);
2180  const auto& type_K_z = ParticleType::find(pdg::K_z);
2181  const auto& type_K_p = ParticleType::find(pdg::K_p);
2182  add_channel(
2183  process_list,
2184  [&] {
2185  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2186  type_p_bar, type_K_p) *
2188  },
2189  sqrt_s_, type_p_bar, type_K_p);
2190  add_channel(
2191  process_list,
2192  [&] {
2193  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2194  type_n_bar, type_K_z) *
2196  },
2197  sqrt_s_, type_n_bar, type_K_z);
2198  break;
2199  }
2200  case pack(pdg::Lambda, pdg::pi_z): {
2201  const auto& type_p = ParticleType::find(pdg::p);
2202  const auto& type_n = ParticleType::find(pdg::n);
2203  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
2204  const auto& type_K_m = ParticleType::find(pdg::K_m);
2205  add_channel(
2206  process_list,
2207  [&] {
2208  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2209  type_p, type_K_m) *
2211  },
2212  sqrt_s_, type_p, type_K_m);
2213  add_channel(
2214  process_list,
2215  [&] {
2216  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2217  type_n, type_Kbar_z) *
2219  },
2220  sqrt_s_, type_n, type_Kbar_z);
2221  break;
2222  }
2223  case pack(-pdg::Lambda, pdg::pi_z): {
2224  const auto& type_p_bar = ParticleType::find(-pdg::p);
2225  const auto& type_n_bar = ParticleType::find(-pdg::n);
2226  const auto& type_K_z = ParticleType::find(pdg::K_z);
2227  const auto& type_K_p = ParticleType::find(pdg::K_p);
2228  add_channel(
2229  process_list,
2230  [&] {
2231  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2232  type_p_bar, type_K_p) *
2234  },
2235  sqrt_s_, type_p_bar, type_K_p);
2236  add_channel(
2237  process_list,
2238  [&] {
2239  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2240  type_n_bar, type_K_z) *
2242  },
2243  sqrt_s_, type_n_bar, type_K_z);
2244  break;
2245  }
2246  case pack(pdg::Sigma_p, pdg::pi_m): {
2247  const auto& type_p = ParticleType::find(pdg::p);
2248  const auto& type_n = ParticleType::find(pdg::n);
2249  const auto& type_K_m = ParticleType::find(pdg::K_m);
2250  const auto& type_Kbar_z = ParticleType::find(pdg::Kbar_z);
2251  add_channel(
2252  process_list,
2253  [&] {
2254  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2255  type_p, type_K_m) *
2257  },
2258  sqrt_s_, type_p, type_K_m);
2259  add_channel(
2260  process_list,
2261  [&] {
2262  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2263  type_n, type_Kbar_z) *
2265  },
2266  sqrt_s_, type_n, type_Kbar_z);
2267  break;
2268  }
2269  case pack(-pdg::Sigma_p, pdg::pi_p): {
2270  const auto& type_p_bar = ParticleType::find(-pdg::p);
2271  const auto& type_n_bar = ParticleType::find(-pdg::n);
2272  const auto& type_K_p = ParticleType::find(pdg::K_p);
2273  const auto& type_K_z = ParticleType::find(pdg::K_z);
2274  add_channel(
2275  process_list,
2276  [&] {
2277  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2278  type_p_bar, type_K_p) *
2280  },
2281  sqrt_s_, type_p_bar, type_K_p);
2282  add_channel(
2283  process_list,
2284  [&] {
2285  return detailed_balance_factor_stable(s, type_hyperon, type_pion,
2286  type_n_bar, type_K_z) *
2288  },
2289  sqrt_s_, type_n_bar, type_K_z);
2290  break;
2291  }
2292  default:
2293  break;
2294  }
2295 
2296  return process_list;
2297 }
static double detailed_balance_factor_stable(double s, const ParticleType &a, const ParticleType &b, const ParticleType &c, const ParticleType &d)
Helper function: Calculate the detailed balance factor R such that.

◆ dpi_xx()

CollisionBranchList smash::CrossSections::dpi_xx ( const ReactionsBitSet included_2to2) const
private

Find all inelastic 2->2 processes involving Pion and (anti-) Deuteron (dpi), specifically dπ→ NN, d̅π→ N̅N̅; πd→ πd' (mockup for πd→ πnp), πd̅→ πd̅' and reverse.

Parameters
[in]included_2to2Which 2->2 reactions are enabled?
Returns
List of all possible dpi reactions with their cross sections

Definition at line 2331 of file crosssections.cc.

2332  {
2333  CollisionBranchList process_list;
2334  const double sqrts = sqrt_s_;
2335  const ParticleType& type_a = incoming_particles_[0].type();
2336  const ParticleType& type_b = incoming_particles_[1].type();
2337 
2338  // pi d -> N N
2339  bool is_pid = (type_a.is_deuteron() && type_b.pdgcode().is_pion()) ||
2340  (type_b.is_deuteron() && type_a.pdgcode().is_pion());
2341  if (is_pid && included_2to2[IncludedReactions::PiDeuteron_to_NN] == 1) {
2342  const int baryon_number = type_a.baryon_number() + type_b.baryon_number();
2343  ParticleTypePtrList nuc = (baryon_number > 0)
2346  const double s = sqrt_s_ * sqrt_s_;
2347  for (ParticleTypePtr nuc_a : nuc) {
2348  for (ParticleTypePtr nuc_b : nuc) {
2349  if (type_a.charge() + type_b.charge() !=
2350  nuc_a->charge() + nuc_b->charge()) {
2351  continue;
2352  }
2353  // loop over total isospin
2354  for (const int twoI : I_tot_range(*nuc_a, *nuc_b)) {
2355  const double isospin_factor = isospin_clebsch_gordan_sqr_2to2(
2356  type_a, type_b, *nuc_a, *nuc_b, twoI);
2357  // If Clebsch-Gordan coefficient = 0, don't bother with the rest.
2358  if (std::abs(isospin_factor) < really_small) {
2359  continue;
2360  }
2361 
2362  // Calculate matrix element for inverse process.
2363  const double matrix_element =
2364  nn_to_resonance_matrix_element(sqrts, type_a, type_b, twoI);
2365  if (matrix_element <= 0.) {
2366  continue;
2367  }
2368 
2369  const double spin_factor = (nuc_a->spin() + 1) * (nuc_b->spin() + 1);
2370  const int sym_fac_in =
2371  (type_a.iso_multiplet() == type_b.iso_multiplet()) ? 2 : 1;
2372  const int sym_fac_out =
2373  (nuc_a->iso_multiplet() == nuc_b->iso_multiplet()) ? 2 : 1;
2374  double p_cm_final = pCM_from_s(s, nuc_a->mass(), nuc_b->mass());
2375  const double xsection = isospin_factor * spin_factor * sym_fac_in /
2376  sym_fac_out * p_cm_final * matrix_element /
2377  (s * cm_momentum());
2378 
2379  if (xsection > really_small) {
2380  process_list.push_back(std::make_unique<CollisionBranch>(
2381  *nuc_a, *nuc_b, xsection, ProcessType::TwoToTwo));
2382  logg[LScatterAction].debug(type_a.name(), type_b.name(), "->",
2383  nuc_a->name(), nuc_b->name(),
2384  " at sqrts [GeV] = ", sqrts,
2385  " with cs[mb] = ", xsection);
2386  }
2387  }
2388  }
2389  }
2390  }
2391 
2392  // pi d -> pi d' (effectively pi d -> pi p n) AND reverse, pi d' -> pi d
2393  bool is_pid_or_pidprime = ((type_a.is_deuteron() || type_a.is_dprime()) &&
2394  type_b.pdgcode().is_pion()) ||
2395  ((type_b.is_deuteron() || type_b.is_dprime()) &&
2396  type_a.pdgcode().is_pion());
2397  if (is_pid_or_pidprime &&
2398  included_2to2[IncludedReactions::PiDeuteron_to_pidprime] == 1) {
2399  const ParticleType& type_pi = type_a.pdgcode().is_pion() ? type_a : type_b;
2400  const ParticleType& type_nucleus = type_a.is_nucleus() ? type_a : type_b;
2401  ParticleTypePtrList nuclei = ParticleType::list_light_nuclei();
2402  for (ParticleTypePtr produced_nucleus : nuclei) {
2403  // Elastic collisions are treated in a different function
2404  if (produced_nucleus == &type_nucleus ||
2405  produced_nucleus->charge() != type_nucleus.charge() ||
2406  produced_nucleus->baryon_number() != type_nucleus.baryon_number()) {
2407  continue;
2408  }
2409  const double xsection =
2410  xs_dpi_dprimepi(sqrts, cm_momentum(), produced_nucleus, type_pi);
2411  process_list.push_back(std::make_unique<CollisionBranch>(
2412  type_pi, *produced_nucleus, xsection, ProcessType::TwoToTwo));
2413  logg[LScatterAction].debug(type_pi.name(), type_nucleus.name(), "→ ",
2414  type_pi.name(), produced_nucleus->name(),
2415  " at ", sqrts, " GeV, xs[mb] = ", xsection);
2416  }
2417  }
2418  return process_list;
2419 }
static double xs_dpi_dprimepi(double sqrts, double cm_mom, ParticleTypePtr produced_nucleus, const ParticleType &type_pi)
Parametrized cross section for πd→ πd' (mockup for πd→ πnp), πd̅→ πd̅' and reverse,...
static double nn_to_resonance_matrix_element(double sqrts, const ParticleType &type_a, const ParticleType &type_b, const int twoI)
Scattering matrix amplitude squared (divided by 16π) for resonance production processes like NN → NR ...
static ParticleTypePtrList & list_nucleons()
Definition: particletype.cc:69
static ParticleTypePtrList & list_light_nuclei()
Definition: particletype.cc:85
@ PiDeuteron_to_pidprime
double isospin_clebsch_gordan_sqr_2to2(const ParticleType &p_a, const ParticleType &p_b, const ParticleType &p_c, const ParticleType &p_d, const int I=-1)
Calculate the squared isospin Clebsch-Gordan coefficient for a 2-to-2 reaction A + B -> C + D.
T pCM_from_s(const T s, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:66
static constexpr int LScatterAction

◆ dn_xx()

CollisionBranchList smash::CrossSections::dn_xx ( const ReactionsBitSet included_2to2) const
private

Find all inelastic 2->2 processes involving Nucleon and (anti-) Deuteron (dN), specifically Nd → Nd', N̅d → N̅d', N̅d̅→ N̅d̅', Nd̅→ Nd̅' and reverse (e.g.

Nd'→ Nd).

Parameters
[in]included_2to2Which 2->2 reactions are enabled?
Returns
List of all possible dN reactions with their cross sections

Definition at line 2459 of file crosssections.cc.

2460  {
2461  const ParticleType& type_a = incoming_particles_[0].type();
2462  const ParticleType& type_b = incoming_particles_[1].type();
2463  const ParticleType& type_N = type_a.is_nucleon() ? type_a : type_b;
2464  const ParticleType& type_nucleus = type_a.is_nucleus() ? type_a : type_b;
2465  CollisionBranchList process_list;
2466  if (included_2to2[IncludedReactions::NDeuteron_to_Ndprime] == 0) {
2467  return process_list;
2468  }
2469  ParticleTypePtrList nuclei = ParticleType::list_light_nuclei();
2470 
2471  for (ParticleTypePtr produced_nucleus : nuclei) {
2472  // No elastic collisions for now, respect conservation laws
2473  if (produced_nucleus == &type_nucleus ||
2474  produced_nucleus->charge() != type_nucleus.charge() ||
2475  produced_nucleus->baryon_number() != type_nucleus.baryon_number()) {
2476  continue;
2477  }
2478  const double xsection = xs_dn_dprimen(
2479  sqrt_s_, cm_momentum(), produced_nucleus, type_nucleus, type_N);
2480  process_list.push_back(std::make_unique<CollisionBranch>(
2481  type_N, *produced_nucleus, xsection, ProcessType::TwoToTwo));
2482  logg[LScatterAction].debug(type_N.name(), type_nucleus.name(), "→ ",
2483  type_N.name(), produced_nucleus->name(), " at ",
2484  sqrt_s_, " GeV, xs[mb] = ", xsection);
2485  }
2486  return process_list;
2487 }
static double xs_dn_dprimen(double sqrts, double cm_mom, ParticleTypePtr produced_nucleus, const ParticleType &type_nucleus, const ParticleType &type_N)
Parametrized cross section for Nd → Nd', N̅d → N̅d', N̅d̅→ N̅d̅', Nd̅→ Nd̅' and reverse (e....
@ NDeuteron_to_Ndprime

◆ xs_dpi_dprimepi()

double smash::CrossSections::xs_dpi_dprimepi ( double  sqrts,
double  cm_mom,
ParticleTypePtr  produced_nucleus,
const ParticleType type_pi 
)
staticprivate

Parametrized cross section for πd→ πd' (mockup for πd→ πnp), πd̅→ πd̅' and reverse, see Oliinychenko:2018ugs [47] for details.

Parameters
[in]sqrtssquare-root of mandelstam s
[in]cm_momcenter of mass momentum of incoming particles
[in]produced_nucleustype of outgoing deuteron or d-prime
[in]type_pitype of scattering pion
Returns
cross section for given scattering

Definition at line 2299 of file crosssections.cc.

2301  {
2302  const double s = sqrts * sqrts;
2303  // same matrix element for πd and πd̅
2304  const double tmp = sqrts - pion_mass - deuteron_mass;
2305  // Matrix element is fit to match the inelastic pi+ d -> pi+ n p
2306  // cross-section from the Fig. 5 of [\iref{Arndt:1994bs}].
2307  const double matrix_element =
2308  295.5 + 2.862 / (0.00283735 + pow_int(sqrts - 2.181, 2)) +
2309  0.0672 / pow_int(tmp, 2) - 6.61753 / tmp;
2310 
2311  const double spin_factor =
2312  (produced_nucleus->spin() + 1) * (type_pi.spin() + 1);
2313  /* Isospin factor is always the same, so it is included into the
2314  * matrix element.
2315  * Symmetry factor is always 1 here.
2316  * The (hbarc)^2/16 pi factor is absorbed into matrix element. */
2317  double xsection = matrix_element * spin_factor / (s * cm_mom);
2318  if (produced_nucleus->is_stable()) {
2319  xsection *= pCM_from_s(s, type_pi.mass(), produced_nucleus->mass());
2320  } else {
2321  const double resonance_integral =
2322  produced_nucleus->iso_multiplet()->get_integral_piR(sqrts);
2323  xsection *= resonance_integral;
2324  logg[LScatterAction].debug("Resonance integral ", resonance_integral,
2325  ", matrix element: ", matrix_element,
2326  ", cm_momentum: ", cm_mom);
2327  }
2328  return xsection;
2329 }
constexpr double deuteron_mass
Deuteron mass in GeV.
Definition: constants.h:96
constexpr T pow_int(const T base, unsigned const exponent)
Efficient template for calculating integer powers using squaring.
Definition: pow.h:23
constexpr double pion_mass
Pion mass in GeV.
Definition: constants.h:69

◆ xs_dn_dprimen()

double smash::CrossSections::xs_dn_dprimen ( double  sqrts,
double  cm_mom,
ParticleTypePtr  produced_nucleus,
const ParticleType type_nucleus,
const ParticleType type_N 
)
staticprivate

Parametrized cross section for Nd → Nd', N̅d → N̅d', N̅d̅→ N̅d̅', Nd̅→ Nd̅' and reverse (e.g.

Nd'→ Nd), see Oliinychenko:2018ugs [47] for details.

Parameters
[in]sqrtssquare-root of mandelstam s
[in]cm_momcenter of mass momentum of incoming particles
[in]produced_nucleustype of outgoing deuteron or d-prime
[in]type_nucleustype of scattering (incoming) deuteron or d-prime
[in]type_Ntype of scattering nucleon
Returns
cross section for given scattering

Nd → Nd', N̅d̅→ N̅d̅' and reverse: Fit to match experimental cross-section Nd -> Nnp from [17].

N̅d → N̅d', Nd̅→ Nd̅' and reverse: Fit to roughly match experimental cross-section N̅d -> N̅ np from Bizzarri:1973sp [10].

Definition at line 2421 of file crosssections.cc.

2424  {
2425  const double s = sqrts * sqrts;
2426  double matrix_element = 0.0;
2427  double tmp = sqrts - nucleon_mass - deuteron_mass;
2428  assert(tmp >= 0.0);
2429  if (std::signbit(type_N.baryon_number()) ==
2430  std::signbit(type_nucleus.baryon_number())) {
2434  matrix_element = 79.0474 / std::pow(tmp, 0.7897) + 654.596 * tmp;
2435  } else {
2439  matrix_element = 342.572 / std::pow(tmp, 0.6);
2440  }
2441  const double spin_factor =
2442  (produced_nucleus->spin() + 1) * (type_N.spin() + 1);
2443  /* Isospin factor is always the same, so it is included into matrix element
2444  * Symmetry factor is always 1 here
2445  * Absorb (hbarc)^2/16 pi factor into matrix element */
2446  double xsection = matrix_element * spin_factor / (s * cm_mom);
2447  if (produced_nucleus->is_stable()) {
2448  assert(!type_nucleus.is_stable());
2449  xsection *= pCM_from_s(s, type_N.mass(), produced_nucleus->mass());
2450  } else {
2451  assert(type_nucleus.is_stable());
2452  const double resonance_integral =
2453  produced_nucleus->iso_multiplet()->get_integral_NR(sqrts);
2454  xsection *= resonance_integral;
2455  }
2456  return xsection;
2457 }

◆ string_hard_cross_section()

double smash::CrossSections::string_hard_cross_section ( ) const
private

Determine the (parametrized) hard non-diffractive string cross section for this collision.

Returns
Parametrized cross section (without AQM scaling).

Definition at line 2697 of file crosssections.cc.

2697  {
2698  double cross_sec = 0.;
2699  /* Hard strings can only be excited if the lower cutoff by
2700  * Pythia is fulfilled */
2702  return cross_sec;
2703  }
2704  const ParticleData& data_a = incoming_particles_[0];
2705  const ParticleData& data_b = incoming_particles_[1];
2706 
2707  if (data_a.is_baryon() && data_b.is_baryon()) {
2708  // Nucleon-nucleon cross section is used for all baryon-baryon cases.
2709  const double eff_s =
2710  effective_AQM_s(sqrt_s_ * sqrt_s_, data_a.effective_mass(),
2711  data_b.effective_mass(), nucleon_mass, nucleon_mass);
2712  cross_sec = NN_string_hard(eff_s);
2713  } else if (data_a.is_baryon() || data_b.is_baryon()) {
2714  // Nucleon-pion cross section is used for all baryon-meson cases.
2715  cross_sec = Npi_string_hard(sqrt_s_ * sqrt_s_);
2716  } else {
2717  // Pion-pion cross section is used for all meson-meson cases.
2718  cross_sec = pipi_string_hard(sqrt_s_ * sqrt_s_);
2719  }
2720 
2721  return cross_sec;
2722 }
double Npi_string_hard(double mandelstam_s)
nucleon-pion hard scattering cross section (with partonic scattering)
constexpr double minimum_sqrts_pythia_can_handle
Energy in GeV, below which hard reactions via pythia are impossible.
Definition: constants.h:115
double pipi_string_hard(double mandelstam_s)
pion-pion hard scattering cross section (with partonic scattering)
double NN_string_hard(double mandelstam_s)
nucleon-nucleon hard scattering cross section (with partonic scattering)

◆ bar_bar_to_nuc_nuc()

CollisionBranchList smash::CrossSections::bar_bar_to_nuc_nuc ( const bool  is_anti_particles) const
private

Calculate cross sections for resonance absorption (i.e.

NR->NN and ΔR->NN).

Parameters
[in]is_anti_particlesWhether the colliding particles are antiparticles
Returns
List of possible resonance absorption processes. Each element of the list contains the types of the final-state particles and the cross section for that particular process.

Cross section for 2->2 resonance absorption, obtained via detailed balance from the inverse reaction. See eqs. (B.6), (B.9) and (181) in Buss:2011mx [14]. There are factors for spin, isospin and symmetry involved.

Definition at line 2786 of file crosssections.cc.

2787  {
2788  const ParticleType& type_a = incoming_particles_[0].type();
2789  const ParticleType& type_b = incoming_particles_[1].type();
2790  CollisionBranchList process_list;
2791 
2792  const double s = sqrt_s_ * sqrt_s_;
2793  // CM momentum in final state
2794  double p_cm_final = std::sqrt(s - 4. * nucleon_mass * nucleon_mass) / 2.;
2795 
2796  ParticleTypePtrList nuc_or_anti_nuc;
2797  if (is_anti_particles) {
2798  nuc_or_anti_nuc = ParticleType::list_anti_nucleons();
2799  } else {
2800  nuc_or_anti_nuc = ParticleType::list_nucleons();
2801  }
2802 
2803  // Loop over all nucleon or anti-nucleon charge states.
2804  for (ParticleTypePtr nuc_a : nuc_or_anti_nuc) {
2805  for (ParticleTypePtr nuc_b : nuc_or_anti_nuc) {
2806  /* Check for charge conservation. */
2807  if (type_a.charge() + type_b.charge() !=
2808  nuc_a->charge() + nuc_b->charge()) {
2809  continue;
2810  }
2811  // loop over total isospin
2812  for (const int twoI : I_tot_range(*nuc_a, *nuc_b)) {
2813  const double isospin_factor = isospin_clebsch_gordan_sqr_2to2(
2814  type_a, type_b, *nuc_a, *nuc_b, twoI);
2815  // If Clebsch-Gordan coefficient is zero, don't bother with the rest
2816  if (std::abs(isospin_factor) < really_small) {
2817  continue;
2818  }
2819 
2820  // Calculate matrix element for inverse process.
2821  const double matrix_element =
2822  nn_to_resonance_matrix_element(sqrt_s_, type_a, type_b, twoI);
2823  if (matrix_element <= 0.) {
2824  continue;
2825  }
2826 
2831  const double spin_factor = (nuc_a->spin() + 1) * (nuc_b->spin() + 1);
2832  const int sym_fac_in =
2833  (type_a.iso_multiplet() == type_b.iso_multiplet()) ? 2 : 1;
2834  const int sym_fac_out =
2835  (nuc_a->iso_multiplet() == nuc_b->iso_multiplet()) ? 2 : 1;
2836  const double xsection = isospin_factor * spin_factor * sym_fac_in /
2837  sym_fac_out * p_cm_final * matrix_element /
2838  (s * cm_momentum());
2839 
2840  if (xsection > really_small) {
2841  process_list.push_back(std::make_unique<CollisionBranch>(
2842  *nuc_a, *nuc_b, xsection, ProcessType::TwoToTwo));
2843  logg[LCrossSections].debug(
2844  "2->2 absorption with original particles: ", type_a, type_b);
2845  }
2846  }
2847  }
2848  }
2849  return process_list;
2850 }

◆ nn_to_resonance_matrix_element()

double smash::CrossSections::nn_to_resonance_matrix_element ( double  sqrts,
const ParticleType type_a,
const ParticleType type_b,
const int  twoI 
)
staticprivate

Scattering matrix amplitude squared (divided by 16π) for resonance production processes like NN → NR and NN → ΔR, where R is a baryon resonance (Δ, N*, Δ*).

Includes no spin or isospin factors.

Parameters
[in]sqrtssqrt(Mandelstam-s), i.e. collision CMS energy.
[in]type_aType information for the first final-state particle.
[in]type_bType information for the second final-state particle.
[in]twoITwice the total isospin of the involved state.
Returns
Matrix amplitude squared \( |\mathcal{M}(\sqrt{s})|^2/16\pi \).

NN → NΔ: fit sqrt(s)-dependence to OBE model [Dmitriev:1986st [21]]

All other processes use a constant matrix element, similar to Bass:1998ca [6], equ. (3.35).

pn → pnη cross section is known to be larger than the corresponding pp → ppη cross section by a factor of 6.5 [Calen:1998vh [15]]. Since the eta is mainly produced by an intermediate N*(1535) we introduce an explicit isospin asymmetry for the production of N*(1535) produced in pn vs. pp similar to [Teis:1996kx [62]], eq. 29.

Definition at line 2852 of file crosssections.cc.

2855  {
2856  const double m_a = type_a.mass();
2857  const double m_b = type_b.mass();
2858  const double msqr = 2. * (m_a * m_a + m_b * m_b);
2859  /* If the c.m. energy is larger than the sum of the pole masses of the
2860  * outgoing particles plus three times of the sum of the widths plus 3 GeV,
2861  * the collision will be neglected.
2862  *
2863  * This can be problematic for some final-state cross sections, but at
2864  * energies that high strings are used anyway.
2865  */
2866  const double w_a = type_a.width_at_pole();
2867  const double w_b = type_b.width_at_pole();
2868  const double uplmt = m_a + m_b + 3.0 * (w_a + w_b) + 3.0;
2869  if (sqrts > uplmt) {
2870  return 0.;
2871  }
2873  if (((type_a.is_Delta() && type_b.is_nucleon()) ||
2874  (type_b.is_Delta() && type_a.is_nucleon())) &&
2875  (type_a.antiparticle_sign() == type_b.antiparticle_sign())) {
2876  return 68. / std::pow(sqrts - 1.104, 1.951);
2879  } else if (((type_a.is_Nstar() && type_b.is_nucleon()) ||
2880  (type_b.is_Nstar() && type_a.is_nucleon())) &&
2881  type_a.antiparticle_sign() == type_b.antiparticle_sign()) {
2882  // NN → NN*
2883  if (twoI == 2) {
2884  return 4.5 / msqr;
2885  } else if (twoI == 0) {
2886  const double parametrization = 14. / msqr;
2892  if (type_a.is_Nstar1535() || type_b.is_Nstar1535()) {
2893  return 6.5 * parametrization;
2894  } else {
2895  return parametrization;
2896  }
2897  }
2898  } else if (((type_a.is_Deltastar() && type_b.is_nucleon()) ||
2899  (type_b.is_Deltastar() && type_a.is_nucleon())) &&
2900  type_a.antiparticle_sign() == type_b.antiparticle_sign()) {
2901  // NN → NΔ*
2902  return 15. / msqr;
2903  } else if ((type_a.is_Delta() && type_b.is_Delta()) &&
2904  (type_a.antiparticle_sign() == type_b.antiparticle_sign())) {
2905  // NN → ΔΔ
2906  if (twoI == 2) {
2907  return 45. / msqr;
2908  } else if (twoI == 0) {
2909  return 120. / msqr;
2910  }
2911  } else if (((type_a.is_Nstar() && type_b.is_Delta()) ||
2912  (type_b.is_Nstar() && type_a.is_Delta())) &&
2913  type_a.antiparticle_sign() == type_b.antiparticle_sign()) {
2914  // NN → ΔN*
2915  return 7. / msqr;
2916  } else if (((type_a.is_Deltastar() && type_b.is_Delta()) ||
2917  (type_b.is_Deltastar() && type_a.is_Delta())) &&
2918  type_a.antiparticle_sign() == type_b.antiparticle_sign()) {
2919  // NN → ΔΔ*
2920  if (twoI == 2) {
2921  return 15. / msqr;
2922  } else if (twoI == 0) {
2923  return 25. / msqr;
2924  }
2925  } else if ((type_a.is_deuteron() && type_b.pdgcode().is_pion()) ||
2926  (type_b.is_deuteron() && type_a.pdgcode().is_pion())) {
2927  /* This parametrization is the result of fitting d+pi->NN cross-section.
2928  * Already Breit-Wigner-like part provides a good fit, exponential fixes
2929  * behaviour around the treshold. The d+pi experimental cross-section
2930  * was taken from Fig. 2 of [\iref{Tanabe:1987vg}]. */
2931  return 0.055 / (pow_int(sqrts - 2.145, 2) + pow_int(0.065, 2)) *
2932  (1.0 - std::exp(-(sqrts - 2.0) * 20.0));
2933  }
2934 
2935  // all cases not listed: zero!
2936  return 0.;
2937 }

◆ find_nn_xsection_from_type()

template<class IntegrationMethod >
CollisionBranchList smash::CrossSections::find_nn_xsection_from_type ( const ParticleTypePtrList &  type_res_1,
const ParticleTypePtrList &  type_res_2,
const IntegrationMethod  integrator 
) const
private

Utility function to avoid code replication in nn_xx().

Parameters
[in]type_res_1List of possible first final resonance types
[in]type_res_2List of possible second final resonance types
[in]integratorUsed to integrate over the kinematically allowed mass range of the Breit-Wigner distribution
Returns
List of all possible NN reactions with their cross sections with different final states

Cross section for 2->2 process with 1/2 resonance(s) in final state. Based on Eq. (46) in Weil:2013mya [65] and Eq. (3.29) in Bass:1998ca [6]

Definition at line 2940 of file crosssections.cc.

2943  {
2944  const ParticleType& type_particle_a = incoming_particles_[0].type();
2945  const ParticleType& type_particle_b = incoming_particles_[1].type();
2946 
2947  CollisionBranchList channel_list;
2948  const double s = sqrt_s_ * sqrt_s_;
2949 
2950  // Loop over specified first resonance list
2951  for (ParticleTypePtr type_res_1 : list_res_1) {
2952  // Loop over specified second resonance list
2953  for (ParticleTypePtr type_res_2 : list_res_2) {
2954  // Check for charge conservation.
2955  if (type_res_1->charge() + type_res_2->charge() !=
2956  type_particle_a.charge() + type_particle_b.charge()) {
2957  continue;
2958  }
2959 
2960  // loop over total isospin
2961  for (const int twoI : I_tot_range(type_particle_a, type_particle_b)) {
2962  const double isospin_factor = isospin_clebsch_gordan_sqr_2to2(
2963  type_particle_a, type_particle_b, *type_res_1, *type_res_2, twoI);
2964  // If Clebsch-Gordan coefficient is zero, don't bother with the rest.
2965  if (std::abs(isospin_factor) < really_small) {
2966  continue;
2967  }
2968 
2969  // Integration limits.
2970  const double lower_limit = type_res_1->min_mass_kinematic();
2971  const double upper_limit = sqrt_s_ - type_res_2->mass();
2972  /* Check the available energy (requiring it to be a little above the
2973  * threshold, because the integration will not work if it's too close).
2974  */
2975  if (upper_limit - lower_limit < 1E-3) {
2976  continue;
2977  }
2978 
2979  // Calculate matrix element.
2980  const double matrix_element = nn_to_resonance_matrix_element(
2981  sqrt_s_, *type_res_1, *type_res_2, twoI);
2982  if (matrix_element <= 0.) {
2983  continue;
2984  }
2985 
2986  /* Calculate resonance production cross section
2987  * using the Breit-Wigner distribution as probability amplitude.
2988  * Integrate over the allowed resonance mass range. */
2989  const double resonance_integral = integrator(*type_res_1, *type_res_2);
2990 
2994  const double spin_factor =
2995  (type_res_1->spin() + 1) * (type_res_2->spin() + 1);
2996  const double xsection = isospin_factor * spin_factor * matrix_element *
2997  resonance_integral / (s * cm_momentum());
2998 
2999  if (xsection > really_small) {
3000  channel_list.push_back(std::make_unique<CollisionBranch>(
3001  *type_res_1, *type_res_2, xsection, ProcessType::TwoToTwo));
3002  logg[LCrossSections].debug(
3003  "Found 2->2 creation process for resonance ", type_res_1, ", ",
3004  type_res_2);
3005  logg[LCrossSections].debug("2->2 with original particles: ",
3006  type_particle_a, type_particle_b);
3007  }
3008  }
3009  }
3010  }
3011  return channel_list;
3012 }

◆ cm_momentum()

double smash::CrossSections::cm_momentum ( ) const
inlineprivate

Determine the momenta of the incoming particles in the center-of-mass system.

Returns
Center-of-mass momentum

Definition at line 580 of file crosssections.h.

580  {
581  const double m1 = incoming_particles_[0].effective_mass();
582  const double m2 = incoming_particles_[1].effective_mass();
583  return pCM(sqrt_s_, m1, m2);
584  }

◆ add_channel()

template<typename F >
void smash::CrossSections::add_channel ( CollisionBranchList &  process_list,
F &&  get_xsection,
double  sqrts,
const ParticleType type_a,
const ParticleType type_b 
) const
inlineprivate

Helper function: Add a 2-to-2 channel to a collision branch list given a cross section.

The cross section is only calculated if there is enough energy for the process. If the cross section is small, the branch is not added.

Definition at line 615 of file crosssections.h.

617  {
618  const double sqrt_s_min =
619  type_a.min_mass_spectral() + type_b.min_mass_spectral();
620  /* Determine wether the process is below the threshold. */
621  double scale_B = 0.0;
622  double scale_I3 = 0.0;
623  bool is_below_threshold;
624  FourVector incoming_momentum = FourVector();
625  if (pot_pointer != nullptr) {
626  for (const auto& p : incoming_particles_) {
627  incoming_momentum += p.momentum();
628  scale_B += pot_pointer->force_scale(p.type()).first;
629  scale_I3 +=
630  pot_pointer->force_scale(p.type()).second * p.type().isospin3_rel();
631  }
632  scale_B -= pot_pointer->force_scale(type_a).first;
633  scale_I3 -=
634  pot_pointer->force_scale(type_a).second * type_a.isospin3_rel();
635  scale_B -= pot_pointer->force_scale(type_b).first;
636  scale_I3 -=
637  pot_pointer->force_scale(type_b).second * type_b.isospin3_rel();
638  is_below_threshold = (incoming_momentum + potentials_.first * scale_B +
639  potentials_.second * scale_I3)
640  .abs() <= sqrt_s_min;
641  } else {
642  is_below_threshold = (sqrts <= sqrt_s_min);
643  }
644  if (is_below_threshold) {
645  return;
646  }
647  const auto xsection = get_xsection();
648  if (xsection > really_small) {
649  process_list.push_back(std::make_unique<CollisionBranch>(
650  type_a, type_b, xsection, ProcessType::TwoToTwo));
651  }
652  }
static std::pair< double, int > force_scale(const ParticleType &data)
Evaluates the scaling factor of the forces acting on the particles.
Definition: potentials.cc:158
Potentials * pot_pointer
Pointer to a Potential class.

Member Data Documentation

◆ incoming_particles_

const ParticleList smash::CrossSections::incoming_particles_
private

List with data of scattering particles.

Definition at line 587 of file crosssections.h.

◆ sqrt_s_

const double smash::CrossSections::sqrt_s_
private

Total energy in the center-of-mass frame.

Definition at line 590 of file crosssections.h.

◆ potentials_

const std::pair<FourVector, FourVector> smash::CrossSections::potentials_
private

Potentials at the interacting point.

They are used to calculate the corrections on the threshold energies.

Definition at line 596 of file crosssections.h.

◆ is_BBbar_pair_

const bool smash::CrossSections::is_BBbar_pair_
private

Whether incoming particles are a pair of a baryon and an antibaryon (could be different baryon types)

Definition at line 602 of file crosssections.h.

◆ is_NNbar_pair_

const bool smash::CrossSections::is_NNbar_pair_
private

Whether incoming particles are a nulecon-antinucleon pair (same isospin)

Definition at line 605 of file crosssections.h.


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