Version: SMASH-1.6
density.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2013-2019
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/density.h"
11 #include "smash/constants.h"
12 #include "smash/logging.h"
13 #include "smash/particles.h"
14 
15 namespace smash {
16 
17 double density_factor(const ParticleType &type, DensityType dens_type) {
18  switch (dens_type) {
20  return type.is_hadron() ? 1. : 0.;
22  return static_cast<double>(type.baryon_number());
24  return type.is_baryon() ? type.isospin3_rel() : 0.;
25  case DensityType::Pion:
26  return type.pdgcode().is_pion() ? 1. : 0.;
28  return type.is_hadron() ? type.isospin3() : 0.;
30  return static_cast<double>(type.charge());
32  return static_cast<double>(type.strangeness());
33  default:
34  return 0.;
35  }
36 }
37 
38 std::pair<double, ThreeVector> unnormalized_smearing_factor(
39  const ThreeVector &r, const FourVector &p, const double m_inv,
40  const DensityParameters &dens_par, const bool compute_gradient) {
41  const double r_sqr = r.sqr();
42  // Distance from particle to point of interest > r_cut
43  if (r_sqr > dens_par.r_cut_sqr()) {
44  return std::make_pair(0.0, ThreeVector(0.0, 0.0, 0.0));
45  }
46 
47  const FourVector u = p * m_inv;
48  const double u_r_scalar = r * u.threevec();
49  const double r_rest_sqr = r_sqr + u_r_scalar * u_r_scalar;
50 
51  // Lorentz contracted distance from particle to point of interest > r_cut
52  if (r_rest_sqr > dens_par.r_cut_sqr()) {
53  return std::make_pair(0.0, ThreeVector(0.0, 0.0, 0.0));
54  }
55  const double sf = std::exp(-r_rest_sqr * dens_par.two_sig_sqr_inv()) * u.x0();
56  const ThreeVector sf_grad = compute_gradient
57  ? sf * (r + u.threevec() * u_r_scalar) *
58  dens_par.two_sig_sqr_inv() * 2.0
59  : ThreeVector(0.0, 0.0, 0.0);
60 
61  return std::make_pair(sf, sf_grad);
62 }
63 
65 template <typename /*ParticlesContainer*/ T>
66 std::tuple<double, FourVector, ThreeVector, ThreeVector, ThreeVector>
67 current_eckart_impl(const ThreeVector &r, const T &plist,
68  const DensityParameters &par, DensityType dens_type,
69  bool compute_gradient, bool smearing) {
70  /* The current density of the positively and negatively charged particles.
71  * Division into positive and negative charges is necessary to avoid
72  * problems with the Eckart frame definition. Example of problem:
73  * get Eckart frame for two identical oppositely flying bunches of
74  * electrons and positrons. For this case jmu = (0, 0, 0, non-zero),
75  * so jmu.abs does not exist and Eckart frame is not defined.
76  * If one takes rho = jmu_pos.abs - jmu_neg.abs, it is still Lorentz-
77  * invariant and gives the right limit in non-relativistic case, but
78  * it gives no such problem. */
79  FourVector jmu_pos, jmu_neg;
80  /* The array of the derivatives of the current density.
81  * The zeroth component is the time derivative,
82  * while the next 3 ones are spacial derivatives. */
83  std::array<FourVector, 4> djmu_dx;
84 
85  for (const auto &p : plist) {
86  const double dens_factor = density_factor(p.type(), dens_type);
87  if (std::fabs(dens_factor) < really_small) {
88  continue;
89  }
90  const FourVector mom = p.momentum();
91  const double m = mom.abs();
92  if (m < really_small) {
93  continue;
94  }
95  const double m_inv = 1.0 / m;
96  const auto sf_and_grad = unnormalized_smearing_factor(
97  p.position().threevec() - r, mom, m_inv, par, compute_gradient);
98  if (smearing && sf_and_grad.first < really_small) {
99  continue;
100  }
101  const FourVector tmp = mom * (dens_factor / mom.x0());
102  if (smearing) {
103  if (dens_factor > 0.) {
104  jmu_pos += tmp * sf_and_grad.first;
105  } else {
106  jmu_neg += tmp * sf_and_grad.first;
107  }
108  } else {
109  if (dens_factor > 0.) {
110  jmu_pos += tmp;
111  } else {
112  jmu_neg += tmp;
113  }
114  }
115  if (compute_gradient) {
116  for (int k = 1; k <= 3; k++) {
117  djmu_dx[k] += tmp * sf_and_grad.second[k - 1];
118  djmu_dx[0] -= tmp * sf_and_grad.second[k - 1] * tmp.threevec()[k - 1] /
119  dens_factor;
120  }
121  }
122  }
123 
124  // Eckart density
125  const double rho_eck = (jmu_pos.abs() - jmu_neg.abs()) * par.norm_factor_sf();
126 
127  // $\partial_t \vec j$
128  const ThreeVector dj_dt = compute_gradient
129  ? djmu_dx[0].threevec() * par.norm_factor_sf()
130  : ThreeVector(0.0, 0.0, 0.0);
131 
132  // Gradient of density
133  ThreeVector rho_grad;
134  // Curl of current density
135  ThreeVector j_rot;
136  if (compute_gradient) {
137  j_rot.set_x1(djmu_dx[2].x3() - djmu_dx[3].x2());
138  j_rot.set_x2(djmu_dx[3].x1() - djmu_dx[1].x3());
139  j_rot.set_x3(djmu_dx[1].x2() - djmu_dx[2].x1());
140  j_rot *= par.norm_factor_sf();
141  for (int i = 1; i < 4; i++) {
142  rho_grad[i - 1] += djmu_dx[i].x0() * par.norm_factor_sf();
143  }
144  }
145  return std::make_tuple(rho_eck, jmu_pos + jmu_neg, rho_grad, dj_dt, j_rot);
146 }
147 
148 std::tuple<double, FourVector, ThreeVector, ThreeVector, ThreeVector>
149 current_eckart(const ThreeVector &r, const ParticleList &plist,
150  const DensityParameters &par, DensityType dens_type,
151  bool compute_gradient, bool smearing) {
152  return current_eckart_impl(r, plist, par, dens_type, compute_gradient,
153  smearing);
154 }
155 std::tuple<double, FourVector, ThreeVector, ThreeVector, ThreeVector>
156 current_eckart(const ThreeVector &r, const Particles &plist,
157  const DensityParameters &par, DensityType dens_type,
158  bool compute_gradient, bool smearing) {
159  return current_eckart_impl(r, plist, par, dens_type, compute_gradient,
160  smearing);
161 }
162 
163 std::ostream &operator<<(std::ostream &os, DensityType dens_type) {
164  switch (dens_type) {
165  case DensityType::Hadron:
166  os << "hadron density";
167  break;
168  case DensityType::Baryon:
169  os << "baryon density";
170  break;
172  os << "baryonic isospin density";
173  break;
174  case DensityType::Pion:
175  os << "pion density";
176  break;
178  os << "total isospin3 density";
179  break;
180  case DensityType::None:
181  os << "none";
182  break;
183  default:
184  os.setstate(std::ios_base::failbit);
185  }
186  return os;
187 }
188 
189 } // namespace smash
A class to pre-calculate and store parameters relevant for density calculation.
Definition: density.h:106
int isospin3() const
Definition: particletype.h:176
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:30
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:34
int baryon_number() const
Definition: particletype.h:206
Collection of useful constants that are known at compile time.
double sqr() const
Definition: threevector.h:249
double abs() const
calculate the lorentz invariant absolute value
Definition: fourvector.h:441
bool is_pion() const
Definition: pdgcode.h:372
ThreeVector threevec() const
Definition: fourvector.h:306
std::tuple< double, FourVector, ThreeVector, ThreeVector, ThreeVector > current_eckart_impl(const ThreeVector &r, const T &plist, const DensityParameters &par, DensityType dens_type, bool compute_gradient, bool smearing)
Calculates Eckart rest frame density and 4-current of a given density type and optionally the gradien...
Definition: density.cc:67
bool is_baryon() const
Definition: particletype.h:200
bool is_hadron() const
Definition: particletype.h:194
void set_x1(double x)
set first component
Definition: threevector.h:157
double x0() const
Definition: fourvector.h:290
double r_cut_sqr() const
Definition: density.h:133
Particle type contains the static properties of a particle species.
Definition: particletype.h:97
int strangeness() const
Definition: particletype.h:209
int32_t charge() const
The charge of the particle.
Definition: particletype.h:188
double density_factor(const ParticleType &type, DensityType dens_type)
Get the factor that determines how much a particle contributes to the density type that is computed...
Definition: density.cc:17
std::tuple< double, FourVector, ThreeVector, ThreeVector, ThreeVector > current_eckart(const ThreeVector &r, const ParticleList &plist, const DensityParameters &par, DensityType dens_type, bool compute_gradient, bool smearing)
Calculates Eckart rest frame density and 4-current of a given density type and optionally the gradien...
Definition: density.cc:149
void set_x3(double z)
set third component
Definition: threevector.h:165
PdgCode pdgcode() const
Definition: particletype.h:156
constexpr int p
Proton.
std::pair< double, ThreeVector > unnormalized_smearing_factor(const ThreeVector &r, const FourVector &p, const double m_inv, const DensityParameters &dens_par, const bool compute_gradient=false)
Implements gaussian smearing for any quantity.
Definition: density.cc:38
double two_sig_sqr_inv() const
Definition: density.h:135
double isospin3_rel() const
Definition: particletype.h:179
double norm_factor_sf() const
Definition: density.h:141
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
DensityType
Allows to choose which kind of density to calculate.
Definition: density.h:34
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
Definition: action.h:463
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:32
void set_x2(double y)
set second component
Definition: threevector.h:161
Definition: action.h:24