ASCOT5
Loading...
Searching...
No Matches
random.c
Go to the documentation of this file.
1
5#if defined(RANDOM_MKL)
6
7#include <mkl_vsl.h>
8#include "random.h"
9
10void random_mkl_init(random_data* rdata, int seed) {
11 vslNewStream(&rdata->r, RANDOM_MKL_RNG, seed);
12}
13
14double random_mkl_uniform(random_data* rdata) {
15 double r;
16 vdRngUniform(VSL_RNG_METHOD_UNIFORM_STD, rdata->r, 1, &r, 0.0, 1.0);
17 return r;
18}
19
20double random_mkl_normal(random_data* rdata) {
21 double r;
22 vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER, rdata->r, 1, &r, 0.0, 1.0);
23 return r;
24}
25
26void random_mkl_uniform_simd(random_data* rdata, int n, double* r) {
27 vdRngUniform(VSL_RNG_METHOD_UNIFORM_STD, rdata->r, n, r, 0.0, 1.0);
28}
29
30void random_mkl_normal_simd(random_data* rdata, int n, double* r) {
31 vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2, rdata->r, n, r, 0.0, 1.0);
32}
33
34
35#elif defined(RANDOM_GSL)
36
37#include <gsl/gsl_rng.h>
38#include "random.h"
39
40void random_gsl_init(random_data* rdata, int seed) {
41 rdata->r = gsl_rng_alloc(gsl_rng_mt19937);
42 gsl_rng_set(rdata->r, seed);
43}
44
45double random_gsl_uniform(random_data* rdata) {
46 return gsl_rng_uniform(rdata->r);
47}
48
49double random_gsl_normal(random_data* rdata) {
50 return gsl_ran_gaussian(rdata->r, 1.0);
51}
52
53void random_gsl_uniform_simd(random_data* rdata, int n, double* r) {
54 #pragma omp simd
55 for(int i = 0; i < n; i++) {
56 r[i] = gsl_rng_uniform(rdata->r);
57 }
58}
59
60void random_gsl_normal_simd(random_data* rdata, int n, double* r) {
61 #pragma omp simd
62 for(int i = 0; i < n; i++) {
63 r[i] = gsl_ran_gaussian(rdata->r, 1.0);
64 }
65}
66
67
68#elif defined(RANDOM_LCG)
69
70#include <stdint.h>
71#include <math.h>
72#include "ascot5.h"
73#include "consts.h"
74#include "random.h"
75
76void random_lcg_init(random_data* rdata, uint64_t seed) {
77 rdata->r = seed;
78}
79
80uint64_t random_lcg_integer(random_data* rdata) {
81 /* parameters from https://nuclear.llnl.gov/CNP/rng/rngman/node4.html */
82 uint64_t a = 2862933555777941757;
83 uint64_t b = 3037000493;
84 rdata->r = (a * rdata->r + b);
85 return rdata->r;
86}
87
88double random_lcg_uniform(random_data* rdata) {
89 double r;
90 random_lcg_uniform_simd(rdata, 1, &r);
91 return r;
92}
93
94double random_lcg_normal(random_data* rdata) {
95 double r;
96 random_lcg_normal_simd(rdata, 1, &r);
97 return r;
98}
99
100void random_lcg_uniform_simd(random_data* rdata, int n, double* r) {
101#ifndef GPU
102 #pragma omp simd
103#endif
104 for(int i = 0; i < n; i++) {
105 r[i] = (double) random_lcg_integer(rdata) / UINT64_MAX;
106 }
107}
108
109void random_lcg_normal_simd(random_data* rdata, int n, double* r) {
110 double x1, x2, w; /* Helper variables */
111 int isEven = (n+1) % 2; /* Indicates if even number of random numbers are
112 requested */
113
114#if A5_CCOL_USE_GEOBM == 1
115 /* The geometric form */
116 GPU_PARALLEL_LOOP_ALL_LEVELS
117 for(int i = 0; i < n; i=i+2) {
118 w = 2.0;
119 while( w >= 1.0 ) {
120 x1 = 2*random_lcg_uniform(rdata)-1;
121 x2 = 2*random_lcg_uniform(rdata)-1;
122 w = x1*x1 + x2*x2;
123 }
124
125 w = sqrt( (-2 * log( w ) ) / w );
126 r[i] = x1 * w;
127 if((i < n-2) || (isEven > 0)) {
128 r[i+1] = x2 * w;
129 }
130 }
131#else
132 /* The common form */
133 double s;
134 GPU_PARALLEL_LOOP_ALL_LEVELS
135 for(int i = 0; i < n; i=i+2) {
136 x1 = random_lcg_uniform(rdata);
137 x2 = random_lcg_uniform(rdata);
138 w = sqrt(-2*log(x1));
139 s = cos(CONST_2PI*x2);
140 r[i] = w*s;
141 if((i < n-2) || (isEven > 0) ) {
142 if(x2 < 0.5) {
143 r[i+1] = w*sqrt(1-s*s);
144 }
145 else {
146 r[i+1] = -w*sqrt(1-s*s);
147 }
148 }
149 }
150#endif
151}
152
153#else /* No RNG lib defined, use drand48 */
154
155#include <stdlib.h>
156#include <math.h>
157#include "ascot5.h"
158#include "consts.h"
159#include "random.h"
160
167 double r;
169 return r;
170}
171
180void random_drand48_uniform_simd(int n, double* r) {
181 #pragma omp simd
182 for(int i = 0; i < n; i++) {
183 r[i] = drand48();
184 }
185}
186
195void random_drand48_normal_simd(int n, double* r) {
196 double x1, x2, w; /* Helper variables */
197 int isEven = (n+1) % 2; /* Indicates if even number of random numbers
198 are requested */
199
200#if A5_CCOL_USE_GEOBM == 1
201 /* The geometric form */
202 #pragma omp simd
203 for(int i = 0; i < n; i=i+2) {
204 w = 2.0;
205 while( w >= 1.0 ) {
206 x1 = 2*drand48()-1;
207 x2 = 2*drand48()-1;
208 w = x1*x1 + x2*x2;
209 }
210
211 w = sqrt( (-2 * log( w ) ) / w );
212 r[i] = x1 * w;
213 if((i < n-2) || (isEven > 0)) {
214 r[i+1] = x2 * w;
215 }
216 }
217#else
218 /* The common form */
219 double s;
220 #pragma omp simd
221 for(int i = 0; i < n; i=i+2) {
222 x1 = drand48(rdata);
223 x2 = drand48(rdata);
224 w = sqrt(-2*log(x1));
225 s = cos(CONST_2PI*x2);
226 r[i] = w*s;
227 if((i < n-2) || (isEven > 0) ) {
228 if(x2 < 0.5) {
229 r[i+1] = w*sqrt(1-s*s);
230 }
231 else {
232 r[i+1] = -w*sqrt(1-s*s);
233 }
234 }
235 }
236#endif
237}
238
239#endif
random_data rdata
Definition afsi.c:22
Main header file for ASCOT5.
Header file containing physical and mathematical constants.
#define CONST_2PI
2*pi
Definition consts.h:14
Header file for math.c.
void random_drand48_uniform_simd(int n, double *r)
Vectorised sampling from uniform distribution.
Definition random.c:180
double random_drand48_normal()
Initialize random generator which uses the linear congruential algorithm and 48-bit integer arithmeti...
Definition random.c:166
void random_drand48_normal_simd(int n, double *r)
Vectorised sampling from normal distribution.
Definition random.c:195
Header file for random.c.
void * random_data
Definition random.h:87