File indexing completed on 2025-08-05 08:19:07
0001
0002
0003
0004
0005 #include "../src/event.h"
0006
0007 #include "catch.hpp"
0008 #include "util.h"
0009
0010 #include "../src/nucleus.h"
0011 #include "../src/random.h"
0012
0013 using namespace trento;
0014
0015 TEST_CASE( "event" ) {
0016
0017
0018
0019 auto pplus = .5 + .49*random::canonical<>();
0020 auto pminus = -.5 + .49*random::canonical<>();
0021 for (auto p : {0., pplus, pminus }) {
0022
0023 auto norm = 1. + .5*random::canonical<>();
0024 auto xsec = 4. + 3.*random::canonical<>();
0025 auto nucleon_width = .5 + .2*random::canonical<>();
0026
0027
0028 auto fluct = 1e12;
0029
0030
0031 auto grid_max = 9.;
0032 auto grid_step = 0.3;
0033 auto grid_nsteps = 60;
0034
0035 auto var_map = make_var_map({
0036 {"normalization", norm},
0037 {"reduced-thickness", p},
0038 {"grid-max", grid_max},
0039 {"grid-step", grid_step},
0040 {"fluctuation", fluct},
0041 {"cross-section", xsec},
0042 {"nucleon-width", nucleon_width},
0043 });
0044
0045 Event event{var_map};
0046 NucleonProfile profile{var_map};
0047
0048 CHECK( event.reduced_thickness_grid().num_dimensions() == 2 );
0049 CHECK( static_cast<int>(event.reduced_thickness_grid().shape()[0]) == grid_nsteps );
0050 CHECK( static_cast<int>(event.reduced_thickness_grid().shape()[1]) == grid_nsteps );
0051
0052 auto nucleusA = Nucleus::create("Pb");
0053 auto nucleusB = Nucleus::create("Pb");
0054
0055
0056 auto b = 4.*std::sqrt(random::canonical<>());
0057 nucleusA->sample_nucleons(+.5*b);
0058 nucleusB->sample_nucleons(-.5*b);
0059
0060 for (auto&& A : *nucleusA)
0061 for (auto&& B : *nucleusB)
0062 profile.participate(A, B);
0063
0064
0065 event.compute(*nucleusA, *nucleusB, profile);
0066
0067
0068 auto count_part = [](const Nucleus& nucleus) {
0069 auto npart = 0;
0070 for (const auto& n : nucleus)
0071 if (n.is_participant())
0072 ++npart;
0073 return npart;
0074 };
0075 auto npart = count_part(*nucleusA) + count_part(*nucleusB);
0076 CHECK( npart == event.npart() );
0077
0078
0079 boost::multi_array<double, 2> TR{boost::extents[grid_nsteps][grid_nsteps]};
0080
0081 auto thickness = [&profile](const Nucleus& nucleus, double x, double y) {
0082 auto t = 0.;
0083 for (const auto& n : nucleus) {
0084 if (n.is_participant()) {
0085 auto dx = n.x() - x;
0086 auto dy = n.y() - y;
0087 t += profile.thickness(dx*dx + dy*dy);
0088 }
0089 }
0090 return t;
0091 };
0092
0093 auto gen_mean = [p](double a, double b) {
0094 if (std::abs(p) < 1e-12)
0095 return std::sqrt(a*b);
0096 else if (p < 0. && (a < 1e-12 || b < 1e-12))
0097 return 0.;
0098 else
0099 return std::pow(.5*(std::pow(a, p) + std::pow(b, p)), 1./p);
0100 };
0101
0102 for (auto iy = 0; iy < grid_nsteps; ++iy) {
0103 for (auto ix = 0; ix < grid_nsteps; ++ix) {
0104 auto x = (ix + .5) * 2 * grid_max/grid_nsteps - grid_max;
0105 auto y = (iy + .5) * 2 * grid_max/grid_nsteps - grid_max;
0106 auto TA = thickness(*nucleusA, x, y);
0107 auto TB = thickness(*nucleusB, x, y);
0108 TR[iy][ix] = norm * gen_mean(TA, TB);
0109 }
0110 }
0111
0112
0113 auto mult = std::pow(2*grid_max/grid_nsteps, 2) *
0114 std::accumulate(TR.origin(), TR.origin() + TR.num_elements(), 0.);
0115 CHECK( mult == Approx(event.multiplicity()) );
0116
0117
0118 auto all_correct = true;
0119 for (const auto* t1 = TR.origin(),
0120 * t2 = event.reduced_thickness_grid().origin();
0121 t1 != TR.origin() + TR.num_elements();
0122 ++t1, ++t2) {
0123 if (*t1 != Approx(*t2).epsilon(1e-5)) {
0124 all_correct = false;
0125 WARN( "TR mismatch: " << *t1 << " != " << *t2 );
0126 break;
0127 }
0128 }
0129 CHECK( all_correct );
0130
0131
0132 auto sum = 0., xcm = 0., ycm = 0.;
0133 for (auto iy = 0; iy < grid_nsteps; ++iy) {
0134 for (auto ix = 0; ix < grid_nsteps; ++ix) {
0135 auto& t = TR[iy][ix];
0136 sum += t;
0137 xcm += t*ix;
0138 ycm += t*iy;
0139 }
0140 }
0141 xcm /= sum;
0142 ycm /= sum;
0143
0144 for (auto n = 2; n <= 5; ++n) {
0145 auto real = 0., imag = 0., weight = 0.;
0146 for (auto iy = 0; iy < grid_nsteps; ++iy) {
0147 for (auto ix = 0; ix < grid_nsteps; ++ix) {
0148 auto x = ix - xcm;
0149 auto y = iy - ycm;
0150 auto w = TR[iy][ix] * std::pow(x*x + y*y, .5*n);
0151
0152 auto phi = std::atan2(y, x);
0153 real += w*std::cos(n*phi);
0154 imag += w*std::sin(n*phi);
0155 weight += w;
0156 }
0157 }
0158 auto ecc = std::sqrt(real*real + imag*imag) / weight;
0159 CHECK( ecc == Approx(event.eccentricity().at(n)).epsilon(1e-6).margin(1e-6) );
0160 }
0161 }
0162
0163
0164 auto var_map = make_var_map({
0165 {"normalization", 1.},
0166 {"reduced-thickness", 0.},
0167 {"grid-max", 10.},
0168 {"grid-step", 0.3}
0169 });
0170
0171 Event event{var_map};
0172
0173 CHECK( event.reduced_thickness_grid().num_dimensions() == 2 );
0174 CHECK( event.reduced_thickness_grid().shape()[0] == 67 );
0175 CHECK( event.reduced_thickness_grid().shape()[1] == 67 );
0176 }