SdSimulation/SdAccidentalInjectorKG/Utilities.h
Go to the documentation of this file.
1 #ifndef _AccidentialInjectorKG_Utilities_h_
2 #define _AccidentialInjectorKG_Utilities_h_
3 
4 #include <utl/Math.h>
5 #include <utl/MathConstants.h>
6 #include <utl/RandomEngine.h>
7 #include <fwk/RandomEngineRegistry.h>
8 
9 #include <CLHEP/Random/Randomize.h>
10 
11 #include <TH2D.h>
12 
13 #include <vector>
14 #include <algorithm>
15 #include <cmath>
16 
17 
18 namespace SdAccidentalInjectorKG {
19 
20  inline
21  std::pair<double, double>
22  StationTopSideArea(const double radius, const double height, const double cosTheta)
23  {
24  const double sinTheta = std::sqrt(1 - utl::Sqr(cosTheta));
25  const double areaTop = cosTheta * utl::kPi * utl::Sqr(radius);
26  const double areaSide = 2 * sinTheta * radius * height;
27  return std::make_pair(areaTop, areaSide);
28  }
29 
30 
31  // station area projected into the plane perpendicular to the particle
32  inline
33  double
34  StationArea(const double radius, const double height, const double cosTheta)
35  {
36  const auto ts = StationTopSideArea(radius, height, cosTheta);
37  return ts.first + ts.second;
38  }
39 
40 
41  class FlatSampler {
42  public:
44  fEngine(&fwk::RandomEngineRegistry::GetInstance().Get(fwk::RandomEngineRegistry::eDetector).GetEngine())
45  { }
46 
47  double operator()(const double vmin, const double vmax) const
48  { return CLHEP::RandFlat::shoot(fEngine, vmin, vmax); }
49 
50  double operator()(const double vmax) const
51  { return CLHEP::RandFlat::shoot(fEngine, 0, vmax); }
52 
53  double operator()() const
54  { return CLHEP::RandFlat::shoot(fEngine, 0, 1); }
55 
56  protected:
58  };
59 
60 
62  public:
64  fEngine(&fwk::RandomEngineRegistry::GetInstance().Get(fwk::RandomEngineRegistry::eDetector).GetEngine())
65  { }
66 
67  double operator()(const double expectation) const
68  { return CLHEP::RandPoisson::shoot(fEngine, expectation); }
69 
70  protected:
72  };
73 
74 
75  /* Strategy:
76  * The PDF is available as a 2D histogram. We should use the Unuran
77  * library to sample from it, but the ROOT interface TUnuran supports
78  * only 1D histograms at the time of this writing.
79  * We therefore apply a custom strategy.
80  *
81  * We integrate over the 2D histogram with a line integral. The line
82  * integral is then inverted as a function of its upper bound.
83  * The inverted function then allows us to convert a uniform random
84  * number to the desired random 2D sample.
85  *
86  * Note that this approach can be generalized to higher dimensions,
87  * but the numerical quality is expected to become worse as the
88  * number of dimensions increases.
89  */
90 
92  public:
94 
95  HistogramSampler(const TH2D& h) :
96  fHistogram(h)
97  {
98  const unsigned int nx = h.GetNbinsX();
99  const unsigned int ny = h.GetNbinsY();
100  fLineIntegral.reserve(nx*ny);
101  double sum = 0;
102  for (unsigned int ix = 1; ix <= nx; ++ix)
103  for (unsigned int iy = 1; iy <= ny; ++iy) {
104  sum += h.GetBinContent(ix, iy);
105  fLineIntegral.push_back(sum);
106  }
107  }
108 
109  std::pair<double, double>
111  const
112  {
113  const double z = fFlat(fLineIntegral.back());
114  // this "inverts" the line integral
115  const auto begin = fLineIntegral.begin();
116  const int i = std::upper_bound(begin, fLineIntegral.end(), z) - begin;
117  const int n = fHistogram.GetNbinsY();
118  const int ix = (i / n) + 1;
119  const int iy = (i % n) + 1;
120 
121  // do flat sampling inside bin
122  const auto& ax = *fHistogram.GetXaxis();
123  const double x = fFlat(ax.GetBinLowEdge(ix), ax.GetBinUpEdge(ix));
124  const auto& ay = *fHistogram.GetYaxis();
125  const double y = fFlat(ay.GetBinLowEdge(iy), ay.GetBinUpEdge(iy));
126  return std::make_pair(x, y);
127  }
128 
129  protected:
131  std::vector<double> fLineIntegral;
133  };
134 
135 
137  public:
139 
140  CylinderSurfaceSampler(const double radius, const double height, const double hull) :
141  // adding walls
142  fRadius(radius + hull),
143  fRadius2(utl::Sqr(fRadius)),
144  fHeight(height + 2*hull),
145  fHull(hull)
146  { }
147 
148  std::tuple<double, double, double>
149  operator()(const double theta, const double phi)
150  const
151  {
152  const auto area = StationTopSideArea(fRadius, fHeight, std::cos(theta));
153  const double totArea = area.first + area.second;
154  // top or side?
155  if (fFlat() < area.first / totArea) {
156  // top
157  const double r = fRadius * std::sqrt(fFlat());
158  const double f = fFlat(2 * utl::kPi);
159  return std::make_tuple(r * std::sin(f), r * std::cos(f), fHeight);
160  }
161  // side
162  const double y = fFlat(-fRadius, fRadius);
163  const double x = std::sqrt(fRadius2 - utl::Sqr(y));
164  const double z = fFlat(fHeight);
165  const double c = std::cos(phi);
166  const double s = std::sin(phi);
167  return std::make_tuple(x*c - y*s, x*s + y*c, z);
168  }
169 
170  protected:
171  double fRadius = 0;
172  double fRadius2 = 0;
173  double fHeight = 0;
174  double fHull = 0;
176  };
177 
178 }
179 
180 
181 #endif
double StationArea(const double radius, const double height, const double cosTheta)
std::pair< double, double > StationTopSideArea(const double radius, const double height, const double cosTheta)
constexpr T Sqr(const T &x)
constexpr double s
Definition: AugerUnits.h:163
constexpr double kPi
Definition: MathConstants.h:24
CylinderSurfaceSampler(const double radius, const double height, const double hull)
double operator()(const double vmin, const double vmax) const
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
std::tuple< double, double, double > operator()(const double theta, const double phi) const
CLHEP::HepRandomEngine RandomEngineType
Definition: RandomEngine.h:30

, generated on Tue Sep 26 2023.