Version: SMASH-3.1
isoparticletype.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2022
3  * SMASH Team
4  *
5  * GNU General Public License (GPLv3 or later)
6  */
7 
9 
10 #include <filesystem>
11 
12 #include "smash/filelock.h"
13 #include "smash/integrate.h"
14 #include "smash/logging.h"
15 
16 namespace smash {
17 static constexpr int LParticleType = LogArea::ParticleType::id;
18 
19 static IsoParticleTypeList iso_type_list;
20 static std::vector<const IsoParticleType *> iso_baryon_resonances;
21 
22 const std::vector<const IsoParticleType *>
24  if (iso_baryon_resonances.empty()) {
25  // Initialize.
26  for (const auto &res : IsoParticleType::list_all()) {
27  const auto baryon_number = res.states_[0]->pdgcode().baryon_number();
28  if (res.states_[0]->is_stable() || (baryon_number <= 0)) {
29  continue;
30  }
31  iso_baryon_resonances.push_back(&res);
32  }
33  }
34  return iso_baryon_resonances;
35 }
36 
37 IsoParticleType::IsoParticleType(const std::string &n, double m, double w,
38  unsigned int s, Parity p)
39  : name_(n), mass_(m), width_(w), spin_(s), parity_(p) {}
40 
41 const IsoParticleTypeList &IsoParticleType::list_all() { return iso_type_list; }
42 
44 static IsoParticleType *try_find_private(const std::string &name) {
45  auto found =
46  std::lower_bound(iso_type_list.begin(), iso_type_list.end(), name,
47  [](const IsoParticleType &l, const std::string &r) {
48  return l.name() < r;
49  });
50  if (found == iso_type_list.end() || found->name() != name) {
51  return {}; // The default constructor creates an invalid pointer.
52  }
53  return &*found;
54 }
55 
56 const IsoParticleType *IsoParticleType::try_find(const std::string &name) {
57  return try_find_private(name);
58 }
59 
60 const IsoParticleType &IsoParticleType::find(const std::string &name) {
61  const auto found = try_find_private(name);
62  if (!found) {
63  throw ParticleNotFoundFailure("Isospin multiplet " + name + " not found!");
64  }
65  return *found;
66 }
67 
69  auto found = try_find_private(name);
70  if (!found) {
71  throw ParticleNotFoundFailure("Isospin multiplet " + name +
72  " not found (privately)!");
73  }
74  return *found;
75 }
76 
77 bool IsoParticleType::exists(const std::string &name) {
78  const auto found = try_find_private(name);
79  return found;
80 }
81 
89 static std::string multiplet_name(std::string name) {
90  if (name.find("⁺⁺") != std::string::npos) {
91  return name.substr(0, name.length() - sizeof("⁺⁺") + 1);
92  } else if (name.find("⁺") != std::string::npos) {
93  return name.substr(0, name.length() - sizeof("⁺") + 1);
94  } else if (name.find("⁻⁻") != std::string::npos) {
95  return name.substr(0, name.length() - sizeof("⁻⁻") + 1);
96  } else if (name.find("⁻") != std::string::npos) {
97  return name.substr(0, name.length() - sizeof("⁻") + 1);
98  } else if (name.find("⁰") != std::string::npos) {
99  return name.substr(0, name.length() - sizeof("⁰") + 1);
100  } else {
101  return name;
102  }
103 }
104 
106  if (states_[0]->has_antiparticle()) {
107  ParticleTypePtr anti = states_[0]->get_antiparticle();
108  if (states_[0]->name() != multiplet_name(anti->name())) {
109  return anti->iso_multiplet();
110  } else {
111  return nullptr;
112  }
113  } else {
114  return nullptr;
115  }
116 }
117 
119  return anti_multiplet() != nullptr;
120 }
121 
122 const ParticleTypePtr IsoParticleType::find_state(const std::string &n) {
124  auto found = std::find_if(multiplet.states_.begin(), multiplet.states_.end(),
125  [&n](ParticleTypePtr p) { return p->name() == n; });
126  if (found == multiplet.states_.end()) {
127  throw std::runtime_error("Isospin state " + n + " not found!");
128  }
129  return *found;
130 }
131 
133  std::string multiname = multiplet_name(type.name());
134  IsoParticleType &multiplet = find_private(multiname);
135  return &multiplet;
136 }
137 
139  states_.push_back(&type);
140 
141  // check if isospin symmetry is fulfilled
142  if (std::abs(mass() - type.mass()) > really_small) {
143  logg[LParticleType].warn()
144  << "Isospin symmetry is broken by mass of " << type.name() << ": "
145  << type.mass() << " vs. " << mass();
146  }
147  if (std::abs(width() - type.width_at_pole()) > really_small) {
148  logg[LParticleType].warn()
149  << "Isospin symmetry is broken by width of " << type.name() << ": "
150  << type.width_at_pole() << " vs. " << width();
151  }
152  if (spin() != type.spin()) {
153  logg[LParticleType].error()
154  << "Isospin symmetry is broken by spin of " << type.name() << ": "
155  << type.spin() << " vs. " << spin();
156  }
157 }
158 
160  // create multiplet if it does not exist yet
161  std::string multiname = multiplet_name(type.name());
162  if (!exists(multiname)) {
163  iso_type_list.emplace_back(multiname, type.mass(), type.width_at_pole(),
164  type.spin(), type.parity());
165  logg[LParticleType].debug()
166  << "Creating isospin multiplet " << multiname
167  << " [ m = " << type.mass() << ", Γ = " << type.width_at_pole() << " ]";
168  }
169 
170  // sort the iso-type list by name
171  std::sort(iso_type_list.begin(), iso_type_list.end(),
172  [](const IsoParticleType &l, const IsoParticleType &r) {
173  return l.name() < r.name();
174  });
175 
176  // add the specific type to the multiplet
177  IsoParticleType &multiplet = find_private(multiname);
178  multiplet.add_state(type);
179 }
180 
183 
189 static std::unordered_map<std::string, Tabulation> NR_tabulations;
190 
196 static std::unordered_map<std::string, Tabulation> piR_tabulations;
197 
203 static std::unordered_map<std::string, Tabulation> RK_tabulations;
204 
210 static std::unordered_map<std::string, Tabulation> DeltaR_tabulations;
211 
217 static std::unordered_map<std::string, Tabulation> rhoR_tabulations;
218 
219 static std::filesystem::path generate_tabulation_path(
220  const std::filesystem::path &dir, const std::string &prefix,
221  const std::string &res_name) {
222  return dir / (prefix + res_name + ".bin");
223 }
224 
225 inline void cache_integral(
226  std::unordered_map<std::string, Tabulation> &tabulations,
227  const std::filesystem::path &dir, sha256::Hash hash,
228  const IsoParticleType &part, const IsoParticleType &res,
229  const IsoParticleType *antires, bool unstable) {
230  constexpr double spacing = 2.0;
231  constexpr double spacing2d = 3.0;
232  const auto path = generate_tabulation_path(dir, part.name_filtered_prime(),
233  res.name_filtered_prime());
234  Tabulation integral;
235  if (!dir.empty() && std::filesystem::exists(path)) {
236  std::ifstream file(path.string());
237  integral = Tabulation::from_file(file, hash);
238  if (!integral.is_empty()) {
239  // Only print message if the found tabulation was valid.
240  std::cout << "Tabulation found at " << path.filename() << '\r'
241  << std::flush;
242  }
243  }
244  if (integral.is_empty()) {
245  if (!dir.empty()) {
246  std::cout << "Caching tabulation to " << path.filename() << '\r'
247  << std::flush;
248  } else {
249  std::cout << "Calculating integral for " << part.name_filtered_prime()
250  << res.name_filtered_prime() << '\r' << std::flush;
251  }
252  if (!unstable) {
253  integral = spectral_integral_semistable(integrate, *res.get_states()[0],
254  *part.get_states()[0], spacing);
255  } else {
256  integral = spectral_integral_unstable(integrate2d, *res.get_states()[0],
257  *part.get_states()[0], spacing2d);
258  }
259  if (!dir.empty()) {
260  std::ofstream file(path.string());
261  integral.write(file, hash);
262  }
263  }
264  tabulations.emplace(std::make_pair(res.name(), integral));
265  if (antires != nullptr) {
266  tabulations.emplace(std::make_pair(antires->name(), integral));
267  }
268 }
269 
271  sha256::Hash hash, const std::filesystem::path &tabulations_path) {
272  // To avoid race conditions, make sure we are the only ones currently storing
273  // tabulations. Otherwise, we ignore any stored tabulations and don't store
274  // our results.
275  FileLock lock(tabulations_path / "tabulations.lock");
276  const std::filesystem::path &dir = lock.acquire() ? tabulations_path : "";
277 
278  const auto nuc = IsoParticleType::try_find("N");
279  const auto pion = IsoParticleType::try_find("π");
280  const auto kaon = IsoParticleType::try_find("K");
281  const auto delta = IsoParticleType::try_find("Δ");
282  const auto rho = IsoParticleType::try_find("ρ");
283  const auto h1 = IsoParticleType::try_find("h₁(1170)");
284  for (const auto &res : IsoParticleType::list_baryon_resonances()) {
285  const auto antires = res->anti_multiplet();
286  if (nuc) {
287  cache_integral(NR_tabulations, dir, hash, *nuc, *res, antires, false);
288  }
289  if (pion) {
290  cache_integral(piR_tabulations, dir, hash, *pion, *res, antires, false);
291  }
292  if (kaon) {
293  cache_integral(RK_tabulations, dir, hash, *kaon, *res, antires, false);
294  }
295  if (delta) {
296  cache_integral(DeltaR_tabulations, dir, hash, *delta, *res, antires,
297  true);
298  }
299  }
300  if (rho) {
301  cache_integral(rhoR_tabulations, dir, hash, *rho, *rho, nullptr, true);
302  }
303  if (rho && h1) {
304  cache_integral(rhoR_tabulations, dir, hash, *rho, *h1, nullptr, true);
305  }
306 }
307 
308 double IsoParticleType::get_integral_NR(double sqrts) {
309  if (XS_NR_tabulation_ == nullptr) {
310  const auto res = states_[0]->iso_multiplet();
311  XS_NR_tabulation_ = &NR_tabulations.at(res->name());
312  }
313  return XS_NR_tabulation_->get_value_linear(sqrts);
314 }
315 
316 double IsoParticleType::get_integral_piR(double sqrts) {
317  if (XS_piR_tabulation_ == nullptr) {
318  const auto res = states_[0]->iso_multiplet();
319  XS_piR_tabulation_ = &piR_tabulations.at(res->name());
320  }
321  return XS_piR_tabulation_->get_value_linear(sqrts);
322 }
323 
324 double IsoParticleType::get_integral_RK(double sqrts) {
325  if (XS_RK_tabulation_ == nullptr) {
326  const auto res = states_[0]->iso_multiplet();
327  XS_RK_tabulation_ = &RK_tabulations.at(res->name());
328  }
329  return XS_RK_tabulation_->get_value_linear(sqrts);
330 }
331 
333  if (XS_rhoR_tabulation_ == nullptr) {
334  const auto res = states_[0]->iso_multiplet();
335  XS_rhoR_tabulation_ = &rhoR_tabulations.at(res->name());
336  }
337  return XS_rhoR_tabulation_->get_value_linear(sqrts);
338 }
339 
341  double sqrts) {
342  const auto res = states_[0]->iso_multiplet();
343  if (type_res_2->states_[0]->is_Delta()) {
344  if (XS_DeltaR_tabulation_ == nullptr) {
345  XS_DeltaR_tabulation_ = &DeltaR_tabulations.at(res->name());
346  }
348  }
349  if (type_res_2->name() == "ρ") {
350  if (XS_rhoR_tabulation_ == nullptr) {
351  XS_rhoR_tabulation_ = &rhoR_tabulations.at(res->name());
352  }
353  return XS_rhoR_tabulation_->get_value_linear(sqrts);
354  }
355  if (type_res_2->name() == "h₁(1170)") {
356  if (XS_rhoR_tabulation_ == nullptr) {
357  XS_rhoR_tabulation_ = &rhoR_tabulations.at(res->name());
358  }
359  return XS_rhoR_tabulation_->get_value_linear(sqrts);
360  }
361  std::stringstream err;
362  err << "RR=" << name() << type_res_2->name() << " is not implemented";
363  throw std::runtime_error(err.str());
364 }
365 
366 } // namespace smash
Guard to create a file lock.
Definition: filelock.h:30
bool acquire()
Try to acquire the file lock.
Definition: filelock.cc:22
A C++ interface for numerical integration in two dimensions with the Cuba Cuhre integration function.
Definition: integrate.h:219
A C++ interface for numerical integration in one dimension with the GSL CQUAD integration functions.
Definition: integrate.h:106
IsoParticleType is a class to represent isospin multiplets.
void add_state(const ParticleType &type)
Add a new state to an existing multiplet (and check if isospin symmetry is fulfilled).
static const IsoParticleType * try_find(const std::string &name)
Returns the IsoParticleType pointer for the given name.
Tabulation * XS_NR_tabulation_
A tabulation for the NN -> NR cross sections, where R is a resonance from this multiplet.
Tabulation * XS_rhoR_tabulation_
A tabulation for the ρρ integrals.
static bool exists(const std::string &name)
Returns whether the ParticleType with the given pdgcode exists.
double width() const
Returns the (average) multiplet width.
static const IsoParticleType & find(const std::string &name)
Returns the IsoParticleType object for the given name.
double get_integral_RR(IsoParticleType *type_res_2, double sqrts)
Look up the tabulated resonance integral for the XX -> RR cross section.
const std::string name_filtered_prime() const
Returns the name of the multiplet, after replacing "'" with "_prime".
static IsoParticleType & find_private(const std::string &name)
Private version of the 'find' method that returns a non-const reference.
static void tabulate_integrals(sha256::Hash hash, const std::filesystem::path &tabulations_path)
Tabulate all relevant integrals.
Tabulation * XS_piR_tabulation_
A tabulation of the spectral integral for the dpi -> d'pi cross sections.
static void create_multiplet(const ParticleType &type)
Add a new multiplet to the global list of IsoParticleTypes, which contains type.
ParticleTypePtrList states_
list of states that are contained in the multiplet
bool has_anti_multiplet() const
Check if there is a multiplet of antiparticles, which is different from the original multiplet.
IsoParticleType(const std::string &n, double m, double w, unsigned int s, Parity p)
Creates a fully initialized IsoParticleType object.
double get_integral_NR(double sqrts)
Look up the tabulated resonance integral for the XX -> NR cross section.
static const IsoParticleTypeList & list_all()
Returns a list of all IsoParticleTypes.
double mass() const
Returns the (average) multiplet mass.
Tabulation * XS_DeltaR_tabulation_
A tabulation for the NN -> RΔ cross sections, where R is a resonance from this multiplet.
const IsoParticleType * anti_multiplet() const
Return a multiplet of antiparticles, if it is different from the original multiplet.
const std::string & name() const
Returns the name of the multiplet.
double get_integral_rhoR(double sqrts)
Look up the tabulated resonance integral for the XX -> rhoR cross section.
static const std::vector< const IsoParticleType * > list_baryon_resonances()
Returns a list of all IsoParticleTypes that are baryon resonances.
double get_integral_RK(double sqrts)
Look up the tabulated resonance integral for the XX -> RK cross section.
unsigned int spin() const
Returns twice the spin of the multiplet.
ParticleTypePtrList get_states() const
Returns list of states that form part of the multiplet.
Tabulation * XS_RK_tabulation_
A tabulation of the spectral integral for the NK -> RK cross sections.
double get_integral_piR(double sqrts)
Look up the tabulated resonance integral for the XX -> piR cross section.
static const ParticleTypePtr find_state(const std::string &name)
Returns the ParticleType object for the given name, by first finding the correct multiplet and then l...
A pointer-like interface to global references to ParticleType objects.
Definition: particletype.h:676
Particle type contains the static properties of a particle species.
Definition: particletype.h:98
const std::string & name() const
Definition: particletype.h:142
double width_at_pole() const
Definition: particletype.h:151
double mass() const
Definition: particletype.h:145
unsigned int spin() const
Definition: particletype.h:192
IsoParticleType * iso_multiplet() const
Definition: particletype.h:186
Parity parity() const
Definition: particletype.h:154
A class for storing a one-dimensional lookup table of floating-point values.
Definition: tabulation.h:35
static Tabulation from_file(std::ifstream &stream, sha256::Hash hash)
Construct a tabulation object by reading binary data from a stream.
Definition: tabulation.cc:167
void write(std::ofstream &stream, sha256::Hash hash) const
Write a binary representation of the tabulation to a stream.
Definition: tabulation.cc:159
bool is_empty() const
Definition: tabulation.h:59
double get_value_linear(double x, Extrapolation extrapolation=Extrapolation::Linear) const
Look up a value from the tabulation using linear interpolation.
Definition: tabulation.cc:38
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 int p
Proton.
constexpr int h1
h₁(1170).
constexpr int n
Neutron.
std::array< uint8_t, HASH_SIZE > Hash
A SHA256 hash.
Definition: sha256.h:25
Definition: action.h:24
static Integrator integrate
Definition: decaytype.cc:143
static IsoParticleTypeList iso_type_list
static std::unordered_map< std::string, Tabulation > NR_tabulations
Tabulation of all N R integrals.
static std::unordered_map< std::string, Tabulation > RK_tabulations
Tabulation of all K R integrals.
static std::filesystem::path generate_tabulation_path(const std::filesystem::path &dir, const std::string &prefix, const std::string &res_name)
Tabulation spectral_integral_semistable(Integrator &integrate, const ParticleType &resonance, const ParticleType &stable, double range)
Create a table for the spectral integral of a resonance and a stable particle.
Definition: tabulation.h:189
static Integrator2d integrate2d(1E7)
Parity
Represent the parity of a particle type.
Definition: particletype.h:25
static std::unordered_map< std::string, Tabulation > piR_tabulations
Tabulation of all pi R integrals.
static std::unordered_map< std::string, Tabulation > DeltaR_tabulations
Tabulation of all Delta R integrals.
static std::unordered_map< std::string, Tabulation > rhoR_tabulations
Tabulation of all rho rho integrals.
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
void cache_integral(std::unordered_map< std::string, Tabulation > &tabulations, const std::filesystem::path &dir, sha256::Hash hash, const IsoParticleType &part, const IsoParticleType &res, const IsoParticleType *antires, bool unstable)
Tabulation spectral_integral_unstable(Integrator2d &integrate2d, const ParticleType &res1, const ParticleType &res2, double range)
Create a table for the spectral integral of two resonances.
Definition: tabulation.h:211
static std::string multiplet_name(std::string name)
Construct the name-string for an isospin multiplet from the given name-string for the particle.
static std::vector< const IsoParticleType * > iso_baryon_resonances
static IsoParticleType * try_find_private(const std::string &name)
Helper function for IsoParticleType::try_find and friends.
static constexpr int LParticleType
Throw when requested particle could not be found.