Version: SMASH-3.0
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 &, bool=false) const override
 Find some final collisions at the end of the simulation. 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 33 of file scatteractionsfinder.cc.

35  : finder_parameters_(create_finder_parameters(config, parameters)),
36  isotropic_(config.take({"Collision_Term", "Isotropic"}, false)),
37  box_length_(parameters.box_length),
38  string_formation_time_(config.take(
39  {"Collision_Term", "String_Parameters", "Formation_Time"}, 1.)) {
41  logg[LFindScatter].info(
42  "Constant elastic isotropic cross-section mode:", " using ",
43  finder_parameters_.elastic_parameter, " mb as maximal cross-section.");
44  }
47  throw std::invalid_argument(
48  "Multi-body reactions (like e.g. 3->1 or 3->2) are only possible with "
49  "the stochastic "
50  "collision "
51  "criterion. Change your config accordingly.");
52  }
53 
56  1 &&
58  .included_2to2[IncludedReactions::PiDeuteron_to_pidprime] == 1 ||
60  .included_2to2[IncludedReactions::NDeuteron_to_Ndprime] == 1)) {
61  throw std::invalid_argument(
62  "To prevent double counting it is not possible to enable deuteron 3->2 "
63  "reactions\nand reactions involving the d' at the same time\ni.e. to "
64  "include \"Deuteron_3to2\" in `Multi_Particle_Reactions` and\n "
65  "\"PiDeuteron_to_pidprime\" "
66  "or \"NDeuteron_to_Ndprime\" in `Included_2to2` at the same time.\n"
67  "Change your config accordingly.");
68  }
69 
72  1 &&
74  throw std::invalid_argument(
75  "Do not use the d' resonance and enable \"Deuteron_3to2\" "
76  "`Multi_Particle_Reactions` at the same time. Either use the direct "
77  "3-to-2 reactions or the d' together with \"PiDeuteron_to_pidprime\" "
78  "and \"NDeuteron_to_Ndprime\" in `Included_2to2`. Otherwise the "
79  "deuteron 3-to-2 reactions would be double counted.");
80  }
81 
85  1) ||
88  1 &&
90  throw std::invalid_argument(
91  "In order to conserve detailed balance, when \"NNbar_5to2\" is "
92  "included in\n`Multi_Particle_Reactions`, the `NNbarTreatment` has to "
93  "be set to \"two to five\" and vice versa.");
94  }
95 
98  throw std::invalid_argument(
99  "'NNbar' has to be in the list of allowed 2 to 2 processes "
100  "to enable annihilation to go through resonances");
101  }
102 
104  auto subconfig = config.extract_sub_configuration(
105  {"Collision_Term", "String_Parameters"}, Configuration::GetEmpty::Yes);
106  string_process_interface_ = std::make_unique<StringProcess>(
107  subconfig.take({"String_Tension"}, 1.0), string_formation_time_,
108  subconfig.take({"Gluon_Beta"}, 0.5),
109  subconfig.take({"Gluon_Pmin"}, 0.001),
110  subconfig.take({"Quark_Alpha"}, 2.0),
111  subconfig.take({"Quark_Beta"}, 7.0),
112  subconfig.take({"Strange_Supp"}, 0.16),
113  subconfig.take({"Diquark_Supp"}, 0.036),
114  subconfig.take({"Sigma_Perp"}, 0.42),
115  subconfig.take({"StringZ_A_Leading"}, 0.2),
116  subconfig.take({"StringZ_B_Leading"}, 2.0),
117  subconfig.take({"StringZ_A"}, 2.0), subconfig.take({"StringZ_B"}, 0.55),
118  subconfig.take({"String_Sigma_T"}, 0.5),
119  subconfig.take({"Form_Time_Factor"}, 1.0),
120  subconfig.take({"Mass_Dependent_Formation_Times"}, false),
121  subconfig.take({"Prob_proton_to_d_uu"}, 1. / 3.),
122  subconfig.take({"Separate_Fragment_Baryon"}, true),
123  subconfig.take({"Popcorn_Rate"}, 0.15),
124  subconfig.take({"Use_Monash_Tune"},
125  parameters.use_monash_tune_default.value()));
126  }
127 }
static const ParticleTypePtr try_find(PdgCode pdgcode)
Returns the ParticleTypePtr for the given pdgcode.
Definition: particletype.cc:89
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:39
constexpr int64_t dprime
Deuteron-prime resonance.
ScatterActionsFinderParameters create_finder_parameters(Configuration &config, const ExperimentParameters &parameters)
Gather all relevant parameters for a ScatterActionsFinder either getting them from an ExperimentParam...
static constexpr int LFindScatter
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.

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 [26] (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 [5] (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:37

◆ 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 401 of file scatteractionsfinder.cc.

403  {
404  std::vector<ActionPtr> actions;
405  for (const ParticleData& p1 : search_list) {
406  for (const ParticleData& p2 : search_list) {
407  // Check for 2 particle scattering
408  if (p1.id() < p2.id()) {
409  ActionPtr act =
410  check_collision_two_part(p1, p2, dt, beam_momentum, gcell_vol);
411  if (act) {
412  actions.push_back(std::move(act));
413  }
414  }
416  // Also, check for 3 particle scatterings with stochastic criterion
417  for (const ParticleData& p3 : search_list) {
422  if (p1.id() < p2.id() && p2.id() < p3.id()) {
423  ActionPtr act =
424  check_collision_multi_part({p1, p2, p3}, dt, gcell_vol);
425  if (act) {
426  actions.push_back(std::move(act));
427  }
428  }
429  }
430  for (const ParticleData& p4 : search_list) {
433  if (p1.id() < p2.id() && p2.id() < p3.id() && p3.id() < p4.id()) {
434  ActionPtr act =
435  check_collision_multi_part({p1, p2, p3, p4}, dt, gcell_vol);
436  if (act) {
437  actions.push_back(std::move(act));
438  }
439  }
440  }
443  search_list.size() >= 5) {
444  for (const ParticleData& p5 : search_list) {
445  if ((p1.id() < p2.id() && p2.id() < p3.id() &&
446  p3.id() < p4.id() && p4.id() < p5.id()) &&
447  (p1.is_pion() && p2.is_pion() && p3.is_pion() &&
448  p4.is_pion() && p5.is_pion())) {
449  // at the moment only pure pion 5-body reactions
450  ActionPtr act = check_collision_multi_part(
451  {p1, p2, p3, p4, p5}, dt, gcell_vol);
452  if (act) {
453  actions.push_back(std::move(act));
454  }
455  }
456  }
457  }
458  }
459  }
460  }
461  }
462  }
463  return actions;
464 }
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 466 of file scatteractionsfinder.cc.

468  {
469  std::vector<ActionPtr> actions;
471  // Only search in cells
472  return actions;
473  }
474  for (const ParticleData& p1 : search_list) {
475  for (const ParticleData& p2 : neighbors_list) {
476  assert(p1.id() != p2.id());
477  // Check if a collision is possible.
478  ActionPtr act = check_collision_two_part(p1, p2, dt, beam_momentum);
479  if (act) {
480  actions.push_back(std::move(act));
481  }
482  }
483  }
484  return actions;
485 }

◆ 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 487 of file scatteractionsfinder.cc.

489  {
490  std::vector<ActionPtr> actions;
492  // Only search in cells
493  return actions;
494  }
495  for (const ParticleData& p2 : surrounding_list) {
496  /* don't look for collisions if the particle from the surrounding list is
497  * also in the search list */
498  auto result = std::find_if(
499  search_list.begin(), search_list.end(),
500  [&p2](const ParticleData& p) { return p.id() == p2.id(); });
501  if (result != search_list.end()) {
502  continue;
503  }
504  for (const ParticleData& p1 : search_list) {
505  // Check if a collision is possible.
506  ActionPtr act = check_collision_two_part(p1, p2, dt, beam_momentum);
507  if (act) {
508  actions.push_back(std::move(act));
509  }
510  }
511  }
512  return actions;
513 }
constexpr int p
Proton.

◆ find_final_actions()

ActionList smash::ScatterActionsFinder::find_final_actions ( const Particles ,
bool  = false 
) const
inlineoverridevirtual

Find some final collisions at the end of the simulation.

Todo:
Seems to do nothing.

Implements smash::ActionFinderInterface.

Definition at line 198 of file scatteractionsfinder.h.

199  {
200  return ActionList();
201  }

◆ 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 213 of file scatteractionsfinder.h.

213  {
214  return ParticleType::list_all().size() == 1 &&
217  }
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 231 of file scatteractionsfinder.h.

231  {
235  testparticles * fm2_mb * M_1_PI;
236  }
constexpr double fm2_mb
mb <-> fm^2 conversion factor.
Definition: constants.h:28

◆ 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 515 of file scatteractionsfinder.cc.

515  {
516  constexpr double time = 0.0;
517 
518  const size_t N_isotypes = IsoParticleType::list_all().size();
519  const size_t N_pairs = N_isotypes * (N_isotypes - 1) / 2;
520 
521  std::cout << N_isotypes << " iso-particle types." << std::endl;
522  std::cout << "They can make " << N_pairs << " pairs." << std::endl;
523  std::vector<double> momentum_scan_list = {0.1, 0.3, 0.5, 1.0,
524  2.0, 3.0, 5.0, 10.0};
525  for (const IsoParticleType& A_isotype : IsoParticleType::list_all()) {
526  for (const IsoParticleType& B_isotype : IsoParticleType::list_all()) {
527  if (&A_isotype > &B_isotype) {
528  continue;
529  }
530  bool any_nonzero_cs = false;
531  std::vector<std::string> r_list;
532  for (const ParticleTypePtr A_type : A_isotype.get_states()) {
533  for (const ParticleTypePtr B_type : B_isotype.get_states()) {
534  if (A_type > B_type) {
535  continue;
536  }
537  ParticleData A(*A_type), B(*B_type);
538  for (auto mom : momentum_scan_list) {
539  A.set_4momentum(A.pole_mass(), mom, 0.0, 0.0);
540  B.set_4momentum(B.pole_mass(), -mom, 0.0, 0.0);
541  ScatterActionPtr act = std::make_unique<ScatterAction>(
542  A, B, time, isotropic_, string_formation_time_);
544  act->set_string_interface(string_process_interface_.get());
545  }
546  act->add_all_scatterings(finder_parameters_);
547  const double total_cs = act->cross_section();
548  if (total_cs <= 0.0) {
549  continue;
550  }
551  any_nonzero_cs = true;
552  for (const auto& channel : act->collision_channels()) {
553  const auto type = channel->get_type();
554  std::string r;
555  if (is_string_soft_process(type) ||
556  type == ProcessType::StringHard) {
557  r = A_type->name() + B_type->name() + std::string(" → strings");
558  } else {
559  std::string r_type =
560  (type == ProcessType::Elastic) ? std::string(" (el)")
561  : (channel->get_type() == ProcessType::TwoToTwo)
562  ? std::string(" (inel)")
563  : std::string(" (?)");
564  r = A_type->name() + B_type->name() + std::string(" → ") +
565  channel->particle_types()[0]->name() +
566  channel->particle_types()[1]->name() + r_type;
567  }
568  isoclean(r);
569  r_list.push_back(r);
570  }
571  }
572  }
573  }
574  std::sort(r_list.begin(), r_list.end());
575  r_list.erase(std::unique(r_list.begin(), r_list.end()), r_list.end());
576  if (any_nonzero_cs) {
577  for (auto r : r_list) {
578  std::cout << r;
579  if (r_list.back() != r) {
580  std::cout << ", ";
581  }
582  }
583  std::cout << std::endl;
584  }
585  }
586  }
587 }
static const IsoParticleTypeList & list_all()
Returns a list of all IsoParticleTypes.
@ 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 898 of file scatteractionsfinder.cc.

900  {
901  typedef std::vector<std::pair<double, double>> xs_saver;
902  std::map<std::string, xs_saver> xs_dump;
903  std::map<std::string, double> outgoing_total_mass;
904 
905  ParticleData a_data(a), b_data(b);
906  int n_momentum_points = 200;
907  constexpr double momentum_step = 0.02;
908  if (plab.size() > 0) {
909  n_momentum_points = plab.size();
910  // Remove duplicates.
911  std::sort(plab.begin(), plab.end());
912  plab.erase(std::unique(plab.begin(), plab.end()), plab.end());
913  }
914  for (int i = 0; i < n_momentum_points; i++) {
915  double momentum;
916  if (plab.size() > 0) {
917  momentum = pCM_from_s(s_from_plab(plab.at(i), m_a, m_b), m_a, m_b);
918  } else {
919  momentum = momentum_step * (i + 1);
920  }
921  a_data.set_4momentum(m_a, momentum, 0.0, 0.0);
922  b_data.set_4momentum(m_b, -momentum, 0.0, 0.0);
923  const double sqrts = (a_data.momentum() + b_data.momentum()).abs();
924  const ParticleList incoming = {a_data, b_data};
925  ScatterActionPtr act = std::make_unique<ScatterAction>(
926  a_data, b_data, 0., isotropic_, string_formation_time_);
928  act->set_string_interface(string_process_interface_.get());
929  }
930  act->add_all_scatterings(finder_parameters_);
931  decaytree::Node tree(a.name() + b.name(), act->cross_section(), {&a, &b},
932  {&a, &b}, {&a, &b}, {});
933  const CollisionBranchList& processes = act->collision_channels();
934  for (const auto& process : processes) {
935  const double xs = process->weight();
936  if (xs <= 0.0) {
937  continue;
938  }
939  if (!final_state) {
940  std::stringstream process_description_stream;
941  process_description_stream << *process;
942  const std::string& description = process_description_stream.str();
943  double m_tot = 0.0;
944  for (const auto& ptype : process->particle_types()) {
945  m_tot += ptype->mass();
946  }
947  outgoing_total_mass[description] = m_tot;
948  if (!xs_dump[description].empty() &&
949  std::abs(xs_dump[description].back().first - sqrts) <
950  really_small) {
951  xs_dump[description].back().second += xs;
952  } else {
953  xs_dump[description].push_back(std::make_pair(sqrts, xs));
954  }
955  } else {
956  std::stringstream process_description_stream;
957  process_description_stream << *process;
958  const std::string& description = process_description_stream.str();
959  ParticleTypePtrList initial_particles = {&a, &b};
960  ParticleTypePtrList final_particles = process->particle_types();
961  auto& process_node =
962  tree.add_action(description, xs, std::move(initial_particles),
963  std::move(final_particles));
964  decaytree::add_decays(process_node, sqrts);
965  }
966  }
967  xs_dump["total"].push_back(std::make_pair(sqrts, act->cross_section()));
968  // Total cross-section should be the first in the list -> negative mass
969  outgoing_total_mass["total"] = -1.0;
970  if (final_state) {
971  // tree.print();
972  auto final_state_xs = tree.final_state_cross_sections();
973  deduplicate(final_state_xs);
974  for (const auto& p : final_state_xs) {
975  // Don't print empty columns.
976  //
977  // FIXME(steinberg): The better fix would be to not have them in the
978  // first place.
979  if (p.name_ == "") {
980  continue;
981  }
982  outgoing_total_mass[p.name_] = p.mass_;
983  xs_dump[p.name_].push_back(std::make_pair(sqrts, p.cross_section_));
984  }
985  }
986  }
987  // Get rid of cross sections that are zero.
988  // (This only happens if their is a resonance in the final state that cannot
989  // decay with our simplified assumptions.)
990  for (auto it = begin(xs_dump); it != end(xs_dump);) {
991  // Sum cross section over all energies.
992  const xs_saver& xs = (*it).second;
993  double sum = 0;
994  for (const auto& p : xs) {
995  sum += p.second;
996  }
997  if (sum == 0.) {
998  it = xs_dump.erase(it);
999  } else {
1000  ++it;
1001  }
1002  }
1003 
1004  // Nice ordering of channels by summed pole mass of products
1005  std::vector<std::string> all_channels;
1006  for (const auto& channel : xs_dump) {
1007  all_channels.push_back(channel.first);
1008  }
1009  std::sort(all_channels.begin(), all_channels.end(),
1010  [&](const std::string& str_a, const std::string& str_b) {
1011  return outgoing_total_mass[str_a] < outgoing_total_mass[str_b];
1012  });
1013 
1014  // Print header
1015  std::cout << "# Dumping partial " << a.name() << b.name()
1016  << " cross-sections in mb, energies in GeV" << std::endl;
1017  std::cout << " sqrt_s";
1018  // Align everything to 16 unicode characters.
1019  // This should be enough for the longest channel name (7 final-state
1020  // particles).
1021  for (const auto& channel : all_channels) {
1022  std::cout << utf8::fill_left(channel, 16, ' ');
1023  }
1024  std::cout << std::endl;
1025 
1026  // Print out all partial cross-sections in mb
1027  for (int i = 0; i < n_momentum_points; i++) {
1028  double momentum;
1029  if (plab.size() > 0) {
1030  momentum = pCM_from_s(s_from_plab(plab.at(i), m_a, m_b), m_a, m_b);
1031  } else {
1032  momentum = momentum_step * (i + 1);
1033  }
1034  a_data.set_4momentum(m_a, momentum, 0.0, 0.0);
1035  b_data.set_4momentum(m_b, -momentum, 0.0, 0.0);
1036  const double sqrts = (a_data.momentum() + b_data.momentum()).abs();
1037  std::printf("%9.6f", sqrts);
1038  for (const auto& channel : all_channels) {
1039  const xs_saver energy_and_xs = xs_dump[channel];
1040  size_t j = 0;
1041  for (; j < energy_and_xs.size() && energy_and_xs[j].first < sqrts; j++) {
1042  }
1043  double xs = 0.0;
1044  if (j < energy_and_xs.size() &&
1045  std::abs(energy_and_xs[j].first - sqrts) < really_small) {
1046  xs = energy_and_xs[j].second;
1047  }
1048  std::printf("%16.6f", xs); // Same alignment as in the header.
1049  }
1050  std::printf("\n");
1051  }
1052 }
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 265 of file scatteractionsfinder.h.

265  {
267  return string_process_interface_.get();
268  } else {
269  return NULL;
270  }
271  }

◆ 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 [5] (3.27). 2. A stochastic collision criterion as introduced in Staudenmaier:2021lrg [56].

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 187 of file scatteractionsfinder.cc.

190  {
191  /* If the two particles
192  * 1) belong to one of the two colliding nuclei, and
193  * 2) both of them have never experienced any collisions,
194  * then the collisions between them are banned. */
196  assert(data_a.id() >= 0);
197  assert(data_b.id() >= 0);
198  bool in_same_nucleus = (data_a.belongs_to() == BelongsTo::Projectile &&
199  data_b.belongs_to() == BelongsTo::Projectile) ||
200  (data_a.belongs_to() == BelongsTo::Target &&
201  data_b.belongs_to() == BelongsTo::Target);
202  bool never_interacted_before =
203  data_a.get_history().collisions_per_particle == 0 &&
204  data_b.get_history().collisions_per_particle == 0;
205  if (in_same_nucleus && never_interacted_before) {
206  return nullptr;
207  }
208  }
209 
210  // No grid or search in cell means no collision for stochastic criterion
212  gcell_vol < really_small) {
213  return nullptr;
214  }
215 
216  // Determine time of collision.
217  const double time_until_collision =
218  collision_time(data_a, data_b, dt, beam_momentum);
219 
220  // Check that collision happens in this timestep.
221  if (time_until_collision < 0. || time_until_collision >= dt) {
222  return nullptr;
223  }
224 
225  // Create ScatterAction object.
226  ScatterActionPtr act = std::make_unique<ScatterAction>(
227  data_a, data_b, time_until_collision, isotropic_, string_formation_time_,
228  box_length_);
229 
231  act->set_stochastic_pos_idx();
232  }
233 
235  act->set_string_interface(string_process_interface_.get());
236  }
237 
238  // Distance squared calculation not needed for stochastic criterion
239  const double distance_squared =
241  ? act->transverse_distance_sqr()
243  ? act->cov_transverse_distance_sqr()
244  : 0.0;
245 
246  // Don't calculate cross section if the particles are very far apart.
247  // Not needed for stochastic criterion because of cell structure.
249  distance_squared >=
251  return nullptr;
252  }
253 
254  // Add various subprocesses.
255  act->add_all_scatterings(finder_parameters_);
256  double xs = act->cross_section() * fm2_mb /
257  static_cast<double>(finder_parameters_.testparticles);
258 
259  // Take cross section scaling factors into account
260  xs *= data_a.xsec_scaling_factor(time_until_collision);
261  xs *= data_b.xsec_scaling_factor(time_until_collision);
262 
264  const double v_rel = act->relative_velocity();
265  /* Collision probability for 2-particle scattering, see
266  * \iref{Staudenmaier:2021lrg}. */
267  const double prob = xs * v_rel * dt / gcell_vol;
268 
269  logg[LFindScatter].debug(
270  "Stochastic collison criterion parameters (2-particles):\nprob = ",
271  prob, ", xs = ", xs, ", v_rel = ", v_rel, ", dt = ", dt,
272  ", gcell_vol = ", gcell_vol,
273  ", testparticles = ", finder_parameters_.testparticles);
274 
275  if (prob > 1.) {
276  std::stringstream err;
277  err << "Probability larger than 1 for stochastic rates. ( P_22 = " << prob
278  << " )\n"
279  << data_a.type().name() << data_b.type().name() << " with masses "
280  << data_a.momentum().abs() << " and " << data_b.momentum().abs()
281  << " at sqrts[GeV] = " << act->sqrt_s()
282  << " with xs[fm^2]/Ntest = " << xs
283  << "\nConsider using smaller timesteps.";
285  logg[LFindScatter].warn(err.str());
286  } else {
287  throw std::runtime_error(err.str());
288  }
289  }
290 
291  // probability criterion
292  double random_no = random::uniform(0., 1.);
293  if (random_no > prob) {
294  return nullptr;
295  }
296 
299  // just collided with this particle
300  if (data_a.id_process() > 0 && data_a.id_process() == data_b.id_process()) {
301  logg[LFindScatter].debug("Skipping collided particles at time ",
302  data_a.position().x0(), " due to process ",
303  data_a.id_process(), "\n ", data_a, "\n<-> ",
304  data_b);
305 
306  return nullptr;
307  }
308 
309  // Cross section for collision criterion
310  const double cross_section_criterion = xs * M_1_PI;
311 
312  // distance criterion according to cross_section
313  if (distance_squared >= cross_section_criterion) {
314  return nullptr;
315  }
316 
317  logg[LFindScatter].debug("particle distance squared: ", distance_squared,
318  "\n ", data_a, "\n<-> ", data_b);
319  }
320 
321  return act;
322 }
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.
@ Geometric
(Default) geometric criterion.
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 bool allow_collisions_within_nucleus
If particles within the same nucleus are allowed to collide for their first time.

◆ 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 [56]. 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 324 of file scatteractionsfinder.cc.

325  {
326  /* If all particles
327  * 1) belong to the two colliding nuclei
328  * 2) are within the same nucleus
329  * 3) have never experienced any collisons,
330  * then the collision between them are banned also for multi-particle
331  * interactions. */
333  bool all_projectile =
334  std::all_of(plist.begin(), plist.end(), [&](const ParticleData& data) {
335  return data.belongs_to() == BelongsTo::Projectile;
336  });
337  bool all_target =
338  std::all_of(plist.begin(), plist.end(), [&](const ParticleData& data) {
339  return data.belongs_to() == BelongsTo::Target;
340  });
341  bool none_collided =
342  std::all_of(plist.begin(), plist.end(), [&](const ParticleData& data) {
343  return data.get_history().collisions_per_particle == 0;
344  });
345  if ((all_projectile || all_target) && none_collided) {
346  return nullptr;
347  }
348  }
349  // No grid or search in cell
350  if (gcell_vol < really_small) {
351  return nullptr;
352  }
353 
354  /* Optimisation for later: Already check here at the beginning
355  * if collision with plist is possible before constructing actions. */
356 
357  // 1. Determine time of collision.
358  const double time_until_collision = dt * random::uniform(0., 1.);
359 
360  // 2. Create ScatterAction object.
361  ScatterActionMultiPtr act =
362  std::make_unique<ScatterActionMulti>(plist, time_until_collision);
363 
364  act->set_stochastic_pos_idx();
365 
366  // 3. Add possible final states (dt and gcell_vol for probability calculation)
367  act->add_possible_reactions(dt, gcell_vol, finder_parameters_.included_multi);
368 
369  /* 4. Return total collision probability
370  * Scales with 1 over the number of testpartciles to the power of the
371  * number of incoming particles - 1 */
372  const double prob =
373  act->get_total_weight() /
374  std::pow(finder_parameters_.testparticles, plist.size() - 1);
375 
376  // 5. Check that probability is smaller than one
377  if (prob > 1.) {
378  std::stringstream err;
379  err << "Probability " << prob << " larger than 1 for stochastic rates for ";
380  for (const ParticleData& data : plist) {
381  err << data.type().name();
382  }
383  err << " at sqrts[GeV] = " << act->sqrt_s()
384  << "\nConsider using smaller timesteps.";
386  logg[LFindScatter].warn(err.str());
387  } else {
388  throw std::runtime_error(err.str());
389  }
390  }
391 
392  // 6. Perform probability decisions
393  double random_no = random::uniform(0., 1.);
394  if (random_no > prob) {
395  return nullptr;
396  }
397 
398  return act;
399 }
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 320 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 322 of file scatteractionsfinder.h.

◆ isotropic_

const bool smash::ScatterActionsFinder::isotropic_
private

Do all collisions isotropically.

Definition at line 324 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 330 of file scatteractionsfinder.h.

◆ string_formation_time_

const double smash::ScatterActionsFinder::string_formation_time_
private

Parameter for formation time.

Definition at line 332 of file scatteractionsfinder.h.


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