Version: SMASH-3.4
smash::ScatterAction Class Reference

#include <scatteraction.h>

ScatterAction is a special action which takes two incoming particles and performs a scattering, producing one or more final-state particles.

Definition at line 30 of file scatteraction.h.

Inheritance diagram for smash::ScatterAction:
[legend]
Collaboration diagram for smash::ScatterAction:
[legend]

Classes

class  InvalidScatterAction
 Thrown when ScatterAction is called to perform with unknown ProcessType. More...
 

Public Member Functions

 ScatterAction (const ParticleData &in_part1, const ParticleData &in_part2, double time, bool isotropic=false, double string_formation_time=1.0, double box_length=-1.0, bool is_total_parametrized=false, const SpinInteractionType spin_interaction_type=SpinInteractionType::Off)
 Construct a ScatterAction object. More...
 
void add_collision (CollisionBranchPtr p)
 Add a new collision channel. More...
 
void add_collisions (CollisionBranchList pv)
 Add several new collision channels at once. More...
 
double transverse_distance_sqr () const
 Calculate the transverse distance of the two incoming particles in their local rest frame. More...
 
double cov_transverse_distance_sqr () const
 Calculate the transverse distance of the two incoming particles in their local rest frame written in a covariant form. More...
 
double mandelstam_s () const
 Determine the Mandelstam s variable,. More...
 
double relative_velocity () const
 Get the relative velocity of the two incoming particles. More...
 
void generate_final_state () override
 Generate the final-state of the scattering process. More...
 
double get_total_weight () const override
 Get the total cross section of scattering particles. More...
 
double get_partial_weight () const override
 Get the partial cross section of the chosen channel. More...
 
void sample_angles (std::pair< double, double > masses, double kinetic_energy_cm) override
 Sample final-state angles in a 2->2 collision (possibly anisotropic). More...
 
void add_all_scatterings (const ScatterActionsFinderParameters &finder_parameters)
 Add all possible scattering subprocesses for this action object. More...
 
void set_parametrized_total_cross_section (const ScatterActionsFinderParameters &finder_parameters)
 Given the incoming particles, assigns the correct parametrization of the total cross section. More...
 
const CollisionBranchList & collision_channels ()
 Get list of possible collision channels. More...
 
void set_string_interface (StringProcess *str_proc)
 Set the StringProcess object to be used. More...
 
virtual double cross_section () const
 Get the total cross section of the scattering particles, either from a parametrization, or from the sum of partials. More...
 
- Public Member Functions inherited from smash::Action
 Action (const ParticleList &in_part, double time)
 Construct an action object with incoming particles and relative time. More...
 
 Action (const ParticleData &in_part, const ParticleData &out_part, double time, ProcessType type)
 Construct an action object with the incoming particles, relative time, and the already known outgoing particles and type of the process. More...
 
 Action (const ParticleList &in_part, const ParticleList &out_part, double absolute_execution_time, ProcessType type)
 Construct an action object with the incoming particles, absolute time, and the already known outgoing particles and type of the process. More...
 
 Action (const Action &)=delete
 Copying is disabled. Use pointers or create a new Action. More...
 
virtual ~Action ()
 Virtual Destructor. More...
 
bool operator< (const Action &rhs) const
 Determine whether one action takes place before another in time. More...
 
virtual ProcessType get_type () const
 Get the process type. More...
 
template<typename Branch >
void add_process (ProcessBranchPtr< Branch > &p, ProcessBranchList< Branch > &subprocesses, double &total_weight)
 Add a new subprocess. More...
 
template<typename Branch >
void add_processes (ProcessBranchList< Branch > pv, ProcessBranchList< Branch > &subprocesses, double &total_weight)
 Add several new subprocesses at once. More...
 
virtual double perform (Particles *particles, uint32_t id_process)
 Actually perform the action, e.g. More...
 
bool is_valid (const Particles &particles) const
 Check whether the action still applies. More...
 
bool is_pauli_blocked (const std::vector< Particles > &ensembles, const PauliBlocker &p_bl) const
 Check if the action is Pauli-blocked. More...
 
const ParticleList & incoming_particles () const
 Get the list of particles that go into the action. More...
 
void update_incoming (const Particles &particles)
 Update the incoming particles that are stored in this action to the state they have in the global particle list. More...
 
const ParticleList & outgoing_particles () const
 Get the list of particles that resulted from the action. More...
 
double time_of_execution () const
 Get the time at which the action is supposed to be performed. More...
 
virtual double check_conservation (const uint32_t id_process) const
 Check various conservation laws. More...
 
double sqrt_s () const
 Determine the total energy in the center-of-mass frame [GeV]. More...
 
FourVector total_momentum_of_outgoing_particles () const
 Calculate the total kinetic momentum of the outgoing particles. More...
 
FourVector get_interaction_point () const
 Get the interaction point. More...
 
std::pair< FourVector, FourVectorget_potential_at_interaction_point () const
 Get the skyrme and asymmetry potential at the interaction point. More...
 
void set_stochastic_pos_idx ()
 Setter function that stores a random incoming particle index latter used to determine the interaction point. More...
 
void assign_unpolarized_spin_vector_to_outgoing_particles ()
 Assign an unpolarized spin vector to all outgoing particles. More...
 

Protected Member Functions

double cm_momentum () const
 Get the momentum of the center of mass of the incoming particles in the calculation frame. More...
 
double cm_momentum_squared () const
 Get the squared momentum of the center of mass of the incoming particles in the calculation frame. More...
 
ThreeVector beta_cm () const
 Get the velocity of the center of mass of the scattering/incoming particles in the calculation frame. More...
 
double gamma_cm () const
 Get the gamma factor corresponding to a boost to the center of mass frame of the colliding particles. More...
 
void elastic_scattering ()
 Perform an elastic two-body scattering, i.e. just exchange momentum. More...
 
void inelastic_scattering ()
 Perform an inelastic two-body scattering, i.e. new particles are formed. More...
 
void two_to_many_scattering ()
 Perform an inelastic two-to-many-body scattering (more than 2) More...
 
void create_string_final_state ()
 Creates the final states for string-processes after they are performed. More...
 
void string_excitation ()
 Todo(ryu): document better - it is not really UrQMD-based, isn't it? Perform the UrQMD-based string excitation and decay. More...
 
void spin_interaction ()
 Perform spin interaction in binary interactions. More...
 
void string_spin_interaction ()
 Perform spin interaction in string excitations. More...
 
void format_debug_output (std::ostream &out) const override
 Writes information about this scatter action to the out stream. More...
 
- Protected Member Functions inherited from smash::Action
FourVector total_momentum () const
 Sum of 4-momenta of incoming particles. More...
 
template<typename Branch >
const Branch * choose_channel (const ProcessBranchList< Branch > &subprocesses, double total_weight)
 Decide for a particular final-state channel via Monte-Carlo and return it as a ProcessBranch. More...
 
virtual std::pair< double, double > sample_masses (double kinetic_energy_cm) const
 Sample final-state masses in general X->2 processes (thus also fixing the absolute c.o.m. More...
 
virtual void sample_2body_phasespace ()
 Sample the full 2-body phase-space (masses, momenta, angles) in the center-of-mass frame for the final state particles. More...
 
virtual void sample_manybody_phasespace ()
 Sample the full n-body phase-space (masses, momenta, angles) in the center-of-mass frame for the final state particles. More...
 
void assign_formation_time_to_outgoing_particles ()
 Assign the formation time to the outgoing particles. More...
 

Protected Attributes

CollisionBranchList collision_channels_
 List of possible collisions. More...
 
double sum_of_partial_cross_sections_
 Current sum of partial hadronic cross sections. More...
 
double partial_cross_section_
 Partial cross-section to the chosen outgoing channel. More...
 
bool isotropic_ = false
 Do this collision isotropically? More...
 
double string_formation_time_ = 1.0
 Time fragments take to be fully formed in hard string excitation. More...
 
- Protected Attributes inherited from smash::Action
ParticleList incoming_particles_
 List with data of incoming particles. More...
 
ParticleList outgoing_particles_
 Initially this stores only the PDG codes of final-state particles. More...
 
const double time_of_execution_
 Time at which the action is supposed to be performed (absolute time in the lab frame in fm). More...
 
ProcessType process_type_
 type of process More...
 
double box_length_ = -1.0
 Box length: needed to determine coordinates of collision correctly in case of collision through the wall. More...
 
int stochastic_position_idx_ = -1
 This stores a randomly-chosen index to an incoming particle. More...
 

Private Member Functions

bool is_elastic () const
 Check if the scattering is elastic. More...
 
void resonance_formation ()
 Perform a 2->1 resonance-formation process. More...
 
void rescale_outgoing_branches ()
 Loop over the possible branches and rescales their weight according to the desired total cross section. More...
 
ParticleTypePtr try_find_pseudoresonance (const PseudoResonance method, const StringTransitionParameters &transition) const
 Try to find a pseudo-resonance that can be created from the incoming particles using a given method. More...
 

Private Attributes

StringProcessstring_process_ = nullptr
 Pointer to interface class for strings. More...
 
bool is_total_parametrized_ = false
 Whether the total cross section is parametrized. More...
 
std::optional< double > parametrized_total_cross_section_ = std::nullopt
 If cross section is parametrized, store the value. More...
 
SpinInteractionType spin_interaction_type_ = SpinInteractionType::Off
 What kind of spin interaction to use. More...
 
bool were_processes_added_ = false
 Lock for calling add_all_scatterings only once. More...
 

Static Private Attributes

static std::set< std::set< ParticleTypePtr > > warned_no_rescaling_available {}
 Warn about zero cross section only once per particle type pair. More...
 

Additional Inherited Members

- Static Public Member Functions inherited from smash::Action
static double lambda_tilde (double a, double b, double c)
 Little helper function that calculates the lambda function (sometimes written with a tilde to better distinguish it) that appears e.g. More...
 

Constructor & Destructor Documentation

◆ ScatterAction()

smash::ScatterAction::ScatterAction ( const ParticleData in_part1,
const ParticleData in_part2,
double  time,
bool  isotropic = false,
double  string_formation_time = 1.0,
double  box_length = -1.0,
bool  is_total_parametrized = false,
const SpinInteractionType  spin_interaction_type = SpinInteractionType::Off 
)

Construct a ScatterAction object.

Parameters
[in]in_part1first scattering partner
[in]in_part2second scattering partner
[in]timeTime at which the action is supposed to take place
[in]isotropicif true, do the collision isotropically
[in]string_formation_timeTime string fragments take to form
[in]box_lengthPassing box length to determine coordinate of the collision, in case it happened through the wall in a box. If negative, then there is no wrapping.
[in]is_total_parametrizedWhether the total cross section used for collision finding is parametrized
[in]spin_interaction_typeWhich type of spin interaction to use

Definition at line 29 of file scatteraction.cc.

36  : Action({in_part_a, in_part_b}, time),
38  isotropic_(isotropic),
39  string_formation_time_(string_formation_time),
40  is_total_parametrized_(is_total_parametrized),
41  spin_interaction_type_(spin_interaction_type) {
42  box_length_ = box_length;
44  parametrized_total_cross_section_ = smash_NaN<double>;
45  }
46 }
Action(const ParticleList &in_part, double time)
Construct an action object with incoming particles and relative time.
Definition: action.h:44
double box_length_
Box length: needed to determine coordinates of collision correctly in case of collision through the w...
Definition: action.h:379
SpinInteractionType spin_interaction_type_
What kind of spin interaction to use.
bool isotropic_
Do this collision isotropically?
double string_formation_time_
Time fragments take to be fully formed in hard string excitation.
std::optional< double > parametrized_total_cross_section_
If cross section is parametrized, store the value.
bool is_total_parametrized_
Whether the total cross section is parametrized.
double sum_of_partial_cross_sections_
Current sum of partial hadronic cross sections.

Member Function Documentation

◆ add_collision()

void smash::ScatterAction::add_collision ( CollisionBranchPtr  p)

Add a new collision channel.

Parameters
[in]pChannel to be added.

Definition at line 48 of file scatteraction.cc.

48  {
49  add_process<CollisionBranch>(p, collision_channels_,
51 }
CollisionBranchList collision_channels_
List of possible collisions.
constexpr int p
Proton.
Here is the caller graph for this function:

◆ add_collisions()

void smash::ScatterAction::add_collisions ( CollisionBranchList  pv)

Add several new collision channels at once.

Parameters
[in]pvlist of channels to be added.

Definition at line 53 of file scatteraction.cc.

53  {
54  add_processes<CollisionBranch>(std::move(pv), collision_channels_,
56 }
Here is the caller graph for this function:

◆ transverse_distance_sqr()

double smash::ScatterAction::transverse_distance_sqr ( ) const

Calculate the transverse distance of the two incoming particles in their local rest frame.

According to UrQMD criterion, Bass:1998ca [8] eq. (3.27):

  • position of particle a: \(\mathbf{x}_a\)
  • position of particle b: \(\mathbf{x}_b\)
  • momentum of particle a: \(\mathbf{p}_a\)
  • momentum of particle b: \(\mathbf{p}_b\)

\[ d^2_\mathrm{coll} = (\mathbf{x}_a - \mathbf{x}_b)^2 - \frac{\bigl[(\mathbf{x}_a - \mathbf{x}_b) \cdot (\mathbf{p}_a - \mathbf{p}_b)\bigr]^2 } {(\mathbf{p}_a - \mathbf{p}_b)^2} \]

Returns
squared distance \(d^2_\mathrm{coll}\).

Definition at line 393 of file scatteraction.cc.

393  {
394  // local copy of particles (since we need to boost them)
395  ParticleData p_a = incoming_particles_[0];
396  ParticleData p_b = incoming_particles_[1];
397  /* Boost particles to center-of-momentum frame. */
398  const ThreeVector velocity = beta_cm();
399  p_a.boost(velocity);
400  p_b.boost(velocity);
401  const ThreeVector pos_diff =
402  p_a.position().threevec() - p_b.position().threevec();
403  const ThreeVector mom_diff =
404  p_a.momentum().threevec() - p_b.momentum().threevec();
405 
406  logg[LScatterAction].debug("Particle ", incoming_particles_,
407  " position difference [fm]: ", pos_diff,
408  ", momentum difference [GeV]: ", mom_diff);
409 
410  const double dp2 = mom_diff.sqr();
411  const double dr2 = pos_diff.sqr();
412  /* Zero momentum leads to infite distance. */
413  if (dp2 < really_small) {
414  return dr2;
415  }
416  const double dpdr = pos_diff * mom_diff;
417 
418  /* UrQMD squared distance criterion, in the center of momentum frame:
419  * position of particle a: x_a
420  * position of particle b: x_b
421  * momentum of particle a: p_a
422  * momentum of particle b: p_b
423  * d^2_{coll} = (x_a - x_b)^2 - ((x_a - x_b) . (p_a - p_b))^2 / (p_a - p_b)^2
424  */
425  const double result = dr2 - dpdr * dpdr / dp2;
426  return result > 0.0 ? result : 0.0;
427 }
ParticleList incoming_particles_
List with data of incoming particles.
Definition: action.h:355
ThreeVector beta_cm() const
Get the velocity of the center of mass of the scattering/incoming particles in the calculation frame.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > & logg
An array that stores all pre-configured Logger objects.
Definition: logging.h:245
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:41
static constexpr int LScatterAction
Here is the call graph for this function:

◆ cov_transverse_distance_sqr()

double smash::ScatterAction::cov_transverse_distance_sqr ( ) const

Calculate the transverse distance of the two incoming particles in their local rest frame written in a covariant form.

Equivalent to the UrQMD transverse distance. See Hirano:2012yy [30] (5.6)-(5.11).

Returns
squared distance \(d^2_\mathrm{coll}\).

Definition at line 429 of file scatteraction.cc.

429  {
430  // local copy of particles (since we need to boost them)
431  ParticleData p_a = incoming_particles_[0];
432  ParticleData p_b = incoming_particles_[1];
433 
434  const FourVector delta_x = p_a.position() - p_b.position();
435  const double mom_diff_sqr =
436  (p_a.momentum().threevec() - p_b.momentum().threevec()).sqr();
437  const double x_sqr = delta_x.sqr();
438 
439  if (mom_diff_sqr < really_small) {
440  return -x_sqr;
441  }
442 
443  const double p_a_sqr = p_a.momentum().sqr();
444  const double p_b_sqr = p_b.momentum().sqr();
445  const double p_a_dot_x = p_a.momentum().Dot(delta_x);
446  const double p_b_dot_x = p_b.momentum().Dot(delta_x);
447  const double p_a_dot_p_b = p_a.momentum().Dot(p_b.momentum());
448 
449  const double b_sqr =
450  -x_sqr -
451  (p_a_sqr * std::pow(p_b_dot_x, 2) + p_b_sqr * std::pow(p_a_dot_x, 2) -
452  2 * p_a_dot_p_b * p_a_dot_x * p_b_dot_x) /
453  (std::pow(p_a_dot_p_b, 2) - p_a_sqr * p_b_sqr);
454  return b_sqr > 0.0 ? b_sqr : 0.0;
455 }
Here is the call graph for this function:

◆ mandelstam_s()

double smash::ScatterAction::mandelstam_s ( ) const

Determine the Mandelstam s variable,.

\[s = (p_a + p_b)^2\]

Equal to the square of CMS energy.

Returns
Mandelstam s

Definition at line 370 of file scatteraction.cc.

370 { return total_momentum().sqr(); }
FourVector total_momentum() const
Sum of 4-momenta of incoming particles.
Definition: action.h:389
double sqr() const
calculate the square of the vector (which is a scalar)
Definition: fourvector.h:460
Here is the call graph for this function:
Here is the caller graph for this function:

◆ relative_velocity()

double smash::ScatterAction::relative_velocity ( ) const

Get the relative velocity of the two incoming particles.

For a defintion see e.g. Seifert:2017oyb [57], eq. (5)

Returns
relative velocity.

Definition at line 384 of file scatteraction.cc.

384  {
385  const double m1 = incoming_particles()[0].effective_mass();
386  const double m2 = incoming_particles()[1].effective_mass();
387  const double m_s = mandelstam_s();
388  const double lamb = lambda_tilde(m_s, m1 * m1, m2 * m2);
389  return std::sqrt(lamb) / (2. * incoming_particles()[0].momentum().x0() *
390  incoming_particles()[1].momentum().x0());
391 }
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
Definition: action.cc:61
static double lambda_tilde(double a, double b, double c)
Little helper function that calculates the lambda function (sometimes written with a tilde to better ...
Definition: action.h:315
double mandelstam_s() const
Determine the Mandelstam s variable,.
Here is the call graph for this function:

◆ generate_final_state()

void smash::ScatterAction::generate_final_state ( )
overridevirtual

Generate the final-state of the scattering process.

Performs either elastic or inelastic scattering.

Exceptions
InvalidScatterAction

Implements smash::Action.

Reimplemented in smash::ScatterActionPhoton.

Definition at line 58 of file scatteraction.cc.

58  {
59  logg[LScatterAction].debug("Incoming particles: ", incoming_particles_);
60 
61  const CollisionBranch *proc = choose_channel<CollisionBranch>(
65  process_type_ = proc->get_type();
66  outgoing_particles_ = proc->particle_list();
67  partial_cross_section_ = proc->weight();
68 
69  logg[LScatterAction].debug("Chosen channel: ", process_type_,
71 
72  /* The production point of the new particles. */
73  FourVector middle_point = get_interaction_point();
74 
75  switch (process_type_) {
77  /* 2->2 elastic scattering */
80  break;
82  /* resonance formation */
85  break;
87  /* 2->2 inelastic scattering */
88  /* Sample the particle momenta in CM system. */
90  break;
94  /* 2->m scattering */
96  break;
108  break;
109  default:
110  throw InvalidScatterAction(
111  "ScatterAction::generate_final_state: Invalid process type " +
112  std::to_string(static_cast<int>(process_type_)) + " was requested. " +
113  "(PDGcode1=" + incoming_particles_[0].pdgcode().string() +
114  ", PDGcode2=" + incoming_particles_[1].pdgcode().string() + ")");
115  }
116 
117  const bool core_in_incoming =
118  std::any_of(incoming_particles_.begin(), incoming_particles_.end(),
119  [](const ParticleData &p) { return p.is_core(); });
120  for (ParticleData &new_particle : outgoing_particles_) {
121  // Boost to the computational frame
123  new_particle.boost_momentum(
125  }
126  /* Set positions of the outgoing particles */
127  if (proc->get_type() != ProcessType::Elastic) {
128  new_particle.set_4position(middle_point);
129  if (core_in_incoming) {
130  new_particle.fluidize();
131  }
132  if (new_particle.type().pdgcode().is_heavy_flavor()) {
133  // Particle weight is the product of incoming weights
134  const double perturbative_weight = std::accumulate(
135  incoming_particles_.begin(), incoming_particles_.end(), 1.0,
136  [](double w, const ParticleData &p) {
137  return w * p.perturbative_weight();
138  });
139  new_particle.set_perturbative_weight(perturbative_weight);
140  }
141  }
142  }
143 }
FourVector total_momentum_of_outgoing_particles() const
Calculate the total kinetic momentum of the outgoing particles.
Definition: action.cc:163
ParticleList outgoing_particles_
Initially this stores only the PDG codes of final-state particles.
Definition: action.h:363
FourVector get_interaction_point() const
Get the interaction point.
Definition: action.cc:71
ProcessType process_type_
type of process
Definition: action.h:372
void string_spin_interaction()
Perform spin interaction in string excitations.
void resonance_formation()
Perform a 2->1 resonance-formation process.
double partial_cross_section_
Partial cross-section to the chosen outgoing channel.
void two_to_many_scattering()
Perform an inelastic two-to-many-body scattering (more than 2)
void string_excitation()
Todo(ryu): document better - it is not really UrQMD-based, isn't it? Perform the UrQMD-based string e...
void elastic_scattering()
Perform an elastic two-body scattering, i.e. just exchange momentum.
void inelastic_scattering()
Perform an inelastic two-body scattering, i.e. new particles are formed.
void spin_interaction()
Perform spin interaction in binary interactions.
@ TwoToOne
See here for a short description.
@ StringHardSingleDiffractiveAX
See here for a short description.
@ StringSoftDoubleDiffractive
See here for a short description.
@ TwoToFive
See here for a short description.
@ StringSoftSingleDiffractiveXB
See here for a short description.
@ TwoToTwo
See here for a short description.
@ Elastic
See here for a short description.
@ TwoToFour
See here for a short description.
@ StringHardNonDiffractive
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.
@ StringHardSingleDiffractiveXB
See here for a short description.
@ StringHardDoubleDiffractive
See here for a short description.
@ TwoToThree
See here for a short description.
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Definition: stringify.cc:26
bool is_string_process(ProcessType p)
Check if a given process type is a string excitation.
Here is the call graph for this function:

◆ get_total_weight()

double smash::ScatterAction::get_total_weight ( ) const
overridevirtual

Get the total cross section of scattering particles.

Returns
total cross section.

Implements smash::Action.

Reimplemented in smash::ScatterActionPhoton.

Definition at line 351 of file scatteraction.cc.

351  {
353  incoming_particles_[0].xsec_scaling_factor() *
354  incoming_particles_[1].xsec_scaling_factor();
355 }

◆ get_partial_weight()

double smash::ScatterAction::get_partial_weight ( ) const
overridevirtual

Get the partial cross section of the chosen channel.

Returns
partial cross section.

Implements smash::Action.

Definition at line 357 of file scatteraction.cc.

357  {
358  return partial_cross_section_ * incoming_particles_[0].xsec_scaling_factor() *
359  incoming_particles_[1].xsec_scaling_factor();
360 }

◆ sample_angles()

void smash::ScatterAction::sample_angles ( std::pair< double, double >  masses,
double  kinetic_energy_cm 
)
overridevirtual

Sample final-state angles in a 2->2 collision (possibly anisotropic).

NN → NN: Choose angular distribution according to Cugnon parametrization, see Cugnon:1996kh [21].

NN → NΔ: Sample scattering angles in center-of-mass frame from an anisotropic angular distribution, using the same distribution as for elastic pp scattering, as suggested in Cugnon:1996kh [21].

NN → NR: Fit to HADES data, see Agakishiev:2014wqa [3].

Reimplemented from smash::Action.

Definition at line 513 of file scatteraction.cc.

514  {
516  // We potentially have more than two particles, so the following angular
517  // distributions don't work. Instead we just keep the angular
518  // distributions generated by string fragmentation.
519  return;
520  }
521  assert(outgoing_particles_.size() == 2);
522 
523  // NN scattering is anisotropic currently
524  const bool nn_scattering = incoming_particles_[0].type().is_nucleon() &&
525  incoming_particles_[1].type().is_nucleon();
526  /* Elastic process is anisotropic and
527  * the angular distribution is based on the NN elastic scattering. */
528  const bool el_scattering = process_type_ == ProcessType::Elastic;
529 
530  const double mass_in_a = incoming_particles_[0].effective_mass();
531  const double mass_in_b = incoming_particles_[1].effective_mass();
532 
533  ParticleData *p_a = &outgoing_particles_[0];
534  ParticleData *p_b = &outgoing_particles_[1];
535 
536  const double mass_a = masses.first;
537  const double mass_b = masses.second;
538 
539  const std::array<double, 2> t_range = get_t_range<double>(
540  kinetic_energy_cm, mass_in_a, mass_in_b, mass_a, mass_b);
541  Angles phitheta;
542  if (el_scattering && !isotropic_) {
543  /** NN → NN: Choose angular distribution according to Cugnon
544  * parametrization,
545  * see \iref{Cugnon:1996kh}. */
546  double mandelstam_s_new = 0.;
547  if (nn_scattering) {
548  mandelstam_s_new = mandelstam_s();
549  } else {
550  /* In the case of elastic collisions other than NN collisions,
551  * there is an ambiguity on how to get the lab-frame momentum (plab),
552  * since the incoming particles can have different masses.
553  * Right now, we first obtain the center-of-mass momentum
554  * of the collision (pcom_now).
555  * Then, the lab-frame momentum is evaluated from the mandelstam s,
556  * which yields the original center-of-mass momentum
557  * when nucleon mass is assumed. */
558  const double pcm_now = pCM_from_s(mandelstam_s(), mass_in_a, mass_in_b);
559  mandelstam_s_new =
560  4. * std::sqrt(pcm_now * pcm_now + nucleon_mass * nucleon_mass);
561  }
562  double bb, a, plab = plab_from_s(mandelstam_s_new);
563  if (nn_scattering &&
564  p_a->pdgcode().antiparticle_sign() ==
565  p_b->pdgcode().antiparticle_sign() &&
566  std::abs(p_a->type().charge() + p_b->type().charge()) == 1) {
567  // proton-neutron and antiproton-antineutron
568  bb = std::max(Cugnon_bnp(plab), really_small);
569  a = (plab < 0.8) ? 1. : 0.64 / (plab * plab);
570  } else {
571  /* all others including pp, nn and AQM elastic processes
572  * This is applied for all particle pairs, which are allowed to
573  * interact elastically. */
574  bb = std::max(Cugnon_bpp(plab), really_small);
575  a = 1.;
576  }
577  double t = random::expo(bb, t_range[0], t_range[1]);
578  if (random::canonical() > 1. / (1. + a)) {
579  t = t_range[0] + t_range[1] - t;
580  }
581  // determine scattering angles in center-of-mass frame
582  phitheta = Angles(2. * M_PI * random::canonical(),
583  1. - 2. * (t - t_range[0]) / (t_range[1] - t_range[0]));
584  } else if (nn_scattering && p_a->pdgcode().is_Delta() &&
585  p_b->pdgcode().is_nucleon() &&
586  p_a->pdgcode().antiparticle_sign() ==
587  p_b->pdgcode().antiparticle_sign() &&
588  !isotropic_) {
589  /** NN → NΔ: Sample scattering angles in center-of-mass frame from an
590  * anisotropic angular distribution, using the same distribution as for
591  * elastic pp scattering, as suggested in \iref{Cugnon:1996kh}. */
592  const double plab = plab_from_s(mandelstam_s());
593  const double bb = std::max(Cugnon_bpp(plab), really_small);
594  double t = random::expo(bb, t_range[0], t_range[1]);
595  if (random::canonical() > 0.5) {
596  t = t_range[0] + t_range[1] - t; // symmetrize
597  }
598  phitheta = Angles(2. * M_PI * random::canonical(),
599  1. - 2. * (t - t_range[0]) / (t_range[1] - t_range[0]));
600  } else if (nn_scattering && p_b->pdgcode().is_nucleon() && !isotropic_ &&
601  (p_a->type().is_Nstar() || p_a->type().is_Deltastar())) {
602  /** NN → NR: Fit to HADES data, see \iref{Agakishiev:2014wqa}. */
603  const std::array<double, 4> p{1.46434, 5.80311, -6.89358, 1.94302};
604  const double a = p[0] + mass_a * (p[1] + mass_a * (p[2] + mass_a * p[3]));
605  /* If the resonance is so heavy that the index "a" exceeds 30,
606  * the power function turns out to be too sharp. Take t directly to be
607  * t_0 in such a case. */
608  double t = t_range[0];
609  if (a < 30) {
610  t = random::power(-a, t_range[0], t_range[1]);
611  }
612  if (random::canonical() > 0.5) {
613  t = t_range[0] + t_range[1] - t; // symmetrize
614  }
615  phitheta = Angles(2. * M_PI * random::canonical(),
616  1. - 2. * (t - t_range[0]) / (t_range[1] - t_range[0]));
617  } else {
618  /* isotropic angular distribution */
619  phitheta.distribute_isotropically();
620  }
621 
622  ThreeVector pscatt = phitheta.threevec();
623  // 3-momentum of first incoming particle in center-of-mass frame
624  ThreeVector pcm =
625  incoming_particles_[0].momentum().lorentz_boost(beta_cm()).threevec();
626  pscatt.rotate_z_axis_to(pcm);
627 
628  // final-state CM momentum
629  const double p_f = pCM(kinetic_energy_cm, mass_a, mass_b);
630  if (!(p_f > 0.0)) {
631  logg[LScatterAction].warn("Particle: ", p_a->pdgcode(),
632  " radial momentum: ", p_f);
633  logg[LScatterAction].warn("Etot: ", kinetic_energy_cm, " m_a: ", mass_a,
634  " m_b: ", mass_b);
635  }
636  p_a->set_4momentum(mass_a, pscatt * p_f);
637  p_b->set_4momentum(mass_b, -pscatt * p_f);
638 
639  /* Debug message is printed before boost, so that p_a and p_b are
640  * the momenta in the center of mass frame and thus opposite to
641  * each other.*/
642  logg[LScatterAction].debug("p_a: ", *p_a, "\np_b: ", *p_b);
643 }
T power(T n, T xMin, T xMax)
Sample from a power-law probability density proportional to |x|^n.
Definition: random.h:229
T expo(T A, T x1, T x2)
Draws a random number x from an exponential distribution exp(A*x), where A is assumed to be positive,...
Definition: random.h:178
T canonical()
Definition: random.h:122
double plab_from_s(double mandelstam_s, double mass)
Convert Mandelstam-s to p_lab in a fixed-target collision.
Definition: kinematics.h:157
static double Cugnon_bnp(double plab)
Computes the B coefficients from the Cugnon parametrization of the angular distribution in elastic np...
T pCM(const T sqrts, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:79
constexpr double nucleon_mass
Nucleon mass in GeV.
Definition: constants.h:69
T pCM_from_s(const T s, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:66
static double Cugnon_bpp(double plab)
Computes the B coefficients from the Cugnon parametrization of the angular distribution in elastic pp...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_all_scatterings()

void smash::ScatterAction::add_all_scatterings ( const ScatterActionsFinderParameters finder_parameters)

Add all possible scattering subprocesses for this action object.

This can only be called once per ScatterAction instance.

Parameters
[in]finder_parametersparameters for collision finding.

Definition at line 145 of file scatteraction.cc.

146  {
147  if (were_processes_added_) {
148  logg[LScatterAction].fatal() << "Trying to add processes again.";
149  throw std::logic_error(
150  "add_all_scatterings should be called only once per ScatterAction "
151  "instance");
152  } else {
153  were_processes_added_ = true;
154  }
155 
156  // Prevent charm interactions if CharmRescattering::None is set
157  const PdgCode &pdg_a = incoming_particles_[0].type().pdgcode();
158  const PdgCode &pdg_b = incoming_particles_[1].type().pdgcode();
159  if (finder_parameters.charm_rescattering == CharmRescattering::None &&
160  (pdg_a.frac_charm() != 0 || pdg_b.frac_charm() != 0)) {
161  return;
162  }
163 
164  CrossSections xs(incoming_particles_, sqrt_s(),
166  CollisionBranchList processes =
167  xs.generate_collision_list(finder_parameters, string_process_);
168 
169  // Add various subprocesses.
170  add_collisions(std::move(processes));
171 
172  /* If the string processes are not triggered by a probability, then they
173  * always happen as long as the parametrized total cross section is larger
174  * than the sum of the cross sections of the non-string processes, and the
175  * square root s exceeds the threshold by at least 0.9 GeV. The cross section
176  * of the string processes are counted by taking the difference between the
177  * parametrized total and the sum of the non-strings. */
178  if (!finder_parameters.strings_with_probability &&
179  xs.string_probability(finder_parameters) > 0) {
180  const double xs_diff =
181  xs.high_energy(finder_parameters) - sum_of_partial_cross_sections_;
182  if (xs_diff > 0.) {
184  xs.string_excitation(xs_diff, string_process_, finder_parameters));
185  }
186  }
187 
188  // Prevent pseudoresonances for charmed hadrons in T-matrix approach
189  bool suppress_pseudoresonances_for_T_matrix_channels = false;
190  if (finder_parameters.charm_rescattering == CharmRescattering::T_Matrix &&
191  ((pdg_a.is_Dmeson() || pdg_b.is_Dmeson()) ||
192  (pdg_a.is_Dstar2007() || pdg_b.is_Dstar2007()))) {
193  if ((pdg_a.is_pion() || pdg_b.is_pion()) ||
194  (pdg_a.is_eta() || pdg_b.is_eta()) ||
195  (pdg_a.is_kaon() || pdg_b.is_kaon())) {
196  suppress_pseudoresonances_for_T_matrix_channels = true;
197  }
198  }
199 
200  ParticleTypePtr pseudoresonance =
201  try_find_pseudoresonance(finder_parameters.pseudoresonance_method,
202  finder_parameters.transition_high_energy);
203  if (pseudoresonance && finder_parameters.two_to_one &&
204  !suppress_pseudoresonances_for_T_matrix_channels) {
205  const double xs_total = is_total_parametrized_
207  : xs.high_energy(finder_parameters);
208  const double xs_gap = xs_total - sum_of_partial_cross_sections_;
209  /* The pseudo-resonance is only created if there is a (positive) cross
210  * section gap */
211  if (xs_gap > really_small) {
212  auto pseudoresonance_branch = std::make_unique<CollisionBranch>(
213  *pseudoresonance, xs_gap, ProcessType::TwoToOne);
214  add_collision(std::move(pseudoresonance_branch));
215  logg[LScatterAction].debug()
216  << "Pseudoresonance between " << incoming_particles_[0].type().name()
217  << " and " << incoming_particles_[1].type().name() << " is "
218  << pseudoresonance->name() << " with cross section " << xs_gap
219  << " mb.";
220  }
221  }
222  // Rescale the branches so that their sum matches the parametrization
225  }
226 }
std::pair< FourVector, FourVector > get_potential_at_interaction_point() const
Get the skyrme and asymmetry potential at the interaction point.
Definition: action.cc:115
double sqrt_s() const
Determine the total energy in the center-of-mass frame [GeV].
Definition: action.h:271
void rescale_outgoing_branches()
Loop over the possible branches and rescales their weight according to the desired total cross sectio...
void add_collision(CollisionBranchPtr p)
Add a new collision channel.
StringProcess * string_process_
Pointer to interface class for strings.
void add_collisions(CollisionBranchList pv)
Add several new collision channels at once.
bool were_processes_added_
Lock for calling add_all_scatterings only once.
ParticleTypePtr try_find_pseudoresonance(const PseudoResonance method, const StringTransitionParameters &transition) const
Try to find a pseudo-resonance that can be created from the incoming particles using a given method.
@ T_Matrix
Charm interactions via T-matrix approach.
@ None
Disable charm interactions.
Here is the call graph for this function:

◆ set_parametrized_total_cross_section()

void smash::ScatterAction::set_parametrized_total_cross_section ( const ScatterActionsFinderParameters finder_parameters)

Given the incoming particles, assigns the correct parametrization of the total cross section.

Parameters
[in]finder_parametersParameters for collision finding.

Definition at line 334 of file scatteraction.cc.

335  {
336  CrossSections xs(incoming_particles_, sqrt_s(),
338 
341  xs.parametrized_total(finder_parameters);
342  } else {
343  logg[LScatterAction].fatal()
344  << "Trying to parametrize total cross section when it shouldn't be.";
345  throw std::logic_error(
346  "This function can only be called on ScatterAction objects with "
347  "parametrized cross section.");
348  }
349 }
Here is the call graph for this function:

◆ collision_channels()

const CollisionBranchList& smash::ScatterAction::collision_channels ( )
inline

Get list of possible collision channels.

Returns
list of possible collision channels.

Definition at line 167 of file scatteraction.h.

167  {
168  return collision_channels_;
169  }

◆ set_string_interface()

void smash::ScatterAction::set_string_interface ( StringProcess str_proc)
inline

Set the StringProcess object to be used.

The StringProcess object is used to handle string excitation and to generate final state particles.

Parameters
[in]str_procString process object to be used.

Definition at line 187 of file scatteraction.h.

187  {
188  string_process_ = str_proc;
189  }

◆ cross_section()

virtual double smash::ScatterAction::cross_section ( ) const
inlinevirtual

Get the total cross section of the scattering particles, either from a parametrization, or from the sum of partials.

Returns
total cross section.

Definition at line 197 of file scatteraction.h.

197  {
200  }
202  }

◆ cm_momentum()

double smash::ScatterAction::cm_momentum ( ) const
protected

Get the momentum of the center of mass of the incoming particles in the calculation frame.

Returns
center of mass momentum.

Definition at line 372 of file scatteraction.cc.

372  {
373  const double m1 = incoming_particles_[0].effective_mass();
374  const double m2 = incoming_particles_[1].effective_mass();
375  return pCM(sqrt_s(), m1, m2);
376 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_momentum_squared()

double smash::ScatterAction::cm_momentum_squared ( ) const
protected

Get the squared momentum of the center of mass of the incoming particles in the calculation frame.

Returns
center of mass momentum squared.

Definition at line 378 of file scatteraction.cc.

378  {
379  const double m1 = incoming_particles_[0].effective_mass();
380  const double m2 = incoming_particles_[1].effective_mass();
381  return pCM_sqr(sqrt_s(), m1, m2);
382 }
T pCM_sqr(const T sqrts, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:91
Here is the call graph for this function:

◆ beta_cm()

ThreeVector smash::ScatterAction::beta_cm ( ) const
protected

Get the velocity of the center of mass of the scattering/incoming particles in the calculation frame.

Note: Do not use this function to boost the outgoing particles. Use total_momentum_of_outgoing_particles(), which corrects for the effect of potentials on intial and final state.

Returns
boost velocity between center of mass and calculation frame.

Definition at line 362 of file scatteraction.cc.

362  {
363  return total_momentum().velocity();
364 }
ThreeVector velocity() const
Get the velocity (3-vector divided by zero component).
Definition: fourvector.h:333
Here is the call graph for this function:
Here is the caller graph for this function:

◆ gamma_cm()

double smash::ScatterAction::gamma_cm ( ) const
protected

Get the gamma factor corresponding to a boost to the center of mass frame of the colliding particles.

Returns
gamma factor.

Definition at line 366 of file scatteraction.cc.

366  {
367  return (1. / std::sqrt(1.0 - beta_cm().sqr()));
368 }
Here is the call graph for this function:

◆ elastic_scattering()

void smash::ScatterAction::elastic_scattering ( )
protected

Perform an elastic two-body scattering, i.e. just exchange momentum.

Definition at line 645 of file scatteraction.cc.

645  {
646  // copy initial particles into final state
649  // resample momenta
650  sample_angles({outgoing_particles_[0].effective_mass(),
651  outgoing_particles_[1].effective_mass()},
652  sqrt_s());
653 }
void sample_angles(std::pair< double, double > masses, double kinetic_energy_cm) override
Sample final-state angles in a 2->2 collision (possibly anisotropic).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ inelastic_scattering()

void smash::ScatterAction::inelastic_scattering ( )
protected

Perform an inelastic two-body scattering, i.e. new particles are formed.

Definition at line 655 of file scatteraction.cc.

655  {
656  // create new particles
661  }
662 }
virtual void sample_2body_phasespace()
Sample the full 2-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
Definition: action.cc:308
void assign_formation_time_to_outgoing_particles()
Assign the formation time to the outgoing particles.
Definition: action.cc:194
void assign_unpolarized_spin_vector_to_outgoing_particles()
Assign an unpolarized spin vector to all outgoing particles.
Definition: action.cc:339
@ Off
No spin interactions.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ two_to_many_scattering()

void smash::ScatterAction::two_to_many_scattering ( )
protected

Perform an inelastic two-to-many-body scattering (more than 2)

Definition at line 664 of file scatteraction.cc.

664  {
669  }
670  logg[LScatterAction].debug("2->", outgoing_particles_.size(),
671  " scattering:", incoming_particles_, " -> ",
673 }
virtual void sample_manybody_phasespace()
Sample the full n-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
Definition: action.cc:319
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_string_final_state()

void smash::ScatterAction::create_string_final_state ( )
protected

Creates the final states for string-processes after they are performed.

Definition at line 700 of file scatteraction.cc.

700  {
703  /* Check momentum difference for debugging */
704  FourVector out_mom;
705  for (ParticleData data : outgoing_particles_) {
706  out_mom += data.momentum();
707  }
708  logg[LPythia].debug("Incoming momenta string:", total_momentum());
709  logg[LPythia].debug("Outgoing momenta string:", out_mom);
710 }
ParticleList get_final_state()
static constexpr int LPythia
Definition: stringprocess.h:27
Here is the call graph for this function:
Here is the caller graph for this function:

◆ string_excitation()

void smash::ScatterAction::string_excitation ( )
protected

Todo(ryu): document better - it is not really UrQMD-based, isn't it? Perform the UrQMD-based string excitation and decay.

Definition at line 716 of file scatteraction.cc.

716  {
717  assert(incoming_particles_.size() == 2);
718  // Disable floating point exception trap for Pythia
719  {
720  DisableFloatTraps guard;
721  /* initialize the string_process_ object for this particular collision */
723  /* implement collision */
724  bool success = false;
725  int ntry = 0;
726  const int ntry_max = 10000;
727  while (!success && ntry < ntry_max) {
728  ntry++;
729  success = string_process_->next(process_type_);
730  }
731 
732  if (ntry == ntry_max) {
733  /* If pythia fails to form a string, it is usually because the energy
734  * is not large enough. In this case, annihilation is then enforced. If
735  * this process still does not not produce any results, it defaults to
736  * an elastic collision. */
737  bool success_newtry = false;
738 
739  /* Check if the initial state is a baryon-antibaryon state.*/
740  PdgCode part1 = incoming_particles_[0].pdgcode(),
741  part2 = incoming_particles_[1].pdgcode();
742  bool is_BBbar_Pair = (part1.baryon_number() != 0) &&
743  (part1.baryon_number() == -part2.baryon_number());
744 
745  /* Decide on the new process .*/
746  if (is_BBbar_Pair) {
748  } else {
750  }
751  /* Perform the new process*/
752  int ntry_new = 0;
753  while (!success_newtry && ntry_new < ntry_max) {
754  ntry_new++;
755  success_newtry = string_process_->next(process_type_);
756  }
757 
758  if (success_newtry) {
760  }
761 
762  if (!success_newtry) {
763  /* If annihilation fails:
764  * Particles are normally added after process selection for
765  * strings, outgoing_particles is still uninitialized, and memory
766  * needs to be allocated. We also shift the process_type_ to elastic
767  * so that sample_angles does a proper treatment. */
768  outgoing_particles_.reserve(2);
769  outgoing_particles_.push_back(ParticleData{incoming_particles_[0]});
770  outgoing_particles_.push_back(ParticleData{incoming_particles_[1]});
773  }
774  } else {
776  }
777  }
778 }
const double time_of_execution_
Time at which the action is supposed to be performed (absolute time in the lab frame in fm).
Definition: action.h:369
void create_string_final_state()
Creates the final states for string-processes after they are performed.
bool next(ProcessType type)
Generate the next string process for a given process type.
void init(const ParticleList &incoming, double tcoll)
initialization feed intial particles, time of collision and gamma factor of the center of mass.
@ FailedString
See here for a short description.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ spin_interaction()

void smash::ScatterAction::spin_interaction ( )
protected

Perform spin interaction in binary interactions.

At the moment, we include a spin-flip in the y component of elastic scatterings if enabled.

Definition at line 790 of file scatteraction.cc.

790  {
792  /* 2->2 elastic scattering */
794  // Final boost to the outgoing particle momenta
797  }
798 
799  /* 2->1 resonance formation */
801  /*
802  * @brief Λ+π → Σ* resonance formation with Λ–spin bookkeeping.
803  *
804  * We do not simulate a direct inelastic Λ+π scattering; instead we form a
805  * Σ* resonance and let it decay later. To preserve Λ polarization per
806  * arXiv:2404.15890v2, we treat the Σ* spin vector as a proxy for the
807  * would-be outgoing Λ spin: at formation, we set the Σ* spin to the
808  * incoming Λ spin and apply a possible spin flip according to the
809  * Λ–flip/non-flip fractions extracted from the paper. On Σ* → Λ+π decay,
810  * the Σ* spin vector is copied to the Λ, thus transporting Λ polarization
811  * through the resonance stage.
812  */
813  // Identify if the outgoing resonance is a Σ*
814  if (outgoing_particles_[0].is_sigmastar()) {
815  // Check that one of the incoming particles is a Λ and the other a π
816  const bool has_lambda = incoming_particles_[0].pdgcode().is_Lambda() ||
817  incoming_particles_[1].pdgcode().is_Lambda();
818  const bool has_pion = incoming_particles_[0].is_pion() ||
819  incoming_particles_[1].is_pion();
820  if (has_lambda && has_pion) {
821  auto &lambda = (incoming_particles_[0].pdgcode().is_Lambda())
823  : incoming_particles_[1];
824  auto &sigma_star = outgoing_particles_[0];
825 
826  // Perform spin flip with probability of 2/9
827  int random_int = random::uniform_int(1, 9);
828  FourVector final_spin_vector = lambda.spin_vector();
829 
830  if (random_int <= 7) {
831  // No spin flip
832  final_spin_vector = final_spin_vector.lorentz_boost(
833  outgoing_particles_[0].velocity());
834  outgoing_particles_[0].set_spin_vector(final_spin_vector);
835  } else {
836  // Spin flip in Lambda rest frame
837  ThreeVector lambda_velocity = lambda.velocity();
838  final_spin_vector =
839  final_spin_vector.lorentz_boost(lambda_velocity);
840 
841  // Flip the spatial spin vector components
842  final_spin_vector[1] = -final_spin_vector[1];
843  final_spin_vector[2] = -final_spin_vector[2];
844  final_spin_vector[3] = -final_spin_vector[3];
845 
846  // Boost back to computational frame and to Sigma* frame
847  final_spin_vector =
848  final_spin_vector.lorentz_boost(-lambda_velocity);
849  final_spin_vector =
850  final_spin_vector.lorentz_boost(sigma_star.velocity());
851  sigma_star.set_spin_vector(final_spin_vector);
852  }
853  }
854  }
855  }
856  }
857 }
T uniform_int(T min, T max)
Definition: random.h:106
static void boost_spin_vectors_after_elastic_scattering(ParticleData &outgoing_particle_a, ParticleData &outgoing_particle_b)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ string_spin_interaction()

void smash::ScatterAction::string_spin_interaction ( )
protected

Perform spin interaction in string excitations.

At the moment, we assign unpolarized spin vectors to the outgoing particles, unless the process is single diffractive, in which case we copy the spin vector of the elastically scattered particle to the corresponding outgoing particle.

Definition at line 859 of file scatteraction.cc.

859  {
860  // Check if spin interaction is disabled
862  return;
863  }
864  const bool is_AB_to_AX =
866  const bool is_AB_to_XB =
868 
869  /* This logic relies on the assumption that the surviving hadron is
870  * always appended as the final element in the outgoing particle list.
871  * This ordering is guaranteed by StringProcess::next_SDiff(bool
872  * is_AB_to_AX). If that implementation changes, the behavior here must
873  * be re-evaluated. */
874  if (is_AB_to_AX || is_AB_to_XB) {
875  const std::size_t idx_hadron_in = is_AB_to_AX ? 0 : 1;
876 
877  // Boost spin vector of surviving hadron to outgoing frame
878  const FourVector final_spin_vector =
879  incoming_particles_[idx_hadron_in].spin_vector().lorentz_boost(
880  outgoing_particles_.back().velocity());
881 
882  outgoing_particles_.back().set_spin_vector(final_spin_vector);
883 
884  /* Set unpolarized spin vector for all newly created particles (all but
885  * the last one) */
886  for (auto it = outgoing_particles_.begin();
887  it != outgoing_particles_.end() - 1; ++it) {
888  it->set_unpolarized_spin_vector();
889  }
890  } else {
891  for (auto &particle : outgoing_particles_) {
892  particle.set_unpolarized_spin_vector();
893  }
894  }
895 }
Here is the caller graph for this function:

◆ is_elastic()

bool smash::ScatterAction::is_elastic ( ) const
private

Check if the scattering is elastic.

Returns
whether the scattering is elastic.

◆ resonance_formation()

void smash::ScatterAction::resonance_formation ( )
private

Perform a 2->1 resonance-formation process.

Exceptions
InvalidResonanceFormation

Definition at line 675 of file scatteraction.cc.

675  {
676  if (outgoing_particles_.size() != 1) {
677  std::string s =
678  "resonance_formation: "
679  "Incorrect number of particles in final state: ";
680  s += std::to_string(outgoing_particles_.size()) + " (";
681  s += incoming_particles_[0].pdgcode().string() + " + ";
682  s += incoming_particles_[1].pdgcode().string() + ")";
683  throw InvalidResonanceFormation(s);
684  }
685  // Set the momentum of the formed resonance in its rest frame.
686  outgoing_particles_[0].set_4momentum(
687  total_momentum_of_outgoing_particles().abs(), 0., 0., 0.);
691  }
692  /* this momentum is evaluated in the computational frame. */
693  logg[LScatterAction].debug("Momentum of the new particle: ",
694  outgoing_particles_[0].momentum());
695 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rescale_outgoing_branches()

void smash::ScatterAction::rescale_outgoing_branches ( )
private

Loop over the possible branches and rescales their weight according to the desired total cross section.

In case the current sum of partials is close to 0, a warning is issued as this would not happen in an usual run, and an elastic process is added to match the total.

Definition at line 228 of file scatteraction.cc.

228  {
229  if (!were_processes_added_) {
230  logg[LScatterAction].fatal()
231  << "Trying to rescale branches before adding processes.";
232  throw std::logic_error(
233  "This function can only be called after having added processes.");
234  }
236  const ParticleTypePtr type_a = &incoming_particles_[0].type();
237  const ParticleTypePtr type_b = &incoming_particles_[1].type();
238  // This is a std::set instead of std::pair because the order of particles
239  // does not matter here
240  const std::set<ParticleTypePtr> pair{type_a, type_b};
241  if (!warned_no_rescaling_available.count(pair)) {
242  logg[LScatterAction].warn()
243  << "Total cross section between " << type_a->name() << " and "
244  << type_b->name() << " is roughly zero at sqrt(s) = " << sqrt_s()
245  << " GeV, and no rescaling to match the parametrized value will be "
246  "done.\nAn elastic process will be added, instead, to match the "
247  "total cross section.\nFor this pair of particles, this warning "
248  "will be subsequently suppressed.";
249  warned_no_rescaling_available.insert(pair);
250  }
251  auto elastic_branch = std::make_unique<CollisionBranch>(
252  *type_a, *type_b, *parametrized_total_cross_section_,
254  add_collision(std::move(elastic_branch));
255  } else {
256  const double reweight =
258  logg[LScatterAction].debug("Reweighting ", sum_of_partial_cross_sections_,
260  for (auto &proc : collision_channels_) {
261  proc->set_weight(proc->weight() * reweight);
262  }
263  }
264 }
static std::set< std::set< ParticleTypePtr > > warned_no_rescaling_available
Warn about zero cross section only once per particle type pair.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_find_pseudoresonance()

ParticleTypePtr smash::ScatterAction::try_find_pseudoresonance ( const PseudoResonance  method,
const StringTransitionParameters transition 
) const
private

Try to find a pseudo-resonance that can be created from the incoming particles using a given method.

Parameters
[in]methodused to select the pseudo-resonance among possible candidates. See user guide description for more information.
[in]transitionparameters for the string transition region, which are also used to determine when a pseudo-resonance can be created.
Returns
the appropriate pseudo-resonance, if there is any, or an invalid pointer otherwise.

Definition at line 266 of file scatteraction.cc.

268  {
269  const ParticleTypePtr type_a = &incoming_particles_[0].type();
270  const ParticleTypePtr type_b = &incoming_particles_[1].type();
271  const double desired_mass = sqrt_s();
272 
273  double string_offset = 0.5 * transition.sqrts_add_lower;
274  const bool nucleon_and_pion = (type_a->is_nucleon() && type_b->is_pion()) ||
275  (type_a->is_pion() && type_b->is_nucleon());
276  const bool two_nucleons = type_a->is_nucleon() && type_b->is_nucleon();
277  const bool two_pions = type_a->is_pion() && type_b->is_pion();
278  const bool nucleon_and_kaon = (type_a->is_nucleon() && type_b->is_kaon()) ||
279  (type_a->is_kaon() && type_b->is_nucleon());
280  if (nucleon_and_pion) {
281  string_offset = transition.sqrts_range_Npi.first - pion_mass - nucleon_mass;
282  } else if (two_nucleons) {
283  string_offset = transition.sqrts_range_NN.first - 2 * nucleon_mass;
284  } else if (two_pions) {
285  string_offset = transition.pipi_offset;
286  } else if (nucleon_and_kaon) {
287  string_offset = transition.KN_offset;
288  }
289  /*
290  * Artificial cutoff to create a pseudo-resonance only close to the string
291  * transition, where data or first-principle models are unhelpful
292  */
293  if (desired_mass < incoming_particles_[0].effective_mass() +
294  incoming_particles_[1].effective_mass() +
295  string_offset) {
296  return {};
297  }
298 
299  if (method == PseudoResonance::None) {
300  return {};
301  } else if (method == PseudoResonance::LargestFromUnstable ||
303  if (type_a->is_stable() && type_b->is_stable()) {
304  return {};
305  }
306  }
307 
308  // If this list is empty, there are no possible pseudo-resonances.
309  ParticleTypePtrList list = list_possible_resonances(type_a, type_b);
310  if (std::empty(list)) {
311  return {};
312  }
313 
314  if (method == PseudoResonance::Largest ||
316  auto largest = *std::max_element(list.begin(), list.end(),
317  [](ParticleTypePtr a, ParticleTypePtr b) {
318  return a->mass() < b->mass();
319  });
320  return largest;
321  } else if (method == PseudoResonance::Closest ||
323  auto comparison = [&desired_mass](ParticleTypePtr a, ParticleTypePtr b) {
324  return std::abs(a->mass() - desired_mass) <
325  std::abs(b->mass() - desired_mass);
326  };
327  auto closest = *std::min_element(list.begin(), list.end(), comparison);
328  return closest;
329  } else {
330  throw std::logic_error("Unknown method for selecting pseudoresonance.");
331  }
332 }
@ Closest
Resonance with the pole mass closest from the invariant mass of incoming particles for all processes.
@ ClosestFromUnstable
Closest resonance for a given mass from processes with at least one resonance in the incoming particl...
@ None
No pseudo-resonance is created.
@ LargestFromUnstable
Heaviest possible resonance from processes with at least one resonance in the incoming particles.
@ Largest
Resonance of largest mass for all processes.
ParticleTypePtrList list_possible_resonances(const ParticleTypePtr type_a, const ParticleTypePtr type_b)
Lists the possible resonances that decay into two particles.
constexpr double pion_mass
Pion mass in GeV.
Definition: constants.h:76
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ collision_channels_

CollisionBranchList smash::ScatterAction::collision_channels_
protected

List of possible collisions.

Definition at line 277 of file scatteraction.h.

◆ sum_of_partial_cross_sections_

double smash::ScatterAction::sum_of_partial_cross_sections_
protected

Current sum of partial hadronic cross sections.

Definition at line 280 of file scatteraction.h.

◆ partial_cross_section_

double smash::ScatterAction::partial_cross_section_
protected

Partial cross-section to the chosen outgoing channel.

Definition at line 283 of file scatteraction.h.

◆ isotropic_

bool smash::ScatterAction::isotropic_ = false
protected

Do this collision isotropically?

Definition at line 286 of file scatteraction.h.

◆ string_formation_time_

double smash::ScatterAction::string_formation_time_ = 1.0
protected

Time fragments take to be fully formed in hard string excitation.

Definition at line 289 of file scatteraction.h.

◆ string_process_

StringProcess* smash::ScatterAction::string_process_ = nullptr
private

Pointer to interface class for strings.

Definition at line 329 of file scatteraction.h.

◆ is_total_parametrized_

bool smash::ScatterAction::is_total_parametrized_ = false
private

Whether the total cross section is parametrized.

Definition at line 332 of file scatteraction.h.

◆ parametrized_total_cross_section_

std::optional<double> smash::ScatterAction::parametrized_total_cross_section_ = std::nullopt
private

If cross section is parametrized, store the value.

Definition at line 335 of file scatteraction.h.

◆ spin_interaction_type_

SpinInteractionType smash::ScatterAction::spin_interaction_type_ = SpinInteractionType::Off
private

What kind of spin interaction to use.

Definition at line 338 of file scatteraction.h.

◆ were_processes_added_

bool smash::ScatterAction::were_processes_added_ = false
private

Lock for calling add_all_scatterings only once.

Definition at line 341 of file scatteraction.h.

◆ warned_no_rescaling_available

std::set<std::set<ParticleTypePtr> > smash::ScatterAction::warned_no_rescaling_available {}
inlinestaticprivate

Warn about zero cross section only once per particle type pair.

Definition at line 345 of file scatteraction.h.


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