Version: SMASH-1.6
scatteractionsfinder.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2019
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
11 
12 #include <algorithm>
13 #include <map>
14 #include <vector>
15 
16 #include "smash/configuration.h"
17 #include "smash/constants.h"
18 #include "smash/crosssections.h"
19 #include "smash/cxx14compat.h"
20 #include "smash/decaymodes.h"
22 #include "smash/isoparticletype.h"
23 #include "smash/logging.h"
24 #include "smash/macros.h"
25 #include "smash/particles.h"
26 #include "smash/scatteraction.h"
28 #include "smash/stringfunctions.h"
29 
30 namespace smash {
209  Configuration config, const ExperimentParameters& parameters,
210  const std::vector<bool>& nucleon_has_interacted, int N_tot, int N_proj)
211  : elastic_parameter_(
212  config.take({"Collision_Term", "Elastic_Cross_Section"}, -1.)),
213  testparticles_(parameters.testparticles),
214  isotropic_(config.take({"Collision_Term", "Isotropic"}, false)),
215  two_to_one_(parameters.two_to_one),
216  incl_set_(parameters.included_2to2),
217  low_snn_cut_(parameters.low_snn_cut),
218  strings_switch_(parameters.strings_switch),
219  use_AQM_(parameters.use_AQM),
220  strings_with_probability_(parameters.strings_with_probability),
221  nnbar_treatment_(parameters.nnbar_treatment),
222  nucleon_has_interacted_(nucleon_has_interacted),
223  N_tot_(N_tot),
224  N_proj_(N_proj),
225  string_formation_time_(config.take(
226  {"Collision_Term", "String_Parameters", "Formation_Time"}, 1.)) {
228  const auto& log = logger<LogArea::FindScatter>();
229  log.info("Constant elastic isotropic cross-section mode:", " using ",
230  elastic_parameter_, " mb as maximal cross-section.");
231  }
232  if (strings_switch_) {
233  auto subconfig = config["Collision_Term"]["String_Parameters"];
234  string_process_interface_ = make_unique<StringProcess>(
235  subconfig.take({"String_Tension"}, 1.0), string_formation_time_,
236  subconfig.take({"Gluon_Beta"}, 0.5),
237  subconfig.take({"Gluon_Pmin"}, 0.001),
238  subconfig.take({"Quark_Alpha"}, 2.0),
239  subconfig.take({"Quark_Beta"}, 7.0),
240  subconfig.take({"Strange_Supp"}, 0.16),
241  subconfig.take({"Diquark_Supp"}, 0.036),
242  subconfig.take({"Sigma_Perp"}, 0.42),
243  subconfig.take({"StringZ_A_Leading"}, 0.2),
244  subconfig.take({"StringZ_B_Leading"}, 2.0),
245  subconfig.take({"StringZ_A"}, 2.0), subconfig.take({"StringZ_B"}, 0.55),
246  subconfig.take({"String_Sigma_T"}, 0.5),
247  subconfig.take({"Form_Time_Factor"}, 1.0),
248  subconfig.take({"Mass_Dependent_Formation_Times"}, false),
249  subconfig.take({"Prob_proton_to_d_uu"}, 1. / 3.),
250  subconfig.take({"Separate_Fragment_Baryon"}, true),
251  subconfig.take({"Popcorn_Rate"}, 0.15));
252  }
253 }
254 
256  const ParticleData& data_b,
257  double dt) const {
258 #ifndef NDEBUG
259  const auto& log = logger<LogArea::FindScatter>();
260 #endif
261 
262  // just collided with this particle
263  if (data_a.id_process() > 0 && data_a.id_process() == data_b.id_process()) {
264 #ifndef NDEBUG
265  log.debug("Skipping collided particles at time ", data_a.position().x0(),
266  " due to process ", data_a.id_process(), "\n ", data_a,
267  "\n<-> ", data_b);
268 #endif
269  return nullptr;
270  }
271  /* If the two particles
272  * 1) belong to the two colliding nuclei
273  * 2) are within the same nucleus
274  * 3) both of them have never experienced any collisons,
275  * then the collision between them are banned. */
276  assert(data_a.id() >= 0);
277  assert(data_b.id() >= 0);
278  if (data_a.id() < N_tot_ && data_b.id() < N_tot_ &&
279  ((data_a.id() < N_proj_ && data_b.id() < N_proj_) ||
280  (data_a.id() >= N_proj_ && data_b.id() >= N_proj_)) &&
281  !(nucleon_has_interacted_[data_a.id()] ||
282  nucleon_has_interacted_[data_b.id()])) {
283  return nullptr;
284  }
285 
286  // Determine time of collision.
287  const double time_until_collision = collision_time(data_a, data_b);
288 
289  // Check that collision happens in this timestep.
290  if (time_until_collision < 0. || time_until_collision >= dt) {
291  return nullptr;
292  }
293 
294  // Create ScatterAction object.
295  ScatterActionPtr act = make_unique<ScatterAction>(
296  data_a, data_b, time_until_collision, isotropic_, string_formation_time_);
297  if (strings_switch_) {
298  act->set_string_interface(string_process_interface_.get());
299  }
300 
301  const double distance_squared = act->transverse_distance_sqr();
302 
303  // Don't calculate cross section if the particles are very far apart.
304  if (distance_squared >= max_transverse_distance_sqr(testparticles_)) {
305  return nullptr;
306  }
307 
308  // Add various subprocesses.
309  act->add_all_scatterings(elastic_parameter_, two_to_one_, incl_set_,
312 
313  // Cross section for collision criterion
314  double cross_section_criterion = act->cross_section() * fm2_mb * M_1_PI /
315  static_cast<double>(testparticles_);
316  // Take cross section scaling factors into account
317  cross_section_criterion *= data_a.xsec_scaling_factor(time_until_collision);
318  cross_section_criterion *= data_b.xsec_scaling_factor(time_until_collision);
319 
320  // distance criterion according to cross_section
321  if (distance_squared >= cross_section_criterion) {
322  return nullptr;
323  }
324 
325 #ifndef NDEBUG
326  log.debug("particle distance squared: ", distance_squared, "\n ", data_a,
327  "\n<-> ", data_b);
328 #endif
329 
330  // Using std::move here is redundant with newer compilers, but required for
331  // supporting GCC 4.8. Once we drop this support, std::move should be removed.
332  return std::move(act);
333 }
334 
336  const ParticleList& search_list, double dt) const {
337  std::vector<ActionPtr> actions;
338  for (const ParticleData& p1 : search_list) {
339  for (const ParticleData& p2 : search_list) {
340  if (p1.id() < p2.id()) {
341  // Check if a collision is possible.
342  ActionPtr act = check_collision(p1, p2, dt);
343  if (act) {
344  actions.push_back(std::move(act));
345  }
346  }
347  }
348  }
349  return actions;
350 }
351 
353  const ParticleList& search_list, const ParticleList& neighbors_list,
354  double dt) const {
355  std::vector<ActionPtr> actions;
356  for (const ParticleData& p1 : search_list) {
357  for (const ParticleData& p2 : neighbors_list) {
358  assert(p1.id() != p2.id());
359  // Check if a collision is possible.
360  ActionPtr act = check_collision(p1, p2, dt);
361  if (act) {
362  actions.push_back(std::move(act));
363  }
364  }
365  }
366  return actions;
367 }
368 
370  const ParticleList& search_list, const Particles& surrounding_list,
371  double dt) const {
372  std::vector<ActionPtr> actions;
373  for (const ParticleData& p2 : surrounding_list) {
374  /* don't look for collisions if the particle from the surrounding list is
375  * also in the search list */
376  auto result = std::find_if(
377  search_list.begin(), search_list.end(),
378  [&p2](const ParticleData& p) { return p.id() == p2.id(); });
379  if (result != search_list.end()) {
380  continue;
381  }
382  for (const ParticleData& p1 : search_list) {
383  // Check if a collision is possible.
384  ActionPtr act = check_collision(p1, p2, dt);
385  if (act) {
386  actions.push_back(std::move(act));
387  }
388  }
389  }
390  return actions;
391 }
392 
394  constexpr double time = 0.0;
395 
396  const size_t N_isotypes = IsoParticleType::list_all().size();
397  const size_t N_pairs = N_isotypes * (N_isotypes - 1) / 2;
398 
399  std::cout << N_isotypes << " iso-particle types." << std::endl;
400  std::cout << "They can make " << N_pairs << " pairs." << std::endl;
401  std::vector<double> momentum_scan_list = {0.1, 0.3, 0.5, 1.0,
402  2.0, 3.0, 5.0, 10.0};
403  for (const IsoParticleType& A_isotype : IsoParticleType::list_all()) {
404  for (const IsoParticleType& B_isotype : IsoParticleType::list_all()) {
405  if (&A_isotype > &B_isotype) {
406  continue;
407  }
408  bool any_nonzero_cs = false;
409  std::vector<std::string> r_list;
410  for (const ParticleTypePtr A_type : A_isotype.get_states()) {
411  for (const ParticleTypePtr B_type : B_isotype.get_states()) {
412  if (A_type > B_type) {
413  continue;
414  }
415  ParticleData A(*A_type), B(*B_type);
416  for (auto mom : momentum_scan_list) {
417  A.set_4momentum(A.pole_mass(), mom, 0.0, 0.0);
418  B.set_4momentum(B.pole_mass(), -mom, 0.0, 0.0);
419  ScatterActionPtr act = make_unique<ScatterAction>(
420  A, B, time, isotropic_, string_formation_time_);
421  if (strings_switch_) {
422  act->set_string_interface(string_process_interface_.get());
423  }
424  act->add_all_scatterings(elastic_parameter_, two_to_one_, incl_set_,
428  const double total_cs = act->cross_section();
429  if (total_cs <= 0.0) {
430  continue;
431  }
432  any_nonzero_cs = true;
433  for (const auto& channel : act->collision_channels()) {
434  const auto type = channel->get_type();
435  std::string r;
436  if (is_string_soft_process(type) ||
437  type == ProcessType::StringHard) {
438  r = A_type->name() + B_type->name() + std::string(" → strings");
439  } else {
440  std::string r_type =
441  (type == ProcessType::Elastic)
442  ? std::string(" (el)")
443  : (channel->get_type() == ProcessType::TwoToTwo)
444  ? std::string(" (inel)")
445  : std::string(" (?)");
446  r = A_type->name() + B_type->name() + std::string(" → ") +
447  channel->particle_types()[0]->name() +
448  channel->particle_types()[1]->name() + r_type;
449  }
450  isoclean(r);
451  r_list.push_back(r);
452  }
453  }
454  }
455  }
456  std::sort(r_list.begin(), r_list.end());
457  r_list.erase(std::unique(r_list.begin(), r_list.end()), r_list.end());
458  if (any_nonzero_cs) {
459  for (auto r : r_list) {
460  std::cout << r;
461  if (r_list.back() != r) {
462  std::cout << ", ";
463  }
464  }
465  std::cout << std::endl;
466  }
467  }
468  }
469 }
470 
474  std::string name_;
475 
478 
480  double mass_;
481 
490  FinalStateCrossSection(const std::string& name, double cross_section,
491  double mass)
492  : name_(name), cross_section_(cross_section), mass_(mass) {}
493 };
494 
495 namespace decaytree {
496 
508 struct Node {
509  public:
511  std::string name_;
512 
514  double weight_;
515 
517  ParticleTypePtrList initial_particles_;
518 
520  ParticleTypePtrList final_particles_;
521 
523  ParticleTypePtrList state_;
524 
526  std::vector<Node> children_;
527 
529  Node(const Node&) = delete;
531  Node(Node&&) = default;
532 
543  Node(const std::string& name, double weight,
544  ParticleTypePtrList&& initial_particles,
545  ParticleTypePtrList&& final_particles, ParticleTypePtrList&& state,
546  std::vector<Node>&& children)
547  : name_(name),
548  weight_(weight),
549  initial_particles_(std::move(initial_particles)),
550  final_particles_(std::move(final_particles)),
551  state_(std::move(state)),
552  children_(std::move(children)) {}
553 
565  Node& add_action(const std::string& name, double weight,
566  ParticleTypePtrList&& initial_particles,
567  ParticleTypePtrList&& final_particles) {
568  // Copy parent state and update it.
569  ParticleTypePtrList state(state_);
570  for (const auto& p : initial_particles) {
571  state.erase(std::find(state.begin(), state.end(), p));
572  }
573  for (const auto& p : final_particles) {
574  state.push_back(p);
575  }
576  // Sort the state to normalize the output.
577  std::sort(state.begin(), state.end(),
579  return a->name() < b->name();
580  });
581  // Push new node to children.
582  Node new_node(name, weight, std::move(initial_particles),
583  std::move(final_particles), std::move(state), {});
584  children_.emplace_back(std::move(new_node));
585  return children_.back();
586  }
587 
589  void print() const { print_helper(0); }
590 
594  std::vector<FinalStateCrossSection> final_state_cross_sections() const {
595  std::vector<FinalStateCrossSection> result;
596  final_state_cross_sections_helper(0, result, "", 1.);
597  return result;
598  }
599 
600  private:
607  void print_helper(uint64_t depth) const {
608  for (uint64_t i = 0; i < depth; i++) {
609  std::cout << " ";
610  }
611  std::cout << name_ << " " << weight_ << std::endl;
612  for (const auto& child : children_) {
613  child.print_helper(depth + 1);
614  }
615  }
616 
629  uint64_t depth, std::vector<FinalStateCrossSection>& result,
630  const std::string& name, double weight,
631  bool show_intermediate_states = false) const {
632  // The first node corresponds to the total cross section and has to be
633  // ignored. The second node corresponds to the partial cross section. All
634  // further nodes correspond to branching ratios.
635  if (depth > 0) {
636  weight *= weight_;
637  }
638 
639  std::string new_name;
640  double mass = 0.;
641 
642  if (show_intermediate_states) {
643  new_name = name;
644  if (!new_name.empty()) {
645  new_name += "->";
646  }
647  new_name += name_;
648  new_name += "{";
649  } else {
650  new_name = "";
651  }
652  for (const auto& s : state_) {
653  new_name += s->name();
654  mass += s->mass();
655  }
656  if (show_intermediate_states) {
657  new_name += "}";
658  }
659 
660  if (children_.empty()) {
661  result.emplace_back(FinalStateCrossSection(new_name, weight, mass));
662  return;
663  }
664  for (const auto& child : children_) {
665  child.final_state_cross_sections_helper(depth + 1, result, new_name,
666  weight, show_intermediate_states);
667  }
668  }
669 };
670 
679 static std::string make_decay_name(const std::string& res_name,
680  const DecayBranchPtr& decay,
681  ParticleTypePtrList& final_state) {
682  std::stringstream name;
683  name << "[" << res_name << "->";
684  for (const auto& p : decay->particle_types()) {
685  name << p->name();
686  final_state.push_back(p);
687  }
688  name << "]";
689  return name.str();
690 }
691 
698 static void add_decays(Node& node, double sqrts) {
699  // If there is more than one unstable particle in the current state, then
700  // there will be redundant paths in the decay tree, corresponding to
701  // reorderings of the decays. To avoid double counting, we normalize by the
702  // number of possible decay orderings. Normalizing by the number of unstable
703  // particles recursively corresponds to normalizing by the factorial that
704  // gives the number of reorderings.
705  //
706  // Ideally, the redundant paths should never be added to the decay tree, but
707  // we never have more than two redundant paths, so it probably does not matter
708  // much.
709  uint32_t n_unstable = 0;
710  double sqrts_minus_masses = sqrts;
711  for (const ParticleTypePtr ptype : node.state_) {
712  if (!ptype->is_stable()) {
713  n_unstable += 1;
714  }
715  sqrts_minus_masses -= ptype->mass();
716  }
717  const double norm =
718  n_unstable != 0 ? 1. / static_cast<double>(n_unstable) : 1.;
719 
720  for (const ParticleTypePtr ptype : node.state_) {
721  if (!ptype->is_stable()) {
722  const double sqrts_decay = sqrts_minus_masses + ptype->mass();
723  for (const auto& decay : ptype->decay_modes().decay_mode_list()) {
724  // Make sure to skip kinematically impossible decays.
725  // In principle, we would have to integrate over the mass of the
726  // resonance, but as an approximation we just assume it at its pole.
727  double final_state_mass = 0.;
728  for (const auto& p : decay->particle_types()) {
729  final_state_mass += p->mass();
730  }
731  if (final_state_mass > sqrts_decay) {
732  continue;
733  }
734 
735  ParticleTypePtrList parts;
736  const auto name = make_decay_name(ptype->name(), decay, parts);
737  auto& new_node = node.add_action(name, norm * decay->weight(), {ptype},
738  std::move(parts));
739  add_decays(new_node, sqrts_decay);
740  }
741  }
742  }
743 }
744 
745 } // namespace decaytree
746 
752 static void deduplicate(std::vector<FinalStateCrossSection>& final_state_xs) {
753  std::sort(final_state_xs.begin(), final_state_xs.end(),
754  [](const FinalStateCrossSection& a,
755  const FinalStateCrossSection& b) { return a.name_ < b.name_; });
756  auto current = final_state_xs.begin();
757  while (current != final_state_xs.end()) {
758  auto adjacent = std::adjacent_find(
759  current, final_state_xs.end(),
760  [](const FinalStateCrossSection& a, const FinalStateCrossSection& b) {
761  return a.name_ == b.name_;
762  });
763  current = adjacent;
764  if (adjacent != final_state_xs.end()) {
765  adjacent->cross_section_ += (adjacent + 1)->cross_section_;
766  final_state_xs.erase(adjacent + 1);
767  }
768  }
769 }
770 
772  const ParticleType& a, const ParticleType& b, double m_a, double m_b,
773  bool final_state, std::vector<double>& plab) const {
774  typedef std::vector<std::pair<double, double>> xs_saver;
775  std::map<std::string, xs_saver> xs_dump;
776  std::map<std::string, double> outgoing_total_mass;
777 
778  ParticleData a_data(a), b_data(b);
779  int n_momentum_points = 200;
780  constexpr double momentum_step = 0.02;
781  /*
782  // Round to output precision.
783  for (auto& p : plab) {
784  p = std::floor((p * 100000) + 0.5) / 100000;
785  }
786  */
787  if (plab.size() > 0) {
788  n_momentum_points = plab.size();
789  // Remove duplicates.
790  std::sort(plab.begin(), plab.end());
791  plab.erase(std::unique(plab.begin(), plab.end()), plab.end());
792  }
793  for (int i = 0; i < n_momentum_points; i++) {
794  double momentum;
795  if (plab.size() > 0) {
796  momentum = pCM_from_s(s_from_plab(plab.at(i), m_a, m_b), m_a, m_b);
797  } else {
798  momentum = momentum_step * (i + 1);
799  }
800  a_data.set_4momentum(m_a, momentum, 0.0, 0.0);
801  b_data.set_4momentum(m_b, -momentum, 0.0, 0.0);
802  const double sqrts = (a_data.momentum() + b_data.momentum()).abs();
803  const ParticleList incoming = {a_data, b_data};
804  ScatterActionPtr act = make_unique<ScatterAction>(
805  a_data, b_data, 0., isotropic_, string_formation_time_);
806  if (strings_switch_) {
807  act->set_string_interface(string_process_interface_.get());
808  }
809  act->add_all_scatterings(elastic_parameter_, two_to_one_, incl_set_,
812  decaytree::Node tree(a.name() + b.name(), act->cross_section(), {&a, &b},
813  {&a, &b}, {&a, &b}, {});
814  const CollisionBranchList& processes = act->collision_channels();
815  for (const auto& process : processes) {
816  const double xs = process->weight();
817  if (xs <= 0.0) {
818  continue;
819  }
820  if (!final_state) {
821  std::stringstream process_description_stream;
822  process_description_stream << *process;
823  const std::string& description = process_description_stream.str();
824  double m_tot = 0.0;
825  for (const auto& ptype : process->particle_types()) {
826  m_tot += ptype->mass();
827  }
828  outgoing_total_mass[description] = m_tot;
829  if (!xs_dump[description].empty() &&
830  std::abs(xs_dump[description].back().first - sqrts) <
831  really_small) {
832  xs_dump[description].back().second += xs;
833  } else {
834  xs_dump[description].push_back(std::make_pair(sqrts, xs));
835  }
836  } else {
837  std::stringstream process_description_stream;
838  process_description_stream << *process;
839  const std::string& description = process_description_stream.str();
840  ParticleTypePtrList initial_particles = {&a, &b};
841  ParticleTypePtrList final_particles = process->particle_types();
842  auto& process_node =
843  tree.add_action(description, xs, std::move(initial_particles),
844  std::move(final_particles));
845  decaytree::add_decays(process_node, sqrts);
846  }
847  }
848  xs_dump["total"].push_back(std::make_pair(sqrts, act->cross_section()));
849  // Total cross-section should be the first in the list -> negative mass
850  outgoing_total_mass["total"] = -1.0;
851  if (final_state) {
852  // tree.print();
853  auto final_state_xs = tree.final_state_cross_sections();
854  deduplicate(final_state_xs);
855  for (const auto& p : final_state_xs) {
856  // Don't print empty columns.
857  //
858  // FIXME(steinberg): The better fix would be to not have them in the
859  // first place.
860  if (p.name_ == "") {
861  continue;
862  }
863  outgoing_total_mass[p.name_] = p.mass_;
864  xs_dump[p.name_].push_back(std::make_pair(sqrts, p.cross_section_));
865  }
866  }
867  }
868 
869  // Nice ordering of channels by summed pole mass of products
870  std::vector<std::string> all_channels;
871  for (const auto channel : xs_dump) {
872  all_channels.push_back(channel.first);
873  }
874  std::sort(all_channels.begin(), all_channels.end(),
875  [&](const std::string& str_a, const std::string& str_b) {
876  return outgoing_total_mass[str_a] < outgoing_total_mass[str_b];
877  });
878 
879  // Print header
880  std::cout << "# Dumping partial " << a.name() << b.name()
881  << " cross-sections in mb, energies in GeV" << std::endl;
882  std::cout << " sqrt_s";
883  // Align everything to 16 unicode characters.
884  // This should be enough for the longest channel name (7 final-state
885  // particles).
886  for (const auto channel : all_channels) {
887  std::cout << utf8::fill_left(channel, 16, ' ');
888  }
889  std::cout << std::endl;
890 
891  // Print out all partial cross-sections in mb
892  for (int i = 0; i < n_momentum_points; i++) {
893  double momentum;
894  if (plab.size() > 0) {
895  momentum = pCM_from_s(s_from_plab(plab.at(i), m_a, m_b), m_a, m_b);
896  } else {
897  momentum = momentum_step * (i + 1);
898  }
899  a_data.set_4momentum(m_a, momentum, 0.0, 0.0);
900  b_data.set_4momentum(m_b, -momentum, 0.0, 0.0);
901  const double sqrts = (a_data.momentum() + b_data.momentum()).abs();
902  std::printf("%9.6f", sqrts);
903  for (const auto channel : all_channels) {
904  const xs_saver energy_and_xs = xs_dump[channel];
905  size_t j = 0;
906  for (; j < energy_and_xs.size() && energy_and_xs[j].first < sqrts; j++) {
907  }
908  double xs = 0.0;
909  if (j < energy_and_xs.size() &&
910  std::abs(energy_and_xs[j].first - sqrts) < really_small) {
911  xs = energy_and_xs[j].second;
912  }
913  std::printf("%16.6f", xs); // Same alignment as in the header.
914  }
915  std::printf("\n");
916  }
917 }
918 
919 } // namespace smash
static void add_decays(Node &node, double sqrts)
Add nodes for all decays possible from the given node and all of its children.
uint32_t id_process() const
Get the id of the last action.
Definition: particledata.h:115
ActionPtr check_collision(const ParticleData &data_a, const ParticleData &data_b, double dt) const
Check for a single pair of particles (id_a, id_b) if a collision will happen in the next timestep and...
std::string name_
Name of the final state.
static double collision_time(const ParticleData &p1, const ParticleData &p2)
Determine the collision time of the two particles.
double mass_
Total mass of final state particles.
static void deduplicate(std::vector< FinalStateCrossSection > &final_state_xs)
Deduplicate the final-state cross sections by summing.
const int testparticles_
Number of test particles.
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
const ReactionsBitSet incl_set_
List of included 2<->2 reactions.
bool is_string_soft_process(ProcessType p)
Check if a given process type is a soft string excitation.
const FourVector & position() const
Get the particle&#39;s position in Minkowski space.
Definition: particledata.h:185
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_.
const bool two_to_one_
Enable 2->1 processes.
bool is_stable() const
Definition: particletype.h:236
static std::string make_decay_name(const std::string &res_name, const DecayBranchPtr &decay, ParticleTypePtrList &final_state)
Generate name for decay and update final state.
const double low_snn_cut_
Elastic collsions between two nucleons with sqrt_s below low_snn_cut_ are excluded.
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.
const double string_formation_time_
Parameter for formation time.
void isoclean(std::string &s)
Remove ⁺, ⁻, ⁰ from string.
Collection of useful constants that are known at compile time.
const bool strings_with_probability_
Decide whether to implement string fragmentation based on a probability.
STL namespace.
T pCM_from_s(const T s, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:66
double max_transverse_distance_sqr(int testparticles) const
The maximal distance over which particles can interact, related to the number of test particles and t...
constexpr double fm2_mb
mb <-> fm^2 conversion factor.
Definition: constants.h:28
2->2 inelastic scattering
std::vector< Node > children_
Possible actions after this action.
const std::vector< bool > & nucleon_has_interacted_
Parameter to record whether the nucleon has experienced a collision or not.
Represent a final-state cross section.
Interface to the SMASH configuration files.
std::unique_ptr< StringProcess > string_process_interface_
Class that deals with strings, interfacing Pythia.
const bool strings_switch_
Switch to turn off string excitation.
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) an...
const DecayBranchList & decay_mode_list() const
Definition: decaymodes.h:63
double x0() const
Definition: fourvector.h:290
ParticleTypePtrList initial_particles_
Initial-state particle types in this action.
ActionList find_actions_in_cell(const ParticleList &search_list, double dt) const override
Search for all the possible collisions within one cell.
std::string name_
Name for printing.
void final_state_cross_sections_helper(uint64_t depth, std::vector< FinalStateCrossSection > &result, const std::string &name, double weight, bool show_intermediate_states=false) const
Internal helper function for final_state_cross_sections, to be called recursively to calculate all fi...
elastic scattering: particles remain the same, only momenta change
double mass() const
Definition: particletype.h:144
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:224
double weight_
Weight (cross section or branching ratio).
const std::string & name() const
Definition: particletype.h:141
Particle type contains the static properties of a particle species.
Definition: particletype.h:97
ScatterActionsFinder(Configuration config, const ExperimentParameters &parameters, const std::vector< bool > &nucleon_has_interacted, int N_tot, int N_proj)
Constructor of the finder with the given parameters.
void set_4momentum(const FourVector &momentum_vector)
Set the particle&#39;s 4-momentum directly.
Definition: particledata.h:145
IsoParticleType is a class to represent isospin multiplets.
const NNbarTreatment nnbar_treatment_
Switch for NNbar reactions.
hard string process involving 2->2 QCD process by PYTHIA.
FinalStateCrossSection(const std::string &name, double cross_section, double mass)
Construct a final-state cross section.
std::vector< FinalStateCrossSection > final_state_cross_sections() const
ParticleTypePtrList final_particles_
Final-state particle types in this action.
void dump_reactions() const
Prints out all the 2-> n (n > 1) reactions with non-zero cross-sections between all possible pairs of...
double pole_mass() const
Get the particle&#39;s pole mass ("on-shell").
Definition: particledata.h:96
constexpr int p
Proton.
const bool use_AQM_
Switch to control whether to use AQM or not.
const int N_proj_
Record the number of the nucleons in the projectile.
const bool isotropic_
Do all collisions isotropically.
void print_helper(uint64_t depth) const
Internal helper function for print, to be called recursively to print all nodes.
const int N_tot_
Record the total number of the nucleons in the two colliding nuclei.
A pointer-like interface to global references to ParticleType objects.
Definition: particletype.h:654
Node of a decay tree, representing a possible action (2-to-2 or 1-to-2).
ParticleTypePtrList state_
Particle types corresponding to the global state after this action.
void print() const
Print the decay tree starting with this node.
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
const DecayModes & decay_modes() const
Node(const std::string &name, double weight, ParticleTypePtrList &&initial_particles, ParticleTypePtrList &&final_particles, ParticleTypePtrList &&state, std::vector< Node > &&children)
int32_t id() const
Get the id of the particle.
Definition: particledata.h:70
double cross_section_
Corresponding cross section in mb.
Node & add_action(const std::string &name, double weight, ParticleTypePtrList &&initial_particles, ParticleTypePtrList &&final_particles)
Add an action to the children of this node.
ActionList find_actions_with_surrounding_particles(const ParticleList &search_list, const Particles &surrounding_list, double dt) const override
Search for all the possible secondary collisions between the outgoing particles and the rest...
Helper structure for Experiment.
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:52
const double elastic_parameter_
Elastic cross section parameter (in mb).
Definition: action.h:24
const FourVector & momentum() const
Get the particle&#39;s 4-momentum.
Definition: particledata.h:139
static const IsoParticleTypeList & list_all()
Returns a list of all IsoParticleTypes.
ActionList find_actions_with_neighbors(const ParticleList &search_list, const ParticleList &neighbors_list, double dt) const override
Search for all the possible collisions among the neighboring cells.