Version: SMASH-2.1
pauliblocking.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2020
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/pauliblocking.h"
11 #include "smash/constants.h"
12 #include "smash/logging.h"
13 
14 namespace smash {
15 static constexpr int LPauliBlocking = LogArea::PauliBlocking::id;
16 
18  const ExperimentParameters &param)
19  : sig_(param.gaussian_sigma),
20  rc_(conf.take({"Gaussian_Cutoff"}, 2.2)),
21  rr_(conf.take({"Spatial_Averaging_Radius"}, 1.86)),
22  rp_(conf.take({"Momentum_Averaging_Radius"}, 0.08)),
23  ntest_(param.testparticles),
24  n_ensembles_(param.n_ensembles) {
49  if (ntest_ * n_ensembles_ < 20) {
50  logg[LPauliBlocking].warn(
51  "Phase-space density calculation in Pauli blocking"
52  " will not work reasonably. Either use testparticles or ensembles, or "
53  "both."
54  " The recommended testparticles * ensembles is at least 20");
55  }
56 
57  if (rc_ < rr_ || rr_ < 0.0 || rp_ < 0) {
58  logg[LPauliBlocking].error(
59  "Please choose reasonable parameters for Pauli blocking:"
60  "All radii have to be positive and Gaussian_Cutoff should"
61  "be larger than Spatial_Averaging_Radius");
62  }
63 
64  init_weights_analytical();
65 }
66 
67 PauliBlocker::~PauliBlocker() {}
68 
69 double PauliBlocker::phasespace_dens(const ThreeVector &r, const ThreeVector &p,
70  const std::vector<Particles> &ensembles,
71  const PdgCode pdg,
72  const ParticleList &disregard) const {
73  double f = 0.0;
74 
75  /* TODO(oliiny): looping over all particles is inefficient,
76  * I need only particles within rp_ radius in momentum and
77  * within rr_+rc_ in coordinate space. Some search algorithm might help. */
78  for (const Particles &particles : ensembles) {
79  for (const ParticleData &part : particles) {
80  // Only consider identical particles
81  if (part.pdgcode() != pdg) {
82  continue;
83  }
84  // Only consider momenta in sphere of radius rp_ with center at p
85  const double pdist_sqr = (part.momentum().threevec() - p).sqr();
86  if (pdist_sqr > rp_ * rp_) {
87  continue;
88  }
89  const double rdist_sqr = (part.position().threevec() - r).sqr();
90  // Only consider coordinates in sphere of radius rr_+rc_ with center at r
91  if (rdist_sqr >= (rr_ + rc_) * (rr_ + rc_)) {
92  continue;
93  }
94  // Do not count particles that should be disregarded.
95  bool to_disregard = false;
96  for (const auto &disregard_part : disregard) {
97  if (part.id() == disregard_part.id()) {
98  to_disregard = true;
99  }
100  }
101  if (to_disregard) {
102  continue;
103  }
104  // 1st order interpolation using tabulated values
105  const double i_real =
106  std::sqrt(rdist_sqr) / (rr_ + rc_) * weights_.size();
107  const size_t i = std::floor(i_real);
108  const double rest = i_real - i;
109  if (likely(i + 1 < weights_.size())) {
110  f += weights_[i] * rest + weights_[i + 1] * (1. - rest);
111  }
112  } // loop over particles in one ensemble
113  } // loop over ensembles
114  return f / ntest_ / n_ensembles_;
115 }
116 
117 void PauliBlocker::init_weights_analytical() {
118  const double pi = M_PI;
119  const double sqrt2 = std::sqrt(2.);
120  const double sqrt_2pi = std::sqrt(2. * pi);
121  // Volume of the phase-space area; Factor 2 stands for spin.
122  const double phase_volume =
123  2 * (4. / 3. * pi * rr_ * rr_ * rr_) * (4. / 3. * pi * rp_ * rp_ * rp_) /
124  ((2 * pi * hbarc) * (2 * pi * hbarc) * (2 * pi * hbarc));
125  // Analytical expression for integral in denominator
126  const double norm =
127  std::erf(rc_ / sqrt2 / sig_) -
128  rc_ * 2 / sqrt_2pi / sig_ * std::exp(-0.5 * rc_ * rc_ / sig_ / sig_);
129 
130  double integral;
131  // Step of the table for tabulated integral
132  const double d_pos = (rr_ + rc_) / static_cast<double>(weights_.size());
133 
134  for (size_t k = 0; k < weights_.size(); k++) {
135  // rdist = 0 ... rc_ (gauss cut) + rr_ (position cut)
136  const double rj = d_pos * k;
137  if (rj < really_small) {
138  // Assuming rc_ > rr_
139  const double A = rr_ / sqrt2 / sig_;
140  integral = sqrt_2pi * sig_ * std::erf(A) - 2 * rr_ * std::exp(-A * A);
141  integral *= sig_ * sig_;
142  } else if (rc_ > rj + rr_) {
143  const double A = (rj + rr_) / sqrt2 / sig_;
144  const double B = (rj - rr_) / sqrt2 / sig_;
145  integral = sig_ / rj * (std::exp(-A * A) - std::exp(-B * B)) +
146  0.5 * sqrt_2pi * (std::erf(A) - std::erf(B));
147  integral *= sig_ * sig_ * sig_;
148  } else {
149  const double A = rc_ / sqrt2 / sig_;
150  const double B = (rj - rr_) / sqrt2 / sig_;
151  const double C = (rc_ - rj) * (rc_ - rj) - rr_ * rr_ + 2 * sig_ * sig_;
152  integral =
153  (0.5 * std::exp(-A * A) * C - sig_ * sig_ * std::exp(-B * B)) / rj +
154  0.5 * sqrt_2pi * sig_ * (std::erf(A) - std::erf(B));
155  integral *= sig_ * sig_;
156  }
157  integral *= 2 * pi / std::pow(2 * pi * sig_ * sig_, 1.5);
158  weights_[k] = integral / norm / phase_volume;
159  logg[LPauliBlocking].debug("Analytical weights[", k, "] = ", weights_[k]);
160  }
161 }
162 
163 } // namespace smash
Interface to the SMASH configuration files.
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:58
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
PauliBlocker(Configuration conf, const ExperimentParameters &parameters)
PauliBlocker constructor.
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
Definition: pdgcode.h:108
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
Collection of useful constants that are known at compile time.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
#define likely(x)
Tell the branch predictor that this expression is likely true.
Definition: macros.h:14
constexpr int p
Proton.
Definition: action.h:24
static constexpr int LPauliBlocking
Definition: action.cc:26
constexpr double hbarc
GeV <-> fm conversion factor.
Definition: constants.h:25
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
Helper structure for Experiment.