Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
test_nucleon.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file test_nucleon.cxx
1 // TRENTO: Reduced Thickness Event-by-event Nuclear Topology
2 // Copyright 2015 Jonah E. Bernhard, J. Scott Moreland
3 // MIT License
4 
5 #include "../src/nucleon.h"
6 
7 #include <cmath>
8 
9 #include "catch.hpp"
10 #include "util.h"
11 
12 #include "../src/nucleus.h"
13 #include "../src/random.h"
14 
15 using namespace trento;
16 
17 TEST_CASE( "nucleon" ) {
18  auto fluct = 1. + .5*random::canonical<>();
19  auto xsec = 4. + 3.*random::canonical<>();
20  auto width = .5 + .2*random::canonical<>();
21  auto wsq = width*width;
22 
23  auto var_map = make_var_map({
24  {"fluctuation", fluct},
25  {"cross-section", xsec},
26  {"nucleon-width", width},
27  });
28 
29  NucleonProfile profile{var_map};
30  profile.fluctuate();
31 
32  // truncation radius
33  auto R = profile.radius();
34  CHECK( R == Approx(5*width) );
35 
36  // thickness function
37  // check relative to zero
38  auto tzero = profile.thickness(0.);
39  CHECK( profile.thickness(wsq) == Approx(tzero*std::exp(-.5)) );
40 
41  // random point inside radius
42  auto dsq = std::pow(R*random::canonical<>(), 2);
43  CHECK( profile.thickness(dsq) == Approx(tzero*std::exp(-.5*dsq/wsq)).epsilon(1e-5).margin(1e-5) );
44 
45  // random point outside radius
46  dsq = std::pow(R*(1+random::canonical<>()), 2);
47  CHECK( profile.thickness(dsq) == 0. );
48 
49  // fluctuations
50  // just check they have unit mean -- the rest is handled by the C++ impl.
51  auto total = 0.;
52  auto n = 1e6;
53  for (auto i = 0; i < static_cast<int>(n); ++i) {
54  profile.fluctuate();
55  total += profile.thickness(0.) * (2*M_PI*wsq);
56  }
57 
58  auto mean = total/n;
59  CHECK( mean == Approx(1.).epsilon(.003) );
60 
61  // must use a Nucleus to set Nucleon position
62  // Proton conveniently sets a deterministic position
63  // a mock class would be better but this works fine
64  Proton A{}, B{};
65  A.sample_nucleons(0.);
66  B.sample_nucleons(0.);
67  auto& nA = *A.begin();
68  auto& nB = *B.begin();
69  CHECK( nA.x() == 0. );
70  CHECK( nA.y() == 0. );
71  CHECK( nA.z() == 0. );
72  CHECK( !nA.is_participant() );
73 
74  // wait until the nucleons participate
75  while (!profile.participate(nA, nB)) {}
76  CHECK( nA.is_participant() );
77  CHECK( nB.is_participant() );
78 
79  // resampling nucleons resets participant state
80  A.sample_nucleons(0.);
81  CHECK( !nA.is_participant() );
82 
83  // test cross section
84  // min-bias impact params
85  auto bmax = profile.max_impact();
86  CHECK( bmax == Approx(6*width) );
87 
88  auto nev = 1e6;
89  auto count = 0;
90  for (auto i = 0; i < static_cast<int>(nev); ++i) {
91  auto b = bmax * std::sqrt(random::canonical<>());
92  A.sample_nucleons(.5*b);
93  B.sample_nucleons(-.5*b);
94  if (profile.participate(nA, nB))
95  ++count;
96  }
97 
98  auto xsec_mc = M_PI*bmax*bmax * static_cast<double>(count)/nev;
99 
100  // precision is better than this, but let's be conservative
101  CHECK( xsec_mc == Approx(xsec).epsilon(.02) );
102 
103  // impact larger than max should never participate
104  auto b = bmax + random::canonical<>();
105  A.sample_nucleons(.5*b);
106  B.sample_nucleons(-.5*b);
107  CHECK( !profile.participate(nA, nB) );
108 
109  // very large fluctuation parameters mean no fluctuations
110  auto no_fluct_var_map = make_var_map({
111  {"fluctuation", 1e12},
112  {"cross-section", xsec},
113  {"nucleon-width", width},
114  });
115 
116  NucleonProfile no_fluct_profile{no_fluct_var_map};
117  no_fluct_profile.fluctuate();
118  CHECK( no_fluct_profile.thickness(0) == Approx(1/(2*M_PI*wsq)) );
119 
120  CHECK_THROWS_AS([]() {
121  // nucleon width too small
122  auto bad_var_map = make_var_map({
123  {"fluctuation", 1.},
124  {"cross-section", 5.},
125  {"nucleon-width", .1},
126  });
127  NucleonProfile bad_profile{bad_var_map};
128  }(),
129  std::domain_error);
130 }