11 #include <boost/program_options/variables_map.hpp>
20 constexpr
double TINY = 1
e-12;
24 inline double positive_pmean(
double p,
double a,
double b) {
25 return std::pow(.5*(std::pow(a, p) + std::pow(b, p)), 1./p);
30 inline double negative_pmean(
double p,
double a,
double b) {
31 if (a < TINY || b < TINY)
33 return positive_pmean(p, a, b);
37 inline double geometric_mean(
double a,
double b) {
38 return std::sqrt(a*b);
42 double beam_rapidity(
double beam_energy) {
44 constexpr
double mp = 0.938;
45 return 0.5 * (beam_energy/mp + std::sqrt(std::pow(beam_energy/mp, 2) - 4.));
58 : norm_(var_map[
"normalization"].as<
double>()),
59 beam_energy_(var_map[
"beam-energy"].as<
double>()),
60 exp_ybeam_(beam_rapidity(beam_energy_)),
61 mean_coeff_(var_map[
"mean-coeff"].as<
double>()),
62 std_coeff_(var_map[
"std-coeff"].as<
double>()),
63 skew_coeff_(var_map[
"skew-coeff"].as<
double>()),
64 skew_type_(var_map[
"skew-type"].as<int>()),
65 dxy_(var_map[
"xy-step"].as<
double>()),
66 deta_(var_map[
"eta-step"].as<
double>()),
67 nsteps_(std::ceil(2.*var_map[
"xy-max"].as<
double>()/dxy_)),
68 neta_(std::ceil(2.*var_map[
"eta-max"].as<
double>()/(deta_+1
e-15))),
69 xymax_(.5*nsteps_*dxy_),
70 etamax_(var_map[
"eta-max"].as<
double>()),
71 eta2y_(var_map[
"jacobian"].as<
double>(), etamax_, deta_),
73 TA_(boost::extents[nsteps_][nsteps_]),
74 TB_(boost::extents[nsteps_][nsteps_]),
75 TR_(boost::extents[nsteps_][nsteps_][1]),
76 TAB_(boost::extents[nsteps_][nsteps_]),
77 with_ncoll_(var_map[
"ncoll"].as<bool>()),
78 density_(boost::extents[nsteps_][nsteps_][neta_]) {
85 auto info =
std::string(
"Error: skew coefficent too large to be stable.\n")
86 +
std::string(
"Requirements: (1) relative skew, skew_coeff < 10\n")
87 +
std::string(
" (2) absolute skew, skew_coeff < 3");
88 throw std::invalid_argument(info);
91 catch (
const std::invalid_argument&
error){
92 std::cerr << error.what() << std::endl;
99 auto p = var_map[
"reduced-thickness"].as<
double>();
100 if (std::fabs(p) <
TINY) {
107 [p](
double a,
double b) {
return positive_pmean(p, a, b); });
112 [p](
double a,
double b) {
return negative_pmean(p, a, b); });
135 template <
typename T>
136 inline const T& clip(
const T&
value,
const T&
min,
const T& max) {
149 for (
int iy = 0; iy <
nsteps_; ++iy) {
150 for (
int ix = 0; ix <
nsteps_; ++ix) {
163 double bpp_sq = std::pow(xA - xB, 2) + std::pow(yA - yB, 2);
165 double x = (xA+xB)/2.;
166 double y = (yA+yB)/2.;
168 const double r = profile.
radius();
169 int ixmin = clip(static_cast<int>((x-r)/
dxy_), 0,
nsteps_-1);
170 int iymin = clip(static_cast<int>((y-r)/
dxy_), 0,
nsteps_-1);
171 int ixmax = clip(static_cast<int>((x+r)/
dxy_), 0,
nsteps_-1);
172 int iymax = clip(static_cast<int>((y+r)/
dxy_), 0,
nsteps_-1);
175 auto norm_Tpp = profile.
norm_Tpp(bpp_sq);
176 for (
auto iy = iymin; iy <= iymax; ++iy) {
177 double dysqA = std::pow(yA - (static_cast<double>(iy)+.5)*
dxy_, 2);
178 double dysqB = std::pow(yB - (static_cast<double>(iy)+.5)*
dxy_, 2);
179 for (
auto ix = ixmin; ix <= ixmax; ++ix) {
180 double dxsqA = std::pow(xA - (static_cast<double>(ix)+.5)*
dxy_, 2);
181 double dxsqB = std::pow(xB - (static_cast<double>(ix)+.5)*
dxy_, 2);
204 std::fill(TX.origin(), TX.origin() + TX.num_elements(), 0.);
206 const double r = profile.
radius();
209 for (
const auto& nucleon : nucleus) {
210 if (!nucleon.is_participant())
216 double x = nucleon.x() +
xymax_;
217 double y = nucleon.y() +
xymax_;
220 int ixmin = clip(static_cast<int>((x-r)/
dxy_), 0,
nsteps_-1);
221 int iymin = clip(static_cast<int>((y-r)/
dxy_), 0,
nsteps_-1);
222 int ixmax = clip(static_cast<int>((x+r)/
dxy_), 0,
nsteps_-1);
223 int iymax = clip(static_cast<int>((y+r)/
dxy_), 0,
nsteps_-1);
229 for (
auto iy = iymin; iy <= iymax; ++iy) {
230 double dysq = std::pow(y - (static_cast<double>(iy)+.5)*
dxy_, 2);
231 for (
auto ix = ixmin; ix <= ixmax; ++ix) {
232 double dxsq = std::pow(x - (static_cast<double>(ix)+.5)*
dxy_, 2);
233 TX[iy][ix] += profile.
thickness(dxsq + dysq);
239 template <
typename GenMean>
245 for (
int iy = 0; iy <
nsteps_; ++iy) {
246 for (
int ix = 0; ix <
nsteps_; ++ix) {
247 auto ta =
TA_[iy][ix];
248 auto tb =
TB_[iy][ix];
249 auto t =
norm_ * gen_mean(ta, tb);
260 for (
int ieta = 0; ieta <
neta_; ++ieta) {
265 density_[iy][ix][ieta] =
t * rapidity_dist / mid_norm * jacobian;
272 ixcm +=
t *
static_cast<double>(ix);
273 iycm +=
t *
static_cast<double>(iy);
286 struct EccentricityAccumulator {
290 double finish()
const
291 {
return std::sqrt(re*re + im*im) / std::fmax(wt, TINY); }
293 {
return atan2(im, re); }
296 for (
int iy = 0; iy <
nsteps_; ++iy) {
297 for (
int ix = 0; ix <
nsteps_; ++ix) {
298 const auto&
t =
TR_[iy][ix][0];
303 auto x =
static_cast<double>(ix) -
ixcm_;
308 auto y =
static_cast<double>(iy) -
iycm_;
314 auto r = std::sqrt(
r2);
346 e2.re +=
t * (x2 - y2);
350 e3.re +=
t * (x3 - 3.*x*y2);
351 e3.im +=
t * y*(3. - 4.*y2);
354 e4.re +=
t * (x4 + y4 - 6.*x2y2);
355 e4.im +=
t * 4.*
xy*(1. - 2.*y2);
358 e5.re +=
t * x*(x4 - 10.*x2y2 - 5.*y4);
359 e5.im +=
t * y*(1. - 12.*x2 + 16.*x4);
369 psi_[2] = e2.angle()/2.;
370 psi_[3] = e3.angle()/3.;
371 psi_[4] = e4.angle()/4.;
372 psi_[5] = e5.angle()/5.;