Version: SMASH-3.3
smash::ScatterActionsFinder Class Reference

#include <scatteractionsfinder.h>

A simple scatter finder: Just loops through all particles and checks each pair for a collision.

It supports two collision criteria: a geometric and stochastic criterion.

Definition at line 31 of file scatteractionsfinder.h.

Inheritance diagram for smash::ScatterActionsFinder:
smash::ActionFinderInterface

Public Member Functions

 ScatterActionsFinder (Configuration &config, const ExperimentParameters &parameters)
 Constructor of the finder with the given parameters. More...
 
double collision_time (const ParticleData &p1, const ParticleData &p2, double dt, const std::vector< FourVector > &beam_momentum) const
 Determine the collision time of the two particles. More...
 
ActionList find_actions_in_cell (const ParticleList &search_list, double dt, const double gcell_vol, const std::vector< FourVector > &beam_momentum) const override
 Search for all the possible collisions within one cell. More...
 
ActionList find_actions_with_neighbors (const ParticleList &search_list, const ParticleList &neighbors_list, double dt, const std::vector< FourVector > &beam_momentum) const override
 Search for all the possible collisions among the neighboring cells. More...
 
ActionList find_actions_with_surrounding_particles (const ParticleList &search_list, const Particles &surrounding_list, double dt, const std::vector< FourVector > &beam_momentum) const override
 Search for all the possible secondary collisions between the outgoing particles and the rest. More...
 
ActionList find_final_actions (const Particles &) const override
 No scatterings should be found when the event is over. More...
 
bool is_constant_elastic_isotropic () const
 If there is only one particle sort, no decays (only elastic scatterings are possible), scatterings are isotropic and cross-section fixed to elastic_parameter_ independently on momenta, then maximal cross-section is elastic_parameter_. More...
 
double max_transverse_distance_sqr (int testparticles) const
 The maximal distance over which particles can interact in case of the geometric criterion, related to the number of test particles and the maximal cross section. More...
 
void dump_reactions () const
 Prints out all the 2-> n (n > 1) reactions with non-zero cross-sections between all possible pairs of particle types. More...
 
void dump_cross_sections (const ParticleType &a, const ParticleType &b, double m_a, double m_b, bool final_state, std::vector< double > &plab) const
 Print out partial cross-sections of all processes that can occur in the collision of a(mass = m_a) and b(mass = m_b). More...
 
StringProcessget_process_string_ptr ()
 
- Public Member Functions inherited from smash::ActionFinderInterface
virtual ~ActionFinderInterface ()=default
 

Private Member Functions

ActionPtr check_collision_two_part (const ParticleData &data_a, const ParticleData &data_b, double dt, const std::vector< FourVector > &beam_momentum={}, const double gcell_vol=0.0) const
 Check for a single pair of particles (id_a, id_b) if a collision will happen in the next timestep and create a corresponding Action object in that case. More...
 
ActionPtr check_collision_multi_part (const ParticleList &plist, double dt, const double gcell_vol) const
 Check for multiple i.e. More...
 

Private Attributes

ScatterActionsFinderParameters finder_parameters_
 Struct collecting several parameters. More...
 
std::unique_ptr< StringProcessstring_process_interface_
 Class that deals with strings, interfacing Pythia. More...
 
const bool isotropic_
 Do all collisions isotropically. More...
 
const double box_length_
 Box length: needed to determine coordinates of collision correctly in case of collision through the wall. More...
 
const double string_formation_time_
 Parameter for formation time. More...
 

Constructor & Destructor Documentation

◆ ScatterActionsFinder()

smash::ScatterActionsFinder::ScatterActionsFinder ( Configuration config,
const ExperimentParameters parameters 
)

Constructor of the finder with the given parameters.

Parameters
[in,out]configConfiguration of smash from which we take: 1) A global elastic cross section [mb]. It will be used regardless of the species of the colliding particles. It won't be used if the value is negative. 2) An option determining whether all the scatterings are isotropic 3) Parameters of the string process
[in]parametersStruct of parameters determining whether to exclude some certain types of scatterings and switching among the methods to treat with the NNbar collisions.

Definition at line 34 of file scatteractionsfinder.cc.

36  : finder_parameters_(config, parameters),
38  box_length_(parameters.box_length),
42  logg[LFindScatter].info(
43  "Constant elastic isotropic cross-section mode:", " using ",
44  finder_parameters_.elastic_parameter, " mb as maximal cross-section.");
45  }
48  throw std::invalid_argument(
49  "Multi-body reactions (like e.g. 3->1 or 3->2) are only possible with "
50  "the stochastic "
51  "collision "
52  "criterion. Change your config accordingly.");
53  }
54 
57  1 &&
59  .included_2to2[IncludedReactions::PiDeuteron_to_pidprime] == 1 ||
61  .included_2to2[IncludedReactions::NDeuteron_to_Ndprime] == 1)) {
62  throw std::invalid_argument(
63  "To prevent double counting it is not possible to enable deuteron 3->2 "
64  "reactions\nand reactions involving the d' at the same time\ni.e. to "
65  "include \"Deuteron_3to2\" in `Multi_Particle_Reactions` and\n "
66  "\"PiDeuteron_to_pidprime\" "
67  "or \"NDeuteron_to_Ndprime\" in `Included_2to2` at the same time.\n"
68  "Change your config accordingly.");
69  }
70 
73  1 &&
75  throw std::invalid_argument(
76  "Do not use the d' resonance and enable \"Deuteron_3to2\" "
77  "`Multi_Particle_Reactions` at the same time. Either use the direct "
78  "3-to-2 reactions or the d' together with \"PiDeuteron_to_pidprime\" "
79  "and \"NDeuteron_to_Ndprime\" in `Included_2to2`. Otherwise the "
80  "deuteron 3-to-2 reactions would be double counted.");
81  }
82 
86  1) ||
89  1 &&
91  throw std::invalid_argument(
92  "In order to conserve detailed balance, when \"NNbar_5to2\" is "
93  "included in\n`Multi_Particle_Reactions`, the `NNbarTreatment` has to "
94  "be set to \"two to five\" and vice versa.");
95  }
96 
99  throw std::invalid_argument(
100  "'NNbar' has to be in the list of allowed 2 to 2 processes "
101  "to enable annihilation to go through resonances");
102  }
103 
105  string_process_interface_ = std::make_unique<StringProcess>(
126  parameters.use_monash_tune_default.value()));
127  }
128 }
static const ParticleTypePtr try_find(PdgCode pdgcode)
Returns the ParticleTypePtr for the given pdgcode.
Definition: particletype.cc:89
const ReactionsBitSet included_2to2
List of included 2<->2 reactions.
const double elastic_parameter
Elastic cross section parameter (in mb).
const bool strings_switch
Indicates whether string fragmentation is switched on.
const MultiParticleReactionsBitSet included_multi
List of included multi-particle reactions.
const NNbarTreatment nnbar_treatment
Switch for NNbar reactions.
const CollisionCriterion coll_crit
Specifies which collision criterion is used.
ScatterActionsFinderParameters finder_parameters_
Struct collecting several parameters.
const bool isotropic_
Do all collisions isotropically.
const double string_formation_time_
Parameter for formation time.
std::unique_ptr< StringProcess > string_process_interface_
Class that deals with strings, interfacing Pythia.
bool is_constant_elastic_isotropic() const
If there is only one particle sort, no decays (only elastic scatterings are possible),...
const double box_length_
Box length: needed to determine coordinates of collision correctly in case of collision through the w...
@ TwoToFive
Directly create 5 pions, use with multi-particle reactions.
@ Resonances
Use intermediate Resonances.
@ NNbar_5to2
@ Deuteron_3to2
@ Stochastic
Stochastic Criteiron.
@ PiDeuteron_to_pidprime
@ NDeuteron_to_Ndprime
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:40
constexpr int64_t dprime
Deuteron-prime resonance.
static constexpr int LFindScatter
static const Key< double > collTerm_stringParam_probabilityPToDUU
See user guide description for more information.
Definition: input_keys.h:2959
static const Key< double > collTerm_stringParam_formationTime
See user guide description for more information.
Definition: input_keys.h:2843
static const Key< bool > collTerm_stringParam_useMonashTune
See user guide description for more information.
Definition: input_keys.h:3112
static const Key< double > collTerm_stringParam_sigmaPerp
See user guide description for more information.
Definition: input_keys.h:2994
static const Key< double > collTerm_stringParam_gluonPMin
See user guide description for more information.
Definition: input_keys.h:2870
static const Key< double > collTerm_stringParam_stringZALeading
See user guide description for more information.
Definition: input_keys.h:3067
static const Key< bool > collTerm_stringParam_mDependentFormationTimes
See user guide description for more information.
Definition: input_keys.h:2884
static const Key< double > collTerm_stringParam_diquarkSuppression
See user guide description for more information.
Definition: input_keys.h:2818
static const Key< double > collTerm_stringParam_formTimeFactor
See user guide description for more information.
Definition: input_keys.h:2831
static const Key< double > collTerm_stringParam_quarkAlpha
See user guide description for more information.
Definition: input_keys.h:2899
static const Key< double > collTerm_stringParam_stringZA
See user guide description for more information.
Definition: input_keys.h:3053
static const Key< double > collTerm_stringParam_strangeSuppression
See user guide description for more information.
Definition: input_keys.h:3012
static const Key< double > collTerm_stringParam_stringSigmaT
See user guide description for more information.
Definition: input_keys.h:3025
static const Key< double > collTerm_stringParam_stringZB
See user guide description for more information.
Definition: input_keys.h:3080
static const Key< double > collTerm_stringParam_quarkBeta
See user guide description for more information.
Definition: input_keys.h:2912
static const Key< double > collTerm_stringParam_popcornRate
See user guide description for more information.
Definition: input_keys.h:2927
static const Key< bool > collTerm_isotropic
See user guide description for more information.
Definition: input_keys.h:2340
static const Key< double > collTerm_stringParam_stringZBLeading
See user guide description for more information.
Definition: input_keys.h:3095
static const Key< double > collTerm_stringParam_stringTension
See user guide description for more information.
Definition: input_keys.h:3040
static const Key< double > collTerm_stringParam_gluonBeta
See user guide description for more information.
Definition: input_keys.h:2856
static const Key< bool > collTerm_stringParam_separateFragmentBaryon
See user guide description for more information.
Definition: input_keys.h:2974

Member Function Documentation

◆ collision_time()

double smash::ScatterActionsFinder::collision_time ( const ParticleData p1,
const ParticleData p2,
double  dt,
const std::vector< FourVector > &  beam_momentum 
) const
inline

Determine the collision time of the two particles.

Time of the closest approach is taken as collision time, if the geometric collision criterion is used. For stochastic criterion the time is distributed uniformly within the timestep.

Parameters
[in]p1First incoming particle
[in]p2Second incoming particle
[in]dtThe maximum time interval at the current time step [fm]
[in]beam_momentum[GeV] List of beam momenta for each particle; only necessary for frozen Fermi motion
Returns
How long does it take for the two incoming particles to propagate before scattering [fm]. It's set equal to -1 if the two particles are not moving relative to each other.

JAM collision times from the closest approach in the two-particle center-of-mass-framem, see Hirano:2012yy [28] (5.13) and (5.14). The scatteraction is performed at the mean of these two times.

UrQMD collision time in computational frame, see Bass:1998ca [6] (3.28): position of particle 1: \(r_1\) [fm] position of particle 2: \(r_2\) [fm] velocity of particle 1: \(v_1\) velocity of particle 1: \(v_2\)

\[t_{coll} = - (r_1 - r_2) . (v_1 - v_2) / (v_1 - v_2)^2\]

[fm]

Definition at line 66 of file scatteractionsfinder.h.

68  {
70  return dt * random::uniform(0., 1.);
71  } else {
72  /*
73  * For frozen Fermi motion:
74  * If particles have not yet interacted and are the initial nucleons,
75  * perform action finding with beam momentum instead of Fermi motion
76  * corrected momentum. That is because the particles are propagated with
77  * the beam momentum until they interact.
78  */
79  if (p1.id() < 0 || p2.id() < 0) {
80  throw std::runtime_error("Invalid particle ID for Fermi motion");
81  }
82  const bool p1_has_no_prior_interactions =
83  (static_cast<uint64_t>(p1.id()) < // particle from
84  static_cast<uint64_t>(beam_momentum.size())) && // initial nucleus
85  (p1.get_history().collisions_per_particle == 0);
86 
87  const bool p2_has_no_prior_interactions =
88  (static_cast<uint64_t>(p2.id()) < // particle from
89  static_cast<uint64_t>(beam_momentum.size())) && // initial nucleus
90  (p2.get_history().collisions_per_particle == 0);
91 
92  const FourVector p1_mom = (p1_has_no_prior_interactions)
93  ? beam_momentum[p1.id()]
94  : p1.momentum();
95  const FourVector p2_mom = (p2_has_no_prior_interactions)
96  ? beam_momentum[p2.id()]
97  : p2.momentum();
105  const FourVector delta_x = p1.position() - p2.position();
106  const double p1_sqr = p1_mom.sqr();
107  const double p2_sqr = p2_mom.sqr();
108  const double p1_dot_x = p1_mom.Dot(delta_x);
109  const double p2_dot_x = p2_mom.Dot(delta_x);
110  const double p1_dot_p2 = p1_mom.Dot(p2_mom);
111  const double denominator = std::pow(p1_dot_p2, 2) - p1_sqr * p2_sqr;
112  if (unlikely(std::abs(denominator) < really_small * really_small)) {
113  return -1.0;
114  }
115 
116  const double time_1 = (p2_sqr * p1_dot_x - p1_dot_p2 * p2_dot_x) *
117  p1_mom.x0() / denominator;
118  const double time_2 = -(p1_sqr * p2_dot_x - p1_dot_p2 * p1_dot_x) *
119  p2_mom.x0() / denominator;
120  return (time_1 + time_2) / 2;
121  } else {
131  const ThreeVector dv_times_e1e2 =
132  p1_mom.threevec() * p2_mom.x0() - p2_mom.threevec() * p1_mom.x0();
133  const double dv_times_e1e2_sqr = dv_times_e1e2.sqr();
134  if (dv_times_e1e2_sqr < really_small) {
135  return -1.0;
136  }
137  const ThreeVector dr =
138  p1.position().threevec() - p2.position().threevec();
139  return -(dr * dv_times_e1e2) *
140  (p1_mom.x0() * p2_mom.x0() / dv_times_e1e2_sqr);
141  }
142  }
143  }
@ Covariant
Covariant Criterion.
#define unlikely(x)
Tell the branch predictor that this expression is likely false.
Definition: macros.h:16
T uniform(T min, T max)
Definition: random.h:88
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:41

◆ find_actions_in_cell()

ActionList smash::ScatterActionsFinder::find_actions_in_cell ( const ParticleList &  search_list,
double  dt,
const double  gcell_vol,
const std::vector< FourVector > &  beam_momentum 
) const
overridevirtual

Search for all the possible collisions within one cell.

This function is only used for counting the primary collisions at the beginning of each time step. (Although it's also called afterwards for searching the secondary collisions among the outgoing particles, no new actions will be found since the scattered pairs cannot scatter again.)

Parameters
[in]search_listA list of particles within one cell
[in]dtThe maximum time interval at the current time step [fm]
[in]gcell_volVolume of searched grid cell [fm^3]
[in]beam_momentum[GeV] List of beam momenta for each particle; only necessary for frozen Fermi motion
Returns
A list of possible scatter actions

Implements smash::ActionFinderInterface.

Definition at line 452 of file scatteractionsfinder.cc.

454  {
455  std::vector<ActionPtr> actions;
456  for (const ParticleData& p1 : search_list) {
457  for (const ParticleData& p2 : search_list) {
458  // Check for 2 particle scattering
459  if (p1.id() < p2.id()) {
460  ActionPtr act =
461  check_collision_two_part(p1, p2, dt, beam_momentum, gcell_vol);
462  if (act) {
463  actions.push_back(std::move(act));
464  }
465  }
467  // Also, check for 3 particle scatterings with stochastic criterion
468  for (const ParticleData& p3 : search_list) {
473  if (p1.id() < p2.id() && p2.id() < p3.id()) {
474  ActionPtr act =
475  check_collision_multi_part({p1, p2, p3}, dt, gcell_vol);
476  if (act) {
477  actions.push_back(std::move(act));
478  }
479  }
480  }
481  for (const ParticleData& p4 : search_list) {
484  if (p1.id() < p2.id() && p2.id() < p3.id() && p3.id() < p4.id()) {
485  ActionPtr act =
486  check_collision_multi_part({p1, p2, p3, p4}, dt, gcell_vol);
487  if (act) {
488  actions.push_back(std::move(act));
489  }
490  }
491  }
494  search_list.size() >= 5) {
495  for (const ParticleData& p5 : search_list) {
496  if ((p1.id() < p2.id() && p2.id() < p3.id() &&
497  p3.id() < p4.id() && p4.id() < p5.id()) &&
498  (p1.is_pion() && p2.is_pion() && p3.is_pion() &&
499  p4.is_pion() && p5.is_pion())) {
500  // at the moment only pure pion 5-body reactions
501  ActionPtr act = check_collision_multi_part(
502  {p1, p2, p3, p4, p5}, dt, gcell_vol);
503  if (act) {
504  actions.push_back(std::move(act));
505  }
506  }
507  }
508  }
509  }
510  }
511  }
512  }
513  }
514  return actions;
515 }
ActionPtr check_collision_two_part(const ParticleData &data_a, const ParticleData &data_b, double dt, const std::vector< FourVector > &beam_momentum={}, const double gcell_vol=0.0) const
Check for a single pair of particles (id_a, id_b) if a collision will happen in the next timestep and...
ActionPtr check_collision_multi_part(const ParticleList &plist, double dt, const double gcell_vol) const
Check for multiple i.e.
@ A3_Nuclei_4to2
@ Meson_3to1

◆ find_actions_with_neighbors()

ActionList smash::ScatterActionsFinder::find_actions_with_neighbors ( const ParticleList &  search_list,
const ParticleList &  neighbors_list,
double  dt,
const std::vector< FourVector > &  beam_momentum 
) const
overridevirtual

Search for all the possible collisions among the neighboring cells.

This function is only used for counting the primary collisions at the beginning of each time step.

Parameters
[in]search_listA list of particles within the current cell
[in]neighbors_listA list of particles within the neighboring cell
[in]dtThe maximum time interval at the current time step [fm]
[in]beam_momentum[GeV] List of beam momenta for each particle; only necessary for frozen Fermi motion
Returns
A list of possible scatter actions

Implements smash::ActionFinderInterface.

Definition at line 517 of file scatteractionsfinder.cc.

519  {
520  std::vector<ActionPtr> actions;
522  // Only search in cells
523  return actions;
524  }
525  for (const ParticleData& p1 : search_list) {
526  for (const ParticleData& p2 : neighbors_list) {
527  assert(p1.id() != p2.id());
528  // Check if a collision is possible.
529  ActionPtr act = check_collision_two_part(p1, p2, dt, beam_momentum);
530  if (act) {
531  actions.push_back(std::move(act));
532  }
533  }
534  }
535  return actions;
536 }

◆ find_actions_with_surrounding_particles()

ActionList smash::ScatterActionsFinder::find_actions_with_surrounding_particles ( const ParticleList &  search_list,
const Particles surrounding_list,
double  dt,
const std::vector< FourVector > &  beam_momentum 
) const
overridevirtual

Search for all the possible secondary collisions between the outgoing particles and the rest.

Parameters
[in]search_listA list of particles within the current cell
[in]surrounding_listThe whole particle list
[in]dtThe maximum time interval at the current time step [fm]
[in]beam_momentum[GeV] List of beam momenta for each particle; only necessary for frozen Fermi motion
Returns
A list of possible scatter actions

Implements smash::ActionFinderInterface.

Definition at line 538 of file scatteractionsfinder.cc.

540  {
541  std::vector<ActionPtr> actions;
543  // Only search in cells
544  return actions;
545  }
546  for (const ParticleData& p2 : surrounding_list) {
547  /* don't look for collisions if the particle from the surrounding list is
548  * also in the search list */
549  auto result = std::find_if(
550  search_list.begin(), search_list.end(),
551  [&p2](const ParticleData& p) { return p.id() == p2.id(); });
552  if (result != search_list.end()) {
553  continue;
554  }
555  for (const ParticleData& p1 : search_list) {
556  // Check if a collision is possible.
557  ActionPtr act = check_collision_two_part(p1, p2, dt, beam_momentum);
558  if (act) {
559  actions.push_back(std::move(act));
560  }
561  }
562  }
563  return actions;
564 }
constexpr int p
Proton.

◆ find_final_actions()

ActionList smash::ScatterActionsFinder::find_final_actions ( const Particles ) const
inlineoverridevirtual

No scatterings should be found when the event is over.

Implements smash::ActionFinderInterface.

Definition at line 195 of file scatteractionsfinder.h.

195 { return {}; }

◆ is_constant_elastic_isotropic()

bool smash::ScatterActionsFinder::is_constant_elastic_isotropic ( ) const
inline

If there is only one particle sort, no decays (only elastic scatterings are possible), scatterings are isotropic and cross-section fixed to elastic_parameter_ independently on momenta, then maximal cross-section is elastic_parameter_.

This knowledge can be used for improving performance.

Returns
A boolean indicating whether all the scatterings are elastic and isotropic

Definition at line 207 of file scatteractionsfinder.h.

207  {
208  return ParticleType::list_all().size() == 1 &&
211  }
static const ParticleTypeList & list_all()
Definition: particletype.cc:51
const bool two_to_one
Enables resonance production.

◆ max_transverse_distance_sqr()

double smash::ScatterActionsFinder::max_transverse_distance_sqr ( int  testparticles) const
inline

The maximal distance over which particles can interact in case of the geometric criterion, related to the number of test particles and the maximal cross section.

Parameters
[in]testparticlesNumber of test particles.
Returns
Maximal transverse distance squared. [fm \(^{2}\)] Particle pairs whose transverse distance is larger than this are not checked for collisions in case of the default geometric collision criterion.

Definition at line 225 of file scatteractionsfinder.h.

225  {
229  testparticles * fm2_mb * M_1_PI;
230  }
constexpr double fm2_mb
mb <-> fm^2 conversion factor.
Definition: constants.h:32

◆ dump_reactions()

void smash::ScatterActionsFinder::dump_reactions ( ) const

Prints out all the 2-> n (n > 1) reactions with non-zero cross-sections between all possible pairs of particle types.

Definition at line 566 of file scatteractionsfinder.cc.

566  {
567  constexpr double time = 0.0;
568 
569  const size_t N_isotypes = IsoParticleType::list_all().size();
570  const size_t N_pairs = N_isotypes * (N_isotypes - 1) / 2;
571 
572  std::cout << N_isotypes << " iso-particle types." << std::endl;
573  std::cout << "They can make " << N_pairs << " pairs." << std::endl;
574  std::vector<double> momentum_scan_list = {0.1, 0.3, 0.5, 1.0,
575  2.0, 3.0, 5.0, 10.0};
576  for (const IsoParticleType& A_isotype : IsoParticleType::list_all()) {
577  for (const IsoParticleType& B_isotype : IsoParticleType::list_all()) {
578  if (&A_isotype > &B_isotype) {
579  continue;
580  }
581  bool any_nonzero_cs = false;
582  std::vector<std::string> r_list;
583  for (const ParticleTypePtr A_type : A_isotype.get_states()) {
584  for (const ParticleTypePtr B_type : B_isotype.get_states()) {
585  if (A_type > B_type) {
586  continue;
587  }
588  ParticleData A(*A_type), B(*B_type);
589  for (auto mom : momentum_scan_list) {
590  A.set_4momentum(A.pole_mass(), mom, 0.0, 0.0);
591  B.set_4momentum(B.pole_mass(), -mom, 0.0, 0.0);
592  ScatterActionPtr act = std::make_unique<ScatterAction>(
593  A, B, time, isotropic_, string_formation_time_, -1, false,
596  act->set_string_interface(string_process_interface_.get());
597  }
598  act->add_all_scatterings(finder_parameters_);
599  const double total_cs = act->cross_section();
600  if (total_cs <= 0.0) {
601  continue;
602  }
603  any_nonzero_cs = true;
604  for (const auto& channel : act->collision_channels()) {
605  const auto type = channel->get_type();
606  std::string r;
607  if (is_string_soft_process(type) ||
608  type == ProcessType::StringHard) {
609  r = A_type->name() + B_type->name() + std::string(" → strings");
610  } else {
611  std::string r_type =
612  (type == ProcessType::Elastic) ? std::string(" (el)")
613  : (channel->get_type() == ProcessType::TwoToTwo)
614  ? std::string(" (inel)")
615  : std::string(" (?)");
616  r = A_type->name() + B_type->name() + std::string(" → ") +
617  channel->particle_types()[0]->name() +
618  channel->particle_types()[1]->name() + r_type;
619  }
620  isoclean(r);
621  r_list.push_back(r);
622  }
623  }
624  }
625  }
626  std::sort(r_list.begin(), r_list.end());
627  r_list.erase(std::unique(r_list.begin(), r_list.end()), r_list.end());
628  if (any_nonzero_cs) {
629  for (auto r : r_list) {
630  std::cout << r;
631  if (r_list.back() != r) {
632  std::cout << ", ";
633  }
634  }
635  std::cout << std::endl;
636  }
637  }
638  }
639 }
static const IsoParticleTypeList & list_all()
Returns a list of all IsoParticleTypes.
const SpinInteractionType spin_interaction_type
Switch to control whether to include spin interactions.
@ TwoToTwo
See here for a short description.
@ Elastic
See here for a short description.
@ StringHard
See here for a short description.
void isoclean(std::string &s)
Remove ⁺, ⁻, ⁰ from string.
bool is_string_soft_process(ProcessType p)
Check if a given process type is a soft string excitation.

◆ dump_cross_sections()

void smash::ScatterActionsFinder::dump_cross_sections ( const ParticleType a,
const ParticleType b,
double  m_a,
double  m_b,
bool  final_state,
std::vector< double > &  plab 
) const

Print out partial cross-sections of all processes that can occur in the collision of a(mass = m_a) and b(mass = m_b).

Parameters
[in]aThe specie of the first incoming particle.
[in]bThe specie of the second incoming particle.
[in]m_aMass of species a [GeV].
[in]m_bMass of species b [GeV].
[in]final_stateWhether the final state cross sections should be printed.
[in]plabOptional momenta in lab frame to be evaluated [GeV]. Ignored if empty.

Definition at line 950 of file scatteractionsfinder.cc.

952  {
953  typedef std::vector<std::pair<double, double>> xs_saver;
954  std::map<std::string, xs_saver> xs_dump;
955  std::map<std::string, double> outgoing_total_mass;
956 
957  ParticleData a_data(a), b_data(b);
958  int n_momentum_points = 200;
959  constexpr double momentum_step = 0.02;
960  if (plab.size() > 0) {
961  n_momentum_points = plab.size();
962  // Remove duplicates.
963  std::sort(plab.begin(), plab.end());
964  plab.erase(std::unique(plab.begin(), plab.end()), plab.end());
965  }
966  for (int i = 0; i < n_momentum_points; i++) {
967  double momentum;
968  if (plab.size() > 0) {
969  momentum = pCM_from_s(s_from_plab(plab.at(i), m_a, m_b), m_a, m_b);
970  } else {
971  momentum = momentum_step * (i + 1);
972  }
973  a_data.set_4momentum(m_a, momentum, 0.0, 0.0);
974  b_data.set_4momentum(m_b, -momentum, 0.0, 0.0);
975  const double sqrts = (a_data.momentum() + b_data.momentum()).abs();
976  const ParticleList incoming = {a_data, b_data};
977  ScatterActionPtr act = std::make_unique<ScatterAction>(
978  a_data, b_data, 0., isotropic_, string_formation_time_, -1, false,
981  act->set_string_interface(string_process_interface_.get());
982  }
983  act->add_all_scatterings(finder_parameters_);
984  decaytree::Node tree(a.name() + b.name(), act->cross_section(), {&a, &b},
985  {&a, &b}, {&a, &b}, {});
986  const CollisionBranchList& processes = act->collision_channels();
987  for (const auto& process : processes) {
988  const double xs = process->weight();
989  if (xs <= 0.0) {
990  continue;
991  }
992  if (!final_state) {
993  std::stringstream process_description_stream;
994  process_description_stream << *process;
995  const std::string& description = process_description_stream.str();
996  double m_tot = 0.0;
997  for (const auto& ptype : process->particle_types()) {
998  m_tot += ptype->mass();
999  }
1000  outgoing_total_mass[description] = m_tot;
1001  if (!xs_dump[description].empty() &&
1002  std::abs(xs_dump[description].back().first - sqrts) <
1003  really_small) {
1004  xs_dump[description].back().second += xs;
1005  } else {
1006  xs_dump[description].push_back(std::make_pair(sqrts, xs));
1007  }
1008  } else {
1009  std::stringstream process_description_stream;
1010  process_description_stream << *process;
1011  const std::string& description = process_description_stream.str();
1012  ParticleTypePtrList initial_particles = {&a, &b};
1013  ParticleTypePtrList final_particles = process->particle_types();
1014  auto& process_node =
1015  tree.add_action(description, xs, std::move(initial_particles),
1016  std::move(final_particles));
1017  decaytree::add_decays(process_node, sqrts);
1018  }
1019  }
1020  xs_dump["total"].push_back(std::make_pair(sqrts, act->cross_section()));
1021  // Total cross-section should be the first in the list -> negative mass
1022  outgoing_total_mass["total"] = -1.0;
1023  if (final_state) {
1024  // tree.print();
1025  auto final_state_xs = tree.final_state_cross_sections();
1026  deduplicate(final_state_xs);
1027  for (const auto& p : final_state_xs) {
1028  // Don't print empty columns.
1029  //
1030  // FIXME(steinberg): The better fix would be to not have them in the
1031  // first place.
1032  if (p.name_ == "") {
1033  continue;
1034  }
1035  outgoing_total_mass[p.name_] = p.mass_;
1036  xs_dump[p.name_].push_back(std::make_pair(sqrts, p.cross_section_));
1037  }
1038  }
1039  }
1040  // Get rid of cross sections that are zero.
1041  // (This only happens if their is a resonance in the final state that cannot
1042  // decay with our simplified assumptions.)
1043  for (auto it = begin(xs_dump); it != end(xs_dump);) {
1044  // Sum cross section over all energies.
1045  const xs_saver& xs = (*it).second;
1046  double sum = 0;
1047  for (const auto& p : xs) {
1048  sum += p.second;
1049  }
1050  if (sum == 0.) {
1051  it = xs_dump.erase(it);
1052  } else {
1053  ++it;
1054  }
1055  }
1056 
1057  // Nice ordering of channels by summed pole mass of products
1058  std::vector<std::string> all_channels;
1059  for (const auto& channel : xs_dump) {
1060  all_channels.push_back(channel.first);
1061  }
1062  std::sort(all_channels.begin(), all_channels.end(),
1063  [&](const std::string& str_a, const std::string& str_b) {
1064  return outgoing_total_mass[str_a] < outgoing_total_mass[str_b];
1065  });
1066 
1067  // Print header
1068  std::cout << "# Dumping partial " << a.name() << b.name()
1069  << " cross-sections in mb, energies in GeV" << std::endl;
1070  std::cout << " sqrt_s";
1071  // Align everything to 24 unicode characters.
1072  // This should be enough for the longest channel name: 7 final-state
1073  // particles, or 2 of the longest named resonances (currently Ds0*(2317)⁺).
1074  for (const auto& channel : all_channels) {
1075  std::cout << utf8::fill_left(channel, 24, ' ');
1076  }
1077  std::cout << std::endl;
1078 
1079  // Print out all partial cross-sections in mb
1080  for (int i = 0; i < n_momentum_points; i++) {
1081  double momentum;
1082  if (plab.size() > 0) {
1083  momentum = pCM_from_s(s_from_plab(plab.at(i), m_a, m_b), m_a, m_b);
1084  } else {
1085  momentum = momentum_step * (i + 1);
1086  }
1087  a_data.set_4momentum(m_a, momentum, 0.0, 0.0);
1088  b_data.set_4momentum(m_b, -momentum, 0.0, 0.0);
1089  const double sqrts = (a_data.momentum() + b_data.momentum()).abs();
1090  std::printf("%9.6f", sqrts);
1091  for (const auto& channel : all_channels) {
1092  const xs_saver energy_and_xs = xs_dump[channel];
1093  size_t j = 0;
1094  for (; j < energy_and_xs.size() && energy_and_xs[j].first < sqrts; j++) {
1095  }
1096  double xs = 0.0;
1097  if (j < energy_and_xs.size() &&
1098  std::abs(energy_and_xs[j].first - sqrts) < really_small) {
1099  xs = energy_and_xs[j].second;
1100  }
1101  std::printf("%16.6f", xs); // Same alignment as in the header.
1102  }
1103  std::printf("\n");
1104  }
1105 }
static void add_decays(Node &node, double sqrts)
Add nodes for all decays possible from the given node and all of its children.
std::string fill_left(const std::string &s, size_t width, char fill=' ')
Fill string with characters to the left until the given width is reached.
static void deduplicate(std::vector< FinalStateCrossSection > &final_state_xs)
Deduplicate the final-state cross sections by summing.
T pCM_from_s(const T s, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:66
double s_from_plab(double plab, double m_P, double m_T)
Convert p_lab to Mandelstam-s for a fixed-target setup, with a projectile of mass m_P and momentum pl...
Definition: kinematics.h:265

◆ get_process_string_ptr()

StringProcess* smash::ScatterActionsFinder::get_process_string_ptr ( )
inline
Returns
Pointer to the string process class object. If string is turned off, the null pointer is returned.

Definition at line 259 of file scatteractionsfinder.h.

259  {
261  return string_process_interface_.get();
262  } else {
263  return NULL;
264  }
265  }

◆ check_collision_two_part()

ActionPtr smash::ScatterActionsFinder::check_collision_two_part ( const ParticleData data_a,
const ParticleData data_b,
double  dt,
const std::vector< FourVector > &  beam_momentum = {},
const double  gcell_vol = 0.0 
) const
private

Check for a single pair of particles (id_a, id_b) if a collision will happen in the next timestep and create a corresponding Action object in that case.

Two criteria for the collision decision are supported: 1. The default geometric criterion from UrQMD Bass:1998ca [6] (3.27). 2. A stochastic collision criterion as introduced in Staudenmaier:2021lrg [61].

Parameters
[in]data_aFirst incoming particle
[in]data_bSecond incoming particle
[in]dtMaximum time interval within which a collision can happen
[in]beam_momentum[GeV] List of beam momenta for each particle; only necessary for frozen Fermi motion
[in]gcell_vol(optional) volume of grid cell in which the collision is checked
Returns
A null pointer if no collision happens or an action which contains the information of the outgoing particles.

Note: gcell_vol is optional, since only find_actions_in_cell has (and needs) this information for the stochastic collision criterion.

Definition at line 217 of file scatteractionsfinder.cc.

220  {
221  /* If the two particles
222  * 1) belong to one of the two colliding nuclei, and
223  * 2) both of them have never experienced any collisions,
224  * then the collisions between them are banned. */
226  assert(data_a.id() >= 0);
227  assert(data_b.id() >= 0);
228  bool in_same_nucleus = (data_a.belongs_to() == BelongsTo::Projectile &&
229  data_b.belongs_to() == BelongsTo::Projectile) ||
230  (data_a.belongs_to() == BelongsTo::Target &&
231  data_b.belongs_to() == BelongsTo::Target);
232  bool never_interacted_before =
233  data_a.get_history().collisions_per_particle == 0 &&
234  data_b.get_history().collisions_per_particle == 0;
235  if (in_same_nucleus && never_interacted_before) {
236  return nullptr;
237  }
238  }
239 
240  // No grid or search in cell means no collision for stochastic criterion
242  gcell_vol < really_small) {
243  return nullptr;
244  }
245 
246  // Determine time of collision.
247  const double time_until_collision =
248  collision_time(data_a, data_b, dt, beam_momentum);
249 
250  // Check that collision happens in this timestep.
251  if (time_until_collision < 0. || time_until_collision >= dt) {
252  return nullptr;
253  }
254 
255  // Determine which total cross section to use
256  bool incoming_parametrized = (finder_parameters_.total_xs_strategy ==
260  const PdgCode& pdg_a = data_a.type().pdgcode();
261  const PdgCode& pdg_b = data_b.type().pdgcode();
262  incoming_parametrized = parametrization_exists(pdg_a, pdg_b);
263  }
264 
265  // Create ScatterAction object.
266  ScatterActionPtr act = std::make_unique<ScatterAction>(
267  data_a, data_b, time_until_collision, isotropic_, string_formation_time_,
268  box_length_, incoming_parametrized,
270 
272  act->set_stochastic_pos_idx();
273  }
274 
276  act->set_string_interface(string_process_interface_.get());
277  }
278 
279  // Distance squared calculation not needed for stochastic criterion
280  const double distance_squared =
282  ? act->transverse_distance_sqr()
284  ? act->cov_transverse_distance_sqr()
285  : 0.0;
286 
287  // Don't calculate cross section if the particles are very far apart.
288  // Not needed for stochastic criterion because of cell structure.
290  distance_squared >=
292  return nullptr;
293  }
294 
295  if (incoming_parametrized) {
296  act->set_parametrized_total_cross_section(finder_parameters_);
297  } else {
298  // Add various subprocesses.
299  act->add_all_scatterings(finder_parameters_);
300  }
301 
302  double xs = act->cross_section() * fm2_mb /
303  static_cast<double>(finder_parameters_.testparticles);
304 
305  // Take cross section scaling factors into account
306  xs *= data_a.xsec_scaling_factor(time_until_collision);
307  xs *= data_b.xsec_scaling_factor(time_until_collision);
308 
310  const double v_rel = act->relative_velocity();
311  /* Collision probability for 2-particle scattering, see
312  * \iref{Staudenmaier:2021lrg}. */
313  const double prob = xs * v_rel * dt / gcell_vol;
314 
315  logg[LFindScatter].debug(
316  "Stochastic collison criterion parameters (2-particles):\nprob = ",
317  prob, ", xs = ", xs, ", v_rel = ", v_rel, ", dt = ", dt,
318  ", gcell_vol = ", gcell_vol,
319  ", testparticles = ", finder_parameters_.testparticles);
320 
321  if (prob > 1.) {
322  std::stringstream err;
323  err << "Probability larger than 1 for stochastic rates. ( P_22 = " << prob
324  << " )\n"
325  << data_a.type().name() << data_b.type().name() << " with masses "
326  << data_a.momentum().abs() << " and " << data_b.momentum().abs()
327  << " at sqrts[GeV] = " << act->sqrt_s()
328  << " with xs[fm^2]/Ntest = " << xs
329  << "\nConsider using smaller timesteps.";
331  logg[LFindScatter].warn(err.str());
332  } else {
333  throw std::runtime_error(err.str());
334  }
335  }
336 
337  // probability criterion
338  double random_no = random::uniform(0., 1.);
339  if (random_no > prob) {
340  return nullptr;
341  }
342 
345  // just collided with this particle
346  if (data_a.id_process() > 0 && data_a.id_process() == data_b.id_process()) {
347  logg[LFindScatter].debug("Skipping collided particles at time ",
348  data_a.position().x0(), " due to process ",
349  data_a.id_process(), "\n ", data_a, "\n<-> ",
350  data_b);
351 
352  return nullptr;
353  }
354 
355  // Cross section for collision criterion
356  const double cross_section_criterion = xs * M_1_PI;
357 
358  // distance criterion according to cross_section
359  if (distance_squared >= cross_section_criterion) {
360  return nullptr;
361  }
362 
363  logg[LFindScatter].debug("particle distance squared: ", distance_squared,
364  "\n ", data_a, "\n<-> ", data_b);
365  }
366 
367  // Include possible outgoing branches
368  if (incoming_parametrized) {
369  act->add_all_scatterings(finder_parameters_);
370  }
371 
372  return act;
373 }
const bool only_warn_for_high_prob
Switch to turn off throwing an exception for collision probabilities larger than 1.
const int testparticles
Number of test particles.
const TotalCrossSectionStrategy total_xs_strategy
Method used to evaluate total cross sections for collision finding.
const bool allow_collisions_within_nucleus
If particles within the same nucleus are allowed to collide for their first time.
double max_transverse_distance_sqr(int testparticles) const
The maximal distance over which particles can interact in case of the geometric criterion,...
double collision_time(const ParticleData &p1, const ParticleData &p2, double dt, const std::vector< FourVector > &beam_momentum) const
Determine the collision time of the two particles.
@ TopDownMeasured
Mix the two above, using the parametrizations only for measured processes, and summing up partials fo...
@ TopDown
Use parametrizations based on existing data, rescaling with AQM for unmeasured processes.
@ Geometric
Geometric criterion.
bool parametrization_exists(const PdgCode &pdg_a, const PdgCode &pdg_b)
Checks if supplied codes have existing parametrizations of total cross sections.

◆ check_collision_multi_part()

ActionPtr smash::ScatterActionsFinder::check_collision_multi_part ( const ParticleList &  plist,
double  dt,
const double  gcell_vol 
) const
private

Check for multiple i.e.

more than 2 particles if a collision will happen in the next timestep and create a corresponding Action object in that case.

This is only possible for the stochastic collision criterion, which is introduced in Staudenmaier:2021lrg [61]. Following the same general idea as for the 2-particle scatterings, probabilities for multi-particle scatterings can be derived.

Parameters
[in]plistList of incoming particles
[in]dtMaximum time interval within which a collision can happen
[in]gcell_volvolume of grid cell in which the collision is checked
Returns
A null pointer if no collision happens or an action which contains the information of the outgoing particles.

Definition at line 375 of file scatteractionsfinder.cc.

376  {
377  /* If all particles
378  * 1) belong to the two colliding nuclei
379  * 2) are within the same nucleus
380  * 3) have never experienced any collisons,
381  * then the collision between them are banned also for multi-particle
382  * interactions. */
384  bool all_projectile =
385  std::all_of(plist.begin(), plist.end(), [&](const ParticleData& data) {
386  return data.belongs_to() == BelongsTo::Projectile;
387  });
388  bool all_target =
389  std::all_of(plist.begin(), plist.end(), [&](const ParticleData& data) {
390  return data.belongs_to() == BelongsTo::Target;
391  });
392  bool none_collided =
393  std::all_of(plist.begin(), plist.end(), [&](const ParticleData& data) {
394  return data.get_history().collisions_per_particle == 0;
395  });
396  if ((all_projectile || all_target) && none_collided) {
397  return nullptr;
398  }
399  }
400  // No grid or search in cell
401  if (gcell_vol < really_small) {
402  return nullptr;
403  }
404 
405  /* Optimisation for later: Already check here at the beginning
406  * if collision with plist is possible before constructing actions. */
407 
408  // 1. Determine time of collision.
409  const double time_until_collision = dt * random::uniform(0., 1.);
410 
411  // 2. Create ScatterAction object.
412  ScatterActionMultiPtr act =
413  std::make_unique<ScatterActionMulti>(plist, time_until_collision);
414 
415  act->set_stochastic_pos_idx();
416 
417  // 3. Add possible final states (dt and gcell_vol for probability calculation)
418  act->add_possible_reactions(dt, gcell_vol, finder_parameters_.included_multi);
419 
420  /* 4. Return total collision probability
421  * Scales with 1 over the number of testpartciles to the power of the
422  * number of incoming particles - 1 */
423  const double prob =
424  act->get_total_weight() /
425  std::pow(finder_parameters_.testparticles, plist.size() - 1);
426 
427  // 5. Check that probability is smaller than one
428  if (prob > 1.) {
429  std::stringstream err;
430  err << "Probability " << prob << " larger than 1 for stochastic rates for ";
431  for (const ParticleData& data : plist) {
432  err << data.type().name();
433  }
434  err << " at sqrts[GeV] = " << act->sqrt_s()
435  << "\nConsider using smaller timesteps.";
437  logg[LFindScatter].warn(err.str());
438  } else {
439  throw std::runtime_error(err.str());
440  }
441  }
442 
443  // 6. Perform probability decisions
444  double random_no = random::uniform(0., 1.);
445  if (random_no > prob) {
446  return nullptr;
447  }
448 
449  return act;
450 }
bool all_of(Container &&c, UnaryPredicate &&p)
Convenience wrapper for std::all_of that operates on a complete container.
Definition: algorithms.h:80

Member Data Documentation

◆ finder_parameters_

ScatterActionsFinderParameters smash::ScatterActionsFinder::finder_parameters_
private

Struct collecting several parameters.

Definition at line 314 of file scatteractionsfinder.h.

◆ string_process_interface_

std::unique_ptr<StringProcess> smash::ScatterActionsFinder::string_process_interface_
private

Class that deals with strings, interfacing Pythia.

Definition at line 316 of file scatteractionsfinder.h.

◆ isotropic_

const bool smash::ScatterActionsFinder::isotropic_
private

Do all collisions isotropically.

Definition at line 318 of file scatteractionsfinder.h.

◆ box_length_

const double smash::ScatterActionsFinder::box_length_
private

Box length: needed to determine coordinates of collision correctly in case of collision through the wall.

Ignored if negative.

Definition at line 324 of file scatteractionsfinder.h.

◆ string_formation_time_

const double smash::ScatterActionsFinder::string_formation_time_
private

Parameter for formation time.

Definition at line 326 of file scatteractionsfinder.h.


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