Version: SMASH-1.8
particletype.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 
10 #include "smash/particletype.h"
11 
12 #include <assert.h>
13 #include <algorithm>
14 #include <map>
15 #include <vector>
16 
17 #include "smash/constants.h"
18 #include "smash/cxx14compat.h"
19 #include "smash/decaymodes.h"
20 #include "smash/distributions.h"
21 #include "smash/formfactors.h"
22 #include "smash/inputfunctions.h"
23 #include "smash/integrate.h"
24 #include "smash/iomanipulators.h"
25 #include "smash/isoparticletype.h"
26 #include "smash/kinematics.h"
27 #include "smash/logging.h"
28 #include "smash/numerics.h"
29 #include "smash/particledata.h"
30 #include "smash/pdgcode.h"
32 #include "smash/pow.h"
33 #include "smash/processbranch.h"
34 #include "smash/stringfunctions.h"
35 
36 namespace smash {
37 static constexpr int LParticleType = LogArea::ParticleType::id;
38 static constexpr int LResonances = LogArea::Resonances::id;
39 
40 namespace {
42 const ParticleTypeList *all_particle_types = nullptr;
44 ParticleTypePtrList nucleons_list;
46 ParticleTypePtrList anti_nucs_list;
48 ParticleTypePtrList deltas_list;
50 ParticleTypePtrList anti_deltas_list;
52 ParticleTypePtrList baryon_resonances_list;
54 ParticleTypePtrList light_nuclei_list;
55 } // unnamed namespace
56 
57 const ParticleTypeList &ParticleType::list_all() {
58  assert(all_particle_types);
59  return *all_particle_types;
60 }
61 
62 // For performance reasonce one might want to inline this function.
64  // Calculate the offset via pointer subtraction:
65  const auto offset = this - std::addressof(list_all()[0]);
66  // Since we're using uint16_t for storing the index better be safe than sorry:
67  // The offset must fit into the data type. If this ever fails we got a lot
68  // more particle types than initially expected and you have to increase the
69  // ParticleTypePtr storage to uint32_t.
70  assert(offset >= 0 && offset < 0xffff);
71  // After the assertion above the down-cast to uint16_t is safe:
72  return ParticleTypePtr(static_cast<uint16_t>(offset));
73 }
74 
75 ParticleTypePtrList &ParticleType::list_nucleons() { return nucleons_list; }
76 
77 ParticleTypePtrList &ParticleType::list_anti_nucleons() {
78  return anti_nucs_list;
79 }
80 
81 ParticleTypePtrList &ParticleType::list_Deltas() { return deltas_list; }
82 
83 ParticleTypePtrList &ParticleType::list_anti_Deltas() {
84  return anti_deltas_list;
85 }
86 
87 ParticleTypePtrList &ParticleType::list_baryon_resonances() {
89 }
90 
91 ParticleTypePtrList &ParticleType::list_light_nuclei() {
92  return light_nuclei_list;
93 }
94 
96  const auto found = std::lower_bound(
98  [](const ParticleType &l, const PdgCode &r) { return l.pdgcode() < r; });
99  if (found == all_particle_types->end() || found->pdgcode() != pdgcode) {
100  return {}; // The default constructor creates an invalid pointer.
101  }
102  return &*found;
103 }
104 
106  const auto found = ParticleType::try_find(pdgcode);
107  if (!found) {
108  throw PdgNotFoundFailure("PDG code " + pdgcode.string() + " not found!");
109  }
110  return *found;
111 }
112 
114  const auto found = ParticleType::try_find(pdgcode);
115  return found;
116 }
117 
118 bool ParticleType::exists(const std::string &name) {
119  const auto found =
120  std::find_if(all_particle_types->begin(), all_particle_types->end(),
121  [&](const ParticleType &p) { return p.name() == name; });
122  if (found == all_particle_types->end()) {
123  return false;
124  }
125  return true;
126 }
127 
128 ParticleType::ParticleType(std::string n, double m, double w, Parity p,
129  PdgCode id)
130  : name_(n),
131  mass_(m),
132  width_(w),
133  parity_(p),
134  pdgcode_(id),
135  min_mass_kinematic_(-1.),
136  min_mass_spectral_(-1.),
137  charge_(pdgcode_.charge()),
138  isospin_(-1),
139  I3_(pdgcode_.isospin3()) {}
140 
149 static std::string antiname(const std::string &name, PdgCode code) {
150  std::string basename, charge;
151 
152  if (name.find("⁺⁺") != std::string::npos) {
153  basename = name.substr(0, name.length() - sizeof("⁺⁺") + 1);
154  charge = "⁻⁻";
155  } else if (name.find("⁺") != std::string::npos) {
156  basename = name.substr(0, name.length() - sizeof("⁺") + 1);
157  charge = "⁻";
158  } else if (name.find("⁻⁻") != std::string::npos) {
159  basename = name.substr(0, name.length() - sizeof("⁻⁻") + 1);
160  charge = "⁺⁺";
161  } else if (name.find("⁻") != std::string::npos) {
162  basename = name.substr(0, name.length() - sizeof("⁻") + 1);
163  charge = "⁺";
164  } else if (name.find("⁰") != std::string::npos) {
165  basename = name.substr(0, name.length() - sizeof("⁰") + 1);
166  charge = "⁰";
167  } else {
168  basename = name;
169  charge = "";
170  }
171 
172  // baryons & strange mesons: insert a bar
173  if (code.baryon_number() != 0 || code.strangeness() != 0) {
174  constexpr char bar[] = "\u0305";
175  basename.insert(utf8::sequence_length(basename.begin()), bar);
176  }
177 
178  return basename + charge;
179 }
180 
188 static std::string chargestr(int charge) {
189  switch (charge) {
190  case 2:
191  return "⁺⁺";
192  case 1:
193  return "⁺";
194  case 0:
195  return "⁰";
196  case -1:
197  return "⁻";
198  case -2:
199  return "⁻⁻";
200  default:
201  throw std::runtime_error("Invalid charge " + std::to_string(charge));
202  }
203 }
204 
205 void ParticleType::create_type_list(const std::string &input) { // {{{
206  static ParticleTypeList type_list;
207  type_list.clear(); // in case LoadFailure was thrown and caught and we should
208  // try again
209  for (const Line &line : line_parser(input)) {
210  std::istringstream lineinput(line.text);
211  std::string name;
212  double mass, width;
213  std::string parity_string;
214  std::vector<std::string> pdgcode_strings;
215  // We expect at most 4 PDG codes per multiplet.
216  pdgcode_strings.reserve(4);
217  lineinput >> name >> mass >> width >> parity_string;
218  Parity parity;
219  bool fail = false;
220  if (parity_string == "+") {
222  } else if (parity_string == "-") {
224  } else {
225  fail = true;
226  }
227  if (lineinput.fail() || fail) {
229  "While loading the ParticleType data:\nFailed to convert the input "
230  "string to the expected data types.",
231  line));
232  }
233  // read additional PDG codes (if present)
234  while (!lineinput.eof()) {
235  pdgcode_strings.push_back("");
236  lineinput >> pdgcode_strings.back();
237  if (lineinput.fail()) {
239  "While loading the ParticleType data:\nFailed to convert the input "
240  "string to the expected data types.",
241  line));
242  }
243  }
244  if (pdgcode_strings.size() < 1) {
246  "While loading the ParticleType data:\nFailed to convert the input "
247  "string due to missing PDG code.",
248  line));
249  }
250  std::vector<PdgCode> pdgcode;
251  pdgcode.resize(pdgcode_strings.size());
252  std::transform(pdgcode_strings.begin(), pdgcode_strings.end(),
253  pdgcode.begin(),
254  [](const std::string &s) { return PdgCode(s); });
255  ensure_all_read(lineinput, line);
256 
257  /* Check if nucleon, kaon, and delta masses are
258  * the same as hardcoded ones, if present */
260  throw std::runtime_error(
261  "Nucleon mass in input file different from 0.938");
262  }
263  if (pdgcode[0].is_kaon() && !almost_equal(mass, kaon_mass)) {
264  throw std::runtime_error("Kaon mass in input file different from 0.494");
265  }
266  if (pdgcode[0].is_Delta() && !almost_equal(mass, delta_mass)) {
267  throw std::runtime_error("Delta mass in input file different from 1.232");
268  }
270  throw std::runtime_error("d mass in input file different from 1.8756");
271  }
272 
273  // add all states to type list
274  for (size_t i = 0; i < pdgcode.size(); i++) {
275  std::string full_name = name;
276  if (pdgcode.size() > 1) {
277  // for multiplets: add charge string to name
278  full_name += chargestr(pdgcode[i].charge());
279  }
280  type_list.emplace_back(full_name, mass, width, parity, pdgcode[i]);
281  logg[LParticleType].debug()
282  << "Setting particle type: " << type_list.back();
283  if (pdgcode[i].has_antiparticle()) {
284  /* add corresponding antiparticle */
285  PdgCode anti = pdgcode[i].get_antiparticle();
286  // For bosons the parity does not change, for fermions it gets inverted.
287  const auto anti_parity = (anti.spin() % 2 == 0) ? parity : -parity;
288  full_name = antiname(full_name, pdgcode[i]);
289  type_list.emplace_back(full_name, mass, width, anti_parity, anti);
290  logg[LParticleType].debug()
291  << "Setting antiparticle type: " << type_list.back();
292  }
293  }
294  }
295  type_list.shrink_to_fit();
296 
297  /* Sort the type list by PDG code. */
298  std::sort(type_list.begin(), type_list.end());
299 
300  /* Look for duplicates. */
301  PdgCode prev_pdg = 0;
302  for (const auto &t : type_list) {
303  if (t.pdgcode() == prev_pdg) {
304  throw ParticleType::LoadFailure("Duplicate PdgCode in particles.txt: " +
305  t.pdgcode().string());
306  }
307  prev_pdg = t.pdgcode();
308  }
309 
310  if (all_particle_types != nullptr) {
311  throw std::runtime_error("Error: Type list was already built!");
312  }
313  all_particle_types = &type_list; // note that type_list is a function-local
314  // static and thus will live on until after
315  // main().
316 
317  // create all isospin multiplets
318  for (const auto &t : type_list) {
320  }
321  // link the multiplets to the types
322  for (auto &t : type_list) {
323  t.iso_multiplet_ = IsoParticleType::find(t);
324  }
325 
326  // Create nucleons/anti-nucleons list
327  if (IsoParticleType::exists("N")) {
328  for (const auto state : IsoParticleType::find("N").get_states()) {
329  nucleons_list.push_back(state);
330  anti_nucs_list.push_back(state->get_antiparticle());
331  }
332  }
333 
334  // Create deltas list
335  if (IsoParticleType::exists("Δ")) {
336  for (const auto state : IsoParticleType::find("Δ").get_states()) {
337  deltas_list.push_back(state);
338  anti_deltas_list.push_back(state->get_antiparticle());
339  }
340  }
341 
342  // Create baryon resonances list
343  for (const ParticleType &type_resonance : ParticleType::list_all()) {
344  /* Only loop over baryon resonances. */
345  if (type_resonance.is_stable() ||
346  type_resonance.pdgcode().baryon_number() != 1) {
347  continue;
348  }
349  baryon_resonances_list.push_back(&type_resonance);
350  baryon_resonances_list.push_back(type_resonance.get_antiparticle());
351  }
352 
353  for (const ParticleType &type : ParticleType::list_all()) {
354  if (type.is_nucleus()) {
355  light_nuclei_list.push_back(&type);
356  }
357  }
358 } /*}}}*/
359 
361  if (unlikely(min_mass_kinematic_ < 0.)) {
362  /* If the particle is stable, min. mass is just the mass. */
364  /* Otherwise, find the lowest mass value needed in any decay mode */
365  if (!is_stable()) {
366  for (const auto &mode : decay_modes().decay_mode_list()) {
367  min_mass_kinematic_ = std::min(min_mass_kinematic_, mode->threshold());
368  }
369  }
370  }
371  return min_mass_kinematic_;
372 }
373 
375  if (unlikely(min_mass_spectral_ < 0.)) {
376  /* If the particle is stable or it has a non-zero spectral function value at
377  * the minimum mass that is allowed by kinematics, min_mass_spectral is just
378  * the min_mass_kinetic. */
380  /* Otherwise, find the lowest mass value where spectral function has a
381  * non-zero value by bisection.*/
382  if (!is_stable() &&
384  // find a right bound that has non-zero spectral function for bisection
385  const double m_step = 0.01;
386  double right_bound_bis;
387  for (unsigned int i = 0;; i++) {
388  right_bound_bis = min_mass_kinematic() + m_step * i;
389  if (this->spectral_function(right_bound_bis) > really_small) {
390  break;
391  }
392  }
393  // bisection
394  const double precision = 1E-6;
395  double left_bound_bis = right_bound_bis - m_step;
396  while (right_bound_bis - left_bound_bis > precision) {
397  const double mid = (left_bound_bis + right_bound_bis) / 2.0;
398  if (this->spectral_function(mid) > really_small) {
399  right_bound_bis = mid;
400  } else {
401  left_bound_bis = mid;
402  }
403  }
404  min_mass_spectral_ = right_bound_bis;
405  }
406  }
407  return min_mass_spectral_;
408 }
409 
411  if (isospin_ < 0) {
414  : 0;
415  }
416  return isospin_;
417 }
418 
419 double ParticleType::partial_width(const double m,
420  const DecayBranch *mode) const {
421  if (m < mode->threshold()) {
422  return 0.;
423  }
424  double partial_width_at_pole = width_at_pole() * mode->weight();
425  return mode->type().width(mass(), partial_width_at_pole, m);
426 }
427 
429  const auto offset = this - std::addressof(list_all()[0]);
430  const auto &modes = (*DecayModes::all_decay_modes)[offset];
431  assert(is_stable() || !modes.is_empty());
432  return modes;
433 }
434 
435 double ParticleType::total_width(const double m) const {
436  double w = 0.;
437  if (is_stable()) {
438  return w;
439  }
440  /* Loop over decay modes and sum up all partial widths. */
441  const auto &modes = decay_modes().decay_mode_list();
442  for (unsigned int i = 0; i < modes.size(); i++) {
443  w = w + partial_width(m, modes[i].get());
444  }
445  if (w < width_cutoff) {
446  return 0.;
447  }
448  return w;
449 }
450 
452  for (const ParticleType &ptype : ParticleType::list_all()) {
453  if (!ptype.is_stable() && ptype.decay_modes().is_empty()) {
454  throw std::runtime_error("Unstable particle " + ptype.name() +
455  " has no decay chanels!");
456  }
457  }
458 }
459 
461  WhichDecaymodes wh) const {
462  const auto FinalTypes = t.particle_types();
463  switch (wh) {
464  case WhichDecaymodes::All: {
465  return true;
466  }
468  // No dileptons in final state particles for 2 or 3-body decays
469  return (
470  (t.particle_number() == 2 &&
471  !(is_dilepton(FinalTypes[0]->pdgcode(),
472  FinalTypes[1]->pdgcode()))) ||
473  (t.particle_number() == 3 &&
474  !(has_lepton_pair(FinalTypes[0]->pdgcode(), FinalTypes[1]->pdgcode(),
475  FinalTypes[2]->pdgcode()))));
476  }
478  // Lepton pair in final state particles for 2 or 3-body decays
479  return (
480  (t.particle_number() == 2 &&
481  is_dilepton(FinalTypes[0]->pdgcode(), FinalTypes[1]->pdgcode())) ||
482  (t.particle_number() == 3 &&
483  has_lepton_pair(FinalTypes[0]->pdgcode(), FinalTypes[1]->pdgcode(),
484  FinalTypes[2]->pdgcode())));
485  }
486  default:
487  throw std::runtime_error(
488  "Problem in selecting decaymodes in wanted_decaymode()");
489  }
490 }
491 
493  const ThreeVector x,
494  WhichDecaymodes wh) const {
495  const auto &decay_mode_list = decay_modes().decay_mode_list();
496  if (decay_mode_list.size() == 0 ||
497  (wh == WhichDecaymodes::Hadronic && is_stable())) {
498  return {};
499  }
500  /* Determine whether the decay is affected by the potentials. If it's
501  * affected, read the values of the potentials at the position of the
502  * particle */
503  FourVector UB = FourVector();
504  FourVector UI3 = FourVector();
505  if (UB_lat_pointer != nullptr) {
506  UB_lat_pointer->value_at(x, UB);
507  }
508  if (UI3_lat_pointer != nullptr) {
509  UI3_lat_pointer->value_at(x, UI3);
510  }
511  /* Loop over decay modes and calculate all partial widths. */
512  DecayBranchList partial;
513  partial.reserve(decay_mode_list.size());
514  for (unsigned int i = 0; i < decay_mode_list.size(); i++) {
515  /* Calculate the sqare root s of the final state particles. */
516  const auto FinalTypes = decay_mode_list[i]->type().particle_types();
517  double scale_B = 0.0;
518  double scale_I3 = 0.0;
519  if (pot_pointer != nullptr) {
520  scale_B += pot_pointer->force_scale(*this).first;
521  scale_I3 += pot_pointer->force_scale(*this).second * isospin3_rel();
522  for (const auto finaltype : FinalTypes) {
523  scale_B -= pot_pointer->force_scale(*finaltype).first;
524  scale_I3 -= pot_pointer->force_scale(*finaltype).second *
525  finaltype->isospin3_rel();
526  }
527  }
528  double sqrt_s = (p + UB * scale_B + UI3 * scale_I3).abs();
529 
530  const double w = partial_width(sqrt_s, decay_mode_list[i].get());
531  if (w > 0.) {
532  if (wanted_decaymode(decay_mode_list[i]->type(), wh)) {
533  partial.push_back(
534  make_unique<DecayBranch>(decay_mode_list[i]->type(), w));
535  }
536  }
537  }
538  return partial;
539 }
540 
541 double ParticleType::get_partial_width(const double m, const ParticleType &t_a,
542  const ParticleType &t_b) const {
543  /* Get all decay modes. */
544  const auto &decaymodes = decay_modes().decay_mode_list();
545 
546  /* Find the right one(s) and add up corresponding widths. */
547  double w = 0.;
548  for (const auto &mode : decaymodes) {
549  double partial_width_at_pole = width_at_pole() * mode->weight();
550  const ParticleTypePtrList l = {&t_a, &t_b};
551  if (mode->type().has_particles(l)) {
552  w += mode->type().width(mass(), partial_width_at_pole, m);
553  }
554  }
555  return w;
556 }
557 
559  const ParticleData &p_a,
560  const ParticleData &p_b) const {
561  /* Get all decay modes. */
562  const auto &decaymodes = decay_modes().decay_mode_list();
563 
564  /* Find the right one(s) and add up corresponding widths. */
565  double w = 0.;
566  for (const auto &mode : decaymodes) {
567  double partial_width_at_pole = width_at_pole() * mode->weight();
568  const ParticleTypePtrList l = {&p_a.type(), &p_b.type()};
569  if (mode->type().has_particles(l)) {
570  w += mode->type().in_width(mass(), partial_width_at_pole, m,
571  p_a.effective_mass(), p_b.effective_mass());
572  }
573  }
574  return w;
575 }
576 
577 double ParticleType::spectral_function(double m) const {
578  if (norm_factor_ < 0.) {
579  /* Initialize the normalization factor
580  * by integrating over the unnormalized spectral function. */
581  static /*thread_local (see #3075)*/ Integrator integrate;
582  const double width = width_at_pole();
583  const double m_pole = mass();
584  // We transform the integral using m = m_min + width_pole * tan(x), to
585  // make it definite and to avoid numerical issues.
586  const double x_min = std::atan((min_mass_kinematic() - m_pole) / width);
587  norm_factor_ = 1. / integrate(x_min, M_PI / 2., [&](double x) {
588  const double tanx = std::tan(x);
589  const double m_x = m_pole + width * tanx;
590  const double jacobian = width * (1.0 + tanx * tanx);
591  return spectral_function_no_norm(m_x) * jacobian;
592  });
593  }
595 }
596 
598  /* The spectral function is a relativistic Breit-Wigner function
599  * with mass-dependent width. Here: without normalization factor. */
600  const double resonance_width = total_width(m);
601  if (resonance_width < ParticleType::width_cutoff) {
602  return 0.;
603  }
604  return breit_wigner(m, mass(), resonance_width);
605 }
606 
608  /* The spectral function is a relativistic Breit-Wigner function.
609  * This variant is using a constant width (evaluated at the pole mass). */
610  const double resonance_width = width_at_pole();
611  if (resonance_width < ParticleType::width_cutoff) {
612  return 0.;
613  }
614  return breit_wigner(m, mass(), resonance_width);
615 }
616 
618  return breit_wigner_nonrel(m, mass(), width_at_pole());
619 }
620 
621 /* Resonance mass sampling for 2-particle final state */
622 double ParticleType::sample_resonance_mass(const double mass_stable,
623  const double cms_energy,
624  int L) const {
625  /* largest possible mass: Use 'nextafter' to make sure it is not above the
626  * physical limit by numerical error. */
627  const double max_mass = std::nextafter(cms_energy - mass_stable, 0.);
628 
629  // smallest possible mass to find non-zero spectral function contributions
630  const double min_mass = this->min_mass_spectral();
631 
632  // largest possible cm momentum (from smallest mass)
633  const double pcm_max = pCM(cms_energy, mass_stable, min_mass);
634  const double blw_max = pcm_max * blatt_weisskopf_sqr(pcm_max, L);
635  /* The maximum of the spectral-function ratio 'usually' happens at the
636  * largest mass. However, this is not always the case, therefore we need
637  * and additional fudge factor (determined automatically). Additionally,
638  * a heuristic knowledge is used that usually such mass exist that
639  * spectral_function(m) > spectral_function_simple(m). */
640  const double sf_ratio_max =
641  std::max(1., this->spectral_function(max_mass) /
642  this->spectral_function_simple(max_mass));
643 
644  double mass_res, val;
645  // outer loop: repeat if maximum is too small
646  do {
647  const double q_max = sf_ratio_max * this->max_factor1_;
648  const double max = blw_max * q_max; // maximum value for rejection sampling
649  // inner loop: rejection sampling
650  do {
651  // sample mass from a simple Breit-Wigner (aka Cauchy) distribution
652  mass_res = random::cauchy(this->mass(), this->width_at_pole() / 2.,
653  this->min_mass_spectral(), max_mass);
654  // determine cm momentum for this case
655  const double pcm = pCM(cms_energy, mass_stable, mass_res);
656  const double blw = pcm * blatt_weisskopf_sqr(pcm, L);
657  // determine ratio of full to simple spectral function
658  const double q = this->spectral_function(mass_res) /
659  this->spectral_function_simple(mass_res);
660  val = q * blw;
661  } while (val < random::uniform(0., max));
662 
663  // check that we are using the proper maximum value
664  if (val > max) {
665  logg[LResonances].debug(
666  "maximum is being increased in sample_resonance_mass: ",
667  this->max_factor1_, " ", val / max, " ", this->pdgcode(), " ",
668  mass_stable, " ", cms_energy, " ", mass_res);
669  this->max_factor1_ *= val / max;
670  } else {
671  break; // maximum ok, exit loop
672  }
673  } while (true);
674 
675  return mass_res;
676 }
677 
678 /* Resonance mass sampling for 2-particle final state with two resonances. */
679 std::pair<double, double> ParticleType::sample_resonance_masses(
680  const ParticleType &t2, const double cms_energy, int L) const {
681  const ParticleType &t1 = *this;
682  /* Sample resonance mass from the distribution
683  * used for calculating the cross section. */
684  const double max_mass_1 =
685  std::nextafter(cms_energy - t2.min_mass_spectral(), 0.);
686  const double max_mass_2 =
687  std::nextafter(cms_energy - t1.min_mass_spectral(), 0.);
688  // largest possible cm momentum (from smallest mass)
689  const double pcm_max =
690  pCM(cms_energy, t1.min_mass_spectral(), t2.min_mass_spectral());
691  const double blw_max = pcm_max * blatt_weisskopf_sqr(pcm_max, L);
692 
693  double mass_1, mass_2, val;
694  // outer loop: repeat if maximum is too small
695  do {
696  // maximum value for rejection sampling (determined automatically)
697  const double max = blw_max * t1.max_factor2_;
698  // inner loop: rejection sampling
699  do {
700  // sample mass from a simple Breit-Wigner (aka Cauchy) distribution
701  mass_1 = random::cauchy(t1.mass(), t1.width_at_pole() / 2.,
702  t1.min_mass_spectral(), max_mass_1);
703  mass_2 = random::cauchy(t2.mass(), t2.width_at_pole() / 2.,
704  t2.min_mass_spectral(), max_mass_2);
705  // determine cm momentum for this case
706  const double pcm = pCM(cms_energy, mass_1, mass_2);
707  const double blw = pcm * blatt_weisskopf_sqr(pcm, L);
708  // determine ratios of full to simple spectral function
709  const double q1 =
710  t1.spectral_function(mass_1) / t1.spectral_function_simple(mass_1);
711  const double q2 =
712  t2.spectral_function(mass_2) / t2.spectral_function_simple(mass_2);
713  val = q1 * q2 * blw;
714  } while (val < random::uniform(0., max));
715 
716  if (val > max) {
717  logg[LResonances].debug(
718  "maximum is being increased in sample_resonance_masses: ",
719  t1.max_factor2_, " ", val / max, " ", t1.pdgcode(), " ", t2.pdgcode(),
720  " ", cms_energy, " ", mass_1, " ", mass_2);
721  t1.max_factor2_ *= val / max;
722  } else {
723  break; // maximum ok, exit loop
724  }
725  } while (true);
726 
727  return {mass_1, mass_2};
728 }
729 
731  if (is_stable()) {
732  std::stringstream err;
733  err << "Particle " << *this << " is stable, so it makes no"
734  << " sense to print its spectral function, etc.";
735  throw std::runtime_error(err.str());
736  }
737 
738  double rightmost_pole = 0.0;
739  const auto &decaymodes = decay_modes().decay_mode_list();
740  for (const auto &mode : decaymodes) {
741  double pole_mass_sum = 0.0;
742  for (const ParticleTypePtr p : mode->type().particle_types()) {
743  pole_mass_sum += p->mass();
744  }
745  if (pole_mass_sum > rightmost_pole) {
746  rightmost_pole = pole_mass_sum;
747  }
748  }
749 
750  std::cout << "# mass m[GeV], width w(m) [GeV],"
751  << " spectral function(m^2)*m [GeV^-1] of " << *this << std::endl;
752  constexpr double m_step = 0.02;
753  const double m_min = min_mass_spectral();
754  // An empirical value used to stop the printout. Assumes that spectral
755  // function decays at high mass, which is true for all known resonances.
756  constexpr double spectral_function_threshold = 8.e-3;
757  std::cout << std::fixed << std::setprecision(5);
758  for (unsigned int i = 0;; i++) {
759  const double m = m_min + m_step * i;
760  const double w = total_width(m), sf = spectral_function(m);
761  if (m > rightmost_pole * 2 && sf < spectral_function_threshold) {
762  break;
763  }
764  std::cout << m << " " << w << " " << sf << std::endl;
765  }
766 }
767 
768 std::ostream &operator<<(std::ostream &out, const ParticleType &type) {
769  const PdgCode &pdg = type.pdgcode();
770  return out << type.name() << std::setfill(' ') << std::right
771  << "[ mass:" << field<6> << type.mass()
772  << ", width:" << field<6> << type.width_at_pole()
773  << ", PDG:" << field<6> << pdg
774  << ", charge:" << field<3> << pdg.charge()
775  << ", spin:" << field<2> << pdg.spin() << "/2 ]";
776 }
777 
778 } // namespace smash
smash::breit_wigner
double breit_wigner(double m, double pole, double width)
Returns a relativistic Breit-Wigner distribution.
Definition: distributions.cc:24
smash::DecayBranch::type
const DecayType & type() const
Definition: processbranch.h:342
smash::line_parser
build_vector_< Line > line_parser(const std::string &input)
Helper function for parsing particles.txt and decaymodes.txt.
Definition: inputfunctions.cc:21
smash
Definition: action.h:24
smash::ParticleType::get_partial_width
double get_partial_width(const double m, const ParticleType &t_a, const ParticleType &t_b) const
Get the mass-dependent partial width of a resonance with mass m, decaying into two given daughter par...
Definition: particletype.cc:541
smash::ParticleType::exists
static bool exists(PdgCode pdgcode)
Definition: particletype.cc:113
smash::ParticleType::list_nucleons
static ParticleTypePtrList & list_nucleons()
Definition: particletype.cc:75
smash::DecayType::particle_number
virtual unsigned int particle_number() const =0
smash::PdgCode::get_antiparticle
PdgCode get_antiparticle() const
Construct the antiparticle to a given PDG code.
Definition: pdgcode.h:257
smash::ParticleType::spectral_function_no_norm
double spectral_function_no_norm(double m) const
Full spectral function without normalization factor.
Definition: particletype.cc:597
smash::random::cauchy
T cauchy(T pole, T width, T min, T max)
Draws a random number from a Cauchy distribution (sometimes also called Lorentz or non-relativistic B...
Definition: random.h:307
smash::IsoParticleType::isospin
int isospin() const
Returns twice the total isospin of the multiplet.
Definition: isoparticletype.h:74
smash::ParticleType::list_anti_nucleons
static ParticleTypePtrList & list_anti_nucleons()
Definition: particletype.cc:77
smash::ParticleType::dump_width_and_spectral_function
void dump_width_and_spectral_function() const
Prints out width and spectral function versus mass to the standard output.
Definition: particletype.cc:730
processbranch.h
particledata.h
smash::IsoParticleType::find
static const IsoParticleType & find(const std::string &name)
Returns the IsoParticleType object for the given name.
Definition: isoparticletype.cc:62
smash::ParticleType::width_at_pole
double width_at_pole() const
Definition: particletype.h:150
smash::ParticleType::min_mass_spectral
double min_mass_spectral() const
The minimum mass of the resonance, where the spectral function is non-zero.
Definition: particletype.cc:374
pow.h
smash::DecayType
DecayType is the abstract base class for all decay types.
Definition: decaytype.h:23
smash::ParticleType::wanted_decaymode
bool wanted_decaymode(const DecayType &t, WhichDecaymodes wh) const
Helper Function that containes the if-statement logic that decides if a decay mode is either a hadron...
Definition: particletype.cc:460
smash::build_error_string
std::string build_error_string(std::string message, const Line &line)
Builds a meaningful error message.
Definition: inputfunctions.h:42
smash::anonymous_namespace{particletype.cc}::anti_deltas_list
ParticleTypePtrList anti_deltas_list
Global pointer to the Particle Type list of anti-deltas.
Definition: particletype.cc:50
smash::ParticleData
Definition: particledata.h:52
smash::PdgCode::baryon_number
int baryon_number() const
Definition: pdgcode.h:305
smash::DecayModes::decay_mode_list
const DecayBranchList & decay_mode_list() const
Definition: decaymodes.h:63
smash::ensure_all_read
void ensure_all_read(std::istream &input, const Line &line)
Makes sure that nothing is left to read from this line.
Definition: inputfunctions.h:59
smash::Potentials::force_scale
static std::pair< double, int > force_scale(const ParticleType &data)
Evaluates the scaling factor of the forces acting on the particles.
Definition: potentials.cc:164
smash::PdgCode::is_hadron
bool is_hadron() const
Definition: pdgcode.h:294
smash::ParticleType::list_light_nuclei
static ParticleTypePtrList & list_light_nuclei()
Definition: particletype.cc:91
smash::PdgCode::spin
unsigned int spin() const
Definition: pdgcode.h:506
cxx14compat.h
unlikely
#define unlikely(x)
Tell the branch predictor that this expression is likely false.
Definition: macros.h:16
smash::WhichDecaymodes::All
All decay mode widths.
smash::Line
Line consists of a line number and the contents of that line.
Definition: inputfunctions.h:23
smash::ParticleData::effective_mass
double effective_mass() const
Get the particle's effective mass.
Definition: particledata.cc:21
smash::anonymous_namespace{particletype.cc}::deltas_list
ParticleTypePtrList deltas_list
Global pointer to the Particle Type list of deltas.
Definition: particletype.cc:48
smash::ParticleType::PdgNotFoundFailure
Definition: particletype.h:489
smash::Integrator
A C++ interface for numerical integration in one dimension with the GSL CQUAD integration functions.
Definition: integrate.h:106
smash::anonymous_namespace{particletype.cc}::all_particle_types
const ParticleTypeList * all_particle_types
Global pointer to the Particle Type list.
Definition: particletype.cc:42
smash::operator<<
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Definition: action.h:463
smash::blatt_weisskopf_sqr
double blatt_weisskopf_sqr(const double p_ab, const int L)
Definition: formfactors.h:33
smash::ParticleType::mass
double mass() const
Definition: particletype.h:144
smash::ParticleType::spectral_function
double spectral_function(double m) const
Full spectral function of the resonance (relativistic Breit-Wigner distribution with mass-dependent ...
Definition: particletype.cc:577
smash::ParticleType::is_Delta
bool is_Delta() const
Definition: particletype.h:215
smash::ParticleType::isospin_
int isospin_
Isospin of the particle; filled automatically from pdgcode_.
Definition: particletype.h:635
smash::ParticleType::get_partial_in_width
double get_partial_in_width(const double m, const ParticleData &p_a, const ParticleData &p_b) const
Get the mass-dependent partial in-width of a resonance with mass m, decaying into two given daughter ...
Definition: particletype.cc:558
smash::nucleon_mass
constexpr double nucleon_mass
Nucleon mass in GeV.
Definition: constants.h:55
smash::ParticleType::create_type_list
static void create_type_list(const std::string &particles)
Initialize the global ParticleType list (list_all) from the given input data.
Definition: particletype.cc:205
smash::ParticleType::pdgcode
PdgCode pdgcode() const
Definition: particletype.h:156
smash::ParticleType::operator&
ParticleTypePtr operator&() const
Returns an object that acts like a pointer, except that it requires only 2 bytes and inhibits pointer...
Definition: particletype.cc:63
smash::ParticleType::min_mass_kinematic_
double min_mass_kinematic_
minimum kinematically allowed mass of the particle Mutable, because it is initialized at first call o...
Definition: particletype.h:621
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::ParticleType::list_anti_Deltas
static ParticleTypePtrList & list_anti_Deltas()
Definition: particletype.cc:83
smash::LResonances
static constexpr int LResonances
Definition: clebschgordan.cc:16
smash::ParticleType::list_Deltas
static ParticleTypePtrList & list_Deltas()
Definition: particletype.cc:81
smash::pCM
T pCM(const T sqrts, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:79
smash::ParticleType::total_width
double total_width(const double m) const
Get the mass-dependent total width of a particle with mass m.
Definition: particletype.cc:435
smash::really_small
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
smash::ParticleType::find
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
Definition: particletype.cc:105
smash::ParticleType::has_antiparticle
bool has_antiparticle() const
Definition: particletype.h:159
smash::ParticleType::decay_modes
const DecayModes & decay_modes() const
Definition: particletype.cc:428
smash::DecayBranch
Definition: processbranch.h:322
smash::UI3_lat_pointer
RectangularLattice< FourVector > * UI3_lat_pointer
Pointer to the symmmetry potential on the lattice.
Definition: potential_globals.cc:16
smash::PdgCode::string
std::string string() const
Definition: pdgcode.h:250
smash::ParticleTypePtr
Definition: particletype.h:663
smash::ParticleType::norm_factor_
double norm_factor_
This normalization factor ensures that the spectral function is normalized to unity,...
Definition: particletype.h:631
smash::ThreeVector
Definition: threevector.h:31
smash::ParticleType::iso_multiplet_
IsoParticleType * iso_multiplet_
Container for the isospin multiplet information.
Definition: particletype.h:640
smash::ParticleType::get_partial_widths
DecayBranchList get_partial_widths(const FourVector p, const ThreeVector x, WhichDecaymodes wh) const
Get all the mass-dependent partial decay widths of a particle with mass m.
Definition: particletype.cc:492
smash::integrate
static Integrator integrate
Definition: decaytype.cc:147
smash::LParticleType
static constexpr int LParticleType
Definition: isoparticletype.cc:19
smash::ParticleType::isospin
int isospin() const
Returns twice the isospin vector length .
Definition: particletype.cc:410
smash::WhichDecaymodes::Hadronic
Ignore dilepton decay modes widths.
smash::PdgCode::charge
int charge() const
The charge of the particle.
Definition: pdgcode.h:467
isoparticletype.h
smash::ParticleType::is_deuteron
bool is_deuteron() const
Definition: particletype.h:242
smash::ParticleType::sample_resonance_masses
std::pair< double, double > sample_resonance_masses(const ParticleType &t2, const double cms_energy, int L=0) const
Resonance mass sampling for 2-particle final state with two resonances.
Definition: particletype.cc:679
formfactors.h
smash::UB_lat_pointer
RectangularLattice< FourVector > * UB_lat_pointer
Pointer to the skyrme potential on the lattice.
Definition: potential_globals.cc:15
smash::ParticleType::is_stable
bool is_stable() const
Definition: particletype.h:236
smash::IsoParticleType::exists
static bool exists(const std::string &name)
Returns whether the ParticleType with the given pdgcode exists.
Definition: isoparticletype.cc:79
smash::breit_wigner_nonrel
double breit_wigner_nonrel(double m, double pole, double width)
Returns a non-relativistic Breit-Wigner distribution, which is essentially a Cauchy distribution with...
Definition: distributions.cc:31
smash::ParticleType::sample_resonance_mass
double sample_resonance_mass(const double mass_stable, const double cms_energy, int L=0) const
Resonance mass sampling for 2-particle final state with one resonance (type given by 'this') and one ...
Definition: particletype.cc:622
smash::anonymous_namespace{particletype.cc}::nucleons_list
ParticleTypePtrList nucleons_list
Global pointer to the Particle Type list of nucleons.
Definition: particletype.cc:44
smash::WhichDecaymodes
WhichDecaymodes
Decide which decay mode widths are returned in get partical widths.
Definition: particletype.h:32
smash::ParticleType::isospin3_rel
double isospin3_rel() const
Definition: particletype.h:179
smash::ParticleType
Definition: particletype.h:97
smash::ParticleType::spectral_function_simple
double spectral_function_simple(double m) const
This one is the most simple form of the spectral function, using a Cauchy distribution (non-relativis...
Definition: particletype.cc:617
smash::ParticleType::name
const std::string & name() const
Definition: particletype.h:141
distributions.h
smash::ParticleType::LoadFailure
Definition: particletype.h:600
smash::almost_equal
bool almost_equal(const N x, const N y)
Checks two numbers for relative approximate equality.
Definition: numerics.h:42
particletype.h
smash::anonymous_namespace{particletype.cc}::baryon_resonances_list
ParticleTypePtrList baryon_resonances_list
Global pointer to the Particle Type list of baryon resonances.
Definition: particletype.cc:52
smash::PdgCode
Definition: pdgcode.h:108
smash::anonymous_namespace{particletype.cc}::light_nuclei_list
ParticleTypePtrList light_nuclei_list
Global pointer to the Particle Type list of light nuclei.
Definition: particletype.cc:54
smash::ParticleType::pdgcode_
PdgCode pdgcode_
PDG Code of the particle.
Definition: particletype.h:614
smash::ParticleType::try_find
static const ParticleTypePtr try_find(PdgCode pdgcode)
Returns the ParticleTypePtr for the given pdgcode.
Definition: particletype.cc:95
smash::ParticleType::ParticleType
ParticleType(std::string n, double m, double w, Parity p, PdgCode id)
Creates a fully initialized ParticleType object.
Definition: particletype.cc:128
smash::ParticleType::check_consistency
static void check_consistency()
Definition: particletype.cc:451
smash::chargestr
static std::string chargestr(int charge)
Construct a charge string, given the charge as integer.
Definition: particletype.cc:188
smash::antiname
static std::string antiname(const std::string &name, PdgCode code)
Construct an antiparticle name-string from the given name-string for the particle and its PDG code.
Definition: particletype.cc:149
smash::utf8::sequence_length
std::iterator_traits< octet_iterator >::difference_type sequence_length(octet_iterator lead_it)
Given an iterator to the beginning of a UTF-8 sequence, return the length of the next UTF-8 code poin...
Definition: stringfunctions.h:103
kinematics.h
smash::ParticleType::max_factor2_
double max_factor2_
Maximum factor for double-res mass sampling, cf. sample_resonance_masses.
Definition: particletype.h:645
smash::Parity::Pos
Positive parity.
smash::DecayModes
Definition: decaymodes.h:29
smash::ParticleType::partial_width
double partial_width(const double m, const DecayBranch *mode) const
Get the mass-dependent partial decay width of a particle with mass m in a particular decay mode.
Definition: particletype.cc:419
smash::PdgCode::strangeness
int strangeness() const
Definition: pdgcode.h:443
integrate.h
numerics.h
smash::has_lepton_pair
bool has_lepton_pair(const PdgCode pdg1, const PdgCode pdg2, const PdgCode pdg3)
Definition: pdgcode.h:992
constants.h
iomanipulators.h
pdgcode.h
smash::ParticleType::min_mass_spectral_
double min_mass_spectral_
minimum mass, where the spectral function is non-zero Mutable, because it is initialized at first cal...
Definition: particletype.h:628
logging.h
smash::ParticleType::spectral_function_const_width
double spectral_function_const_width(double m) const
Definition: particletype.cc:607
smash::delta_mass
constexpr double delta_mass
Delta mass in GeV.
Definition: constants.h:89
smash::ParticleType::max_factor1_
double max_factor1_
Maximum factor for single-res mass sampling, cf. sample_resonance_mass.
Definition: particletype.h:643
smash::DecayType::width
virtual double width(double m0, double G0, double m) const =0
smash::FourVector
Definition: fourvector.h:33
smash::Parity
Parity
Represent the parity of a particle type.
Definition: particletype.h:24
smash::pdg::p
constexpr int p
Proton.
Definition: pdgcode_constants.h:28
smash::random::uniform
T uniform(T min, T max)
Definition: random.h:88
smash::pdg::n
constexpr int n
Neutron.
Definition: pdgcode_constants.h:30
smash::ParticleType::list_baryon_resonances
static ParticleTypePtrList & list_baryon_resonances()
Definition: particletype.cc:87
smash::ParticleType::min_mass_kinematic
double min_mass_kinematic() const
The minimum mass of the resonance that is kinematically allowed.
Definition: particletype.cc:360
smash::pot_pointer
Potentials * pot_pointer
Pointer to a Potential class.
Definition: potential_globals.cc:17
smash::ParticleType::mass_
double mass_
pole mass of the particle
Definition: particletype.h:608
smash::deuteron_mass
constexpr double deuteron_mass
Deuteron mass in GeV.
Definition: constants.h:95
smash::WhichDecaymodes::Dileptons
Only return dilepton decays widths.
potential_globals.h
smash::kaon_mass
constexpr double kaon_mass
Kaon mass in GeV.
Definition: constants.h:69
smash::ParticleData::type
const ParticleType & type() const
Get the type of the particle.
Definition: particledata.h:112
smash::anonymous_namespace{particletype.cc}::anti_nucs_list
ParticleTypePtrList anti_nucs_list
Global pointer to the Particle Type list of anti-nucleons.
Definition: particletype.cc:46
smash::Parity::Neg
Negative parity.
inputfunctions.h
stringfunctions.h
smash::is_dilepton
bool is_dilepton(const PdgCode pdg1, const PdgCode pdg2)
Definition: pdgcode.h:980
smash::DecayType::particle_types
const ParticleTypePtrList & particle_types() const
Definition: decaytype.h:59
smash::IsoParticleType::get_states
ParticleTypePtrList get_states() const
Returns list of states that form part of the multiplet.
Definition: isoparticletype.h:93
smash::ParticleType::width_cutoff
static constexpr double width_cutoff
Decay width cutoff for considering a particle as stable.
Definition: particletype.h:107
smash::ParticleType::list_all
static const ParticleTypeList & list_all()
Definition: particletype.cc:57
smash::IsoParticleType::create_multiplet
static void create_multiplet(const ParticleType &type)
Add a new multiplet to the global list of IsoParticleTypes, which contains type.
Definition: isoparticletype.cc:161
smash::ParticleType::charge
int32_t charge() const
The charge of the particle.
Definition: particletype.h:188
smash::ProcessBranch::weight
double weight() const
Definition: processbranch.h:186
smash::ParticleType::parity
Parity parity() const
Definition: particletype.h:153
decaymodes.h
smash::ParticleType::is_nucleon
bool is_nucleon() const
Definition: particletype.h:212