Line data Source code
1 : // Class NormalDistribution
2 : // This class can be used for sampling normal distribution function
3 : // on bounded domain, e.g. using Inverse Transform Sampling.
4 : //
5 : #ifndef IPPL_NORMAL_DISTRIBUTION_H
6 : #define IPPL_NORMAL_DISTRIBUTION_H
7 :
8 : #include "Random/Distribution.h"
9 : #include "Random/Utility.h"
10 :
11 : namespace ippl {
12 : namespace random {
13 :
14 : /*!
15 : * @brief Calculate the cumulative distribution function (CDF) for a normal distribution.
16 : *
17 : * @param x Input value.
18 : * @param mean Mean of the distribution.
19 : * @param stddev Standard deviation of the distribution.
20 : * @return The CDF value.
21 : */
22 : template <typename T>
23 0 : KOKKOS_FUNCTION T normal_cdf_func(T x, T mean, T stddev) {
24 0 : return 0.5 * (1 + Kokkos::erf((x - mean) / (stddev * Kokkos::sqrt(2.0))));
25 : }
26 :
27 : /*!
28 : * @brief Calculate the probability density function (PDF) for a normal distribution.
29 : *
30 : * @param x Input value.
31 : * @param mean Mean of the distribution.
32 : * @param stddev Standard deviation of the distribution.
33 : * @return The PDF value.
34 : */
35 : template <typename T>
36 0 : KOKKOS_FUNCTION T normal_pdf_func(T x, T mean, T stddev) {
37 0 : const T pi = Kokkos::numbers::pi_v<T>;
38 0 : return (1.0 / (stddev * Kokkos::sqrt(2 * pi)))
39 0 : * Kokkos::exp(-(x - mean) * (x - mean) / (2 * stddev * stddev));
40 : }
41 :
42 : /*!
43 : * @brief An estimator for the initial guess that is used in Newton-Raphson method of
44 : * Inverste Transfrom Sampling
45 : *
46 : * @param x Input value.
47 : * @param mean Mean of the distribution.
48 : * @param stddev Standard deviation of the distribution.
49 : * @return The estimate value.
50 : */
51 : template <typename T>
52 0 : KOKKOS_FUNCTION T normal_estimate_func(T u, T mean, T stddev) {
53 0 : return mean + 0. * u * stddev;
54 : }
55 :
56 : /*!
57 : * @struct normal_cdf
58 : * @brief Functor to calculate the cumulative distribution function (CDF) for a normal
59 : * distribution.
60 : *
61 : * This functor calculates the CDF for a normal distribution in a specific dimension 'd'.
62 : *
63 : * @tparam T Data type for the input value 'x'.
64 : */
65 : template <typename T>
66 : struct normal_cdf {
67 : KOKKOS_INLINE_FUNCTION double operator()(T x, unsigned int d, const T* params_p) const {
68 : T mean = params_p[2 * d + 0];
69 : T stddev = params_p[2 * d + 1];
70 : return ippl::random::normal_cdf_func<T>(x, mean, stddev);
71 : }
72 : };
73 :
74 : /*!
75 : * @struct normal_pdf
76 : * @brief Functor to calculate the probability density function (PDF) for a normal
77 : * distribution.
78 : *
79 : * This functor calculates the PDF for a normal distribution in a specific dimension 'd'.
80 : *
81 : * @tparam T Data type for the input value 'x'.
82 : */
83 : template <typename T>
84 : struct normal_pdf {
85 : KOKKOS_INLINE_FUNCTION double operator()(T x, unsigned int d, T const* params_p) const {
86 : T mean = params_p[2 * d + 0];
87 : T stddev = params_p[2 * d + 1];
88 : return ippl::random::normal_pdf_func<T>(x, mean, stddev);
89 : }
90 : };
91 :
92 : /*!
93 : * @struct normal_estimate
94 : * @brief Functor to estimate the initial guess for sampling normal distribution.
95 : *
96 : * This functor estimates the value for a normal distribution in a specific dimension 'd'.
97 : *
98 : * @tparam T Data type for the input value 'u'.
99 : */
100 : template <typename T>
101 : struct normal_estimate {
102 : KOKKOS_INLINE_FUNCTION double operator()(T u, unsigned int d, T const* params_p) const {
103 : T mean = params_p[2 * d + 0];
104 : T stddev = params_p[2 * d + 1];
105 : return ippl::random::normal_estimate_func<T>(u, mean, stddev);
106 : }
107 : };
108 :
109 : template <typename T>
110 : struct NormalDistributionFunctions {
111 : // Functor to calculate the probability density function (PDF) for a normal
112 : // distribution.
113 : struct PDF {
114 0 : KOKKOS_INLINE_FUNCTION double operator()(T x, unsigned int d,
115 : const T* params_p) const {
116 0 : T mean = params_p[2 * d + 0];
117 0 : T stddev = params_p[2 * d + 1];
118 0 : return ippl::random::normal_pdf_func<T>(x, mean, stddev);
119 : }
120 : };
121 :
122 : // Functor to calculate the cumulative distribution function (CDF) for a normal
123 : // distribution.
124 : struct CDF {
125 0 : KOKKOS_INLINE_FUNCTION double operator()(T x, unsigned int d,
126 : const T* params_p) const {
127 0 : T mean = params_p[2 * d + 0];
128 0 : T stddev = params_p[2 * d + 1];
129 0 : return ippl::random::normal_cdf_func<T>(x, mean, stddev);
130 : }
131 : };
132 :
133 : // Functor to estimate the initial guess for sampling a normal distribution.
134 : struct Estimate {
135 0 : KOKKOS_INLINE_FUNCTION double operator()(T u, unsigned int d,
136 : T const* params_p) const {
137 0 : T mean = params_p[2 * d + 0];
138 0 : T stddev = params_p[2 * d + 1];
139 0 : return ippl::random::normal_estimate_func<T>(u, mean, stddev);
140 : }
141 : };
142 : };
143 :
144 : /*!
145 : * @file NormalDistribution.h
146 : * @class NormalDistribution
147 : */
148 : template <typename T, unsigned Dim>
149 : class NormalDistribution
150 : : public ippl::random::Distribution<T, Dim, 2 * Dim, NormalDistributionFunctions<T>> {
151 : public:
152 : /*!
153 : * @brief Constructor for the Normal Distribution class.
154 : * The constructor takes an array of parameters of normal distribution, i.e. mean and
155 : * standard deviation.
156 : */
157 0 : KOKKOS_INLINE_FUNCTION NormalDistribution(const T* par_p)
158 : : ippl::random::Distribution<T, Dim, 2 * Dim, NormalDistributionFunctions<T>>(
159 0 : par_p) {}
160 : };
161 :
162 : } // namespace random
163 : } // namespace ippl
164 :
165 : #endif
|