Bridge++  Version 1.4.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
randomNumbers_SFMT.cpp
Go to the documentation of this file.
1 
14 #ifdef USE_SFMTLIB
15 
16 #include "randomNumbers_SFMT.h"
17 
18 #include "timer.h"
19 
20 #include <iomanip>
21 
22 const std::string RandomNumbers_SFMT::class_name = "RandomNumbers:SFMT";
23 
24 #ifdef ENABLE_SFMT_JUMP
25 static const NTL::GF2X ch_poly = sfmt_characteristic_polynomial();
26 #endif
27 
28 //====================================================================
29 RandomNumbers_SFMT::RandomNumbers_SFMT(const int s)
30 {
31  // initialize with seed s
32  sfmt_init_gen_rand(&m_state, s);
33 }
34 
35 
36 //====================================================================
37 void RandomNumbers_SFMT::reset(unsigned long seed)
38 {
39  // initialize with seed
40  sfmt_init_gen_rand(&m_state, seed);
41 }
42 
43 
44 //====================================================================
45 double RandomNumbers_SFMT::get()
46 {
47  return sfmt_genrand_res53(&m_state);
48 }
49 
50 
51 //====================================================================
52 void RandomNumbers_SFMT::get_block(double *v, const size_t n)
53 {
54  for (size_t i = 0; i < n; ++i) {
55  v[i] = get();
56  }
57 }
58 
59 
60 //====================================================================
61 #ifdef ENABLE_SFMT_JUMP
62 
63 void RandomNumbers_SFMT::uniform_lex_global(Field& f)
64 {
65  return generate_global_jump<RandomNumbers::rand_uniform>(f);
66 }
67 
68 
69 //====================================================================
70 void RandomNumbers_SFMT::gauss_lex_global(Field& f)
71 {
72  if (f.nin() % 2 == 0) {
73  return generate_global_jump<RandomNumbers::rand_gauss_even>(f);
74  } else {
75  return generate_global_jump<RandomNumbers::rand_gauss_odd>(f);
76  }
77 }
78 
79 
80 //====================================================================
81 template<typename InnerGenerator>
82 void RandomNumbers_SFMT::generate_global_jump(Field& f)
83 {
84  InnerGenerator fill(f, this);
85 
86  const int Nin = f.nin();
87  const int Nvol = f.nvol();
88  const int Nex = f.nex();
89 
90  if (Communicator::size() == 1) {
91  vout.detailed(m_vl, "%s: single node. no need to consider division.\n", class_name.c_str());
92 
93  for (int j = 0; j < Nex; ++j) {
94  for (int isite = 0; isite < Nvol; ++isite) {
95  fill(true);
96  }
97  }
98  } else {
99  if (f.nvol() != CommonParameters::Nvol()) {
100  vout.crucial(m_vl, "Error at %s::%s: Nvol mismatch.\n", class_name.c_str(), __func__);
101  exit(EXIT_FAILURE);
102  }
103 
104  // duplicate mt state for backup.
105  sfmt_t rng_state = m_state;
106 
107  const int Lx = CommonParameters::Lx();
108  const int Ly = CommonParameters::Ly();
109  const int Lz = CommonParameters::Lz();
110  const int Lt = CommonParameters::Lt();
111  const int Lvol = CommonParameters::Lvol();
112 
113  const int Nx = CommonParameters::Nx();
114  const int Ny = CommonParameters::Ny();
115  const int Nz = CommonParameters::Nz();
116  const int Nt = CommonParameters::Nt();
117  const int Nvol = CommonParameters::Nvol();
118 
119  const int Gx = Communicator::npe(0);
120  const int Gy = Communicator::npe(1);
121  const int Gz = Communicator::npe(2);
122  const int Gt = Communicator::npe(3);
123  const int NPE = Communicator::size();
124 
125  vout.detailed(m_vl, "L = { %2d, %2d, %2d, %2d }, Lvol = %d\n", Lx, Ly, Lz, Lt, Lvol);
126  vout.detailed(m_vl, "N = { %2d, %2d, %2d, %2d }, Nvol = %d\n", Nx, Ny, Nz, Nt, Nvol);
127  vout.detailed(m_vl, "G = { %2d, %2d, %2d, %2d }, NPE = %d\n", Gx, Gy, Gz, Gt, NPE);
128 
129  // calculate jump polynomials
130  sfmt_jump_t jump_y;
131  sfmt_jump_t jump_z;
132  sfmt_jump_t jump_t;
133  // for external degree of freedom
134  sfmt_jump_t jump_w;
135 
136  size_t block_size = fill.block_size();
137 
138  if (Lx - Nx != 0)
139  sfmt_calculate_jump_polynomial(jump_y, block_size * (Lx - Nx), ch_poly);
140  if (Ly - Ny != 0)
141  sfmt_calculate_jump_polynomial(jump_z, block_size * (Lx * (Ly - Ny)), ch_poly);
142  if (Lz - Nz != 0)
143  sfmt_calculate_jump_polynomial(jump_t, block_size * (Lx * Ly * (Lz - Nz)), ch_poly);
144  if (Lt - Nt != 0)
145  sfmt_calculate_jump_polynomial(jump_w, block_size * (Lx * Ly * Lz * (Lt - Nt)), ch_poly);
146 
147 #define calc_global_index(x, y, z, t) \
148  (x) + Lx * ((y) + Ly * ((z) + Lz * (t)))
149 
150 #define calc_local_index(x, y, z, t) \
151  (x) + Nx * ((y) + Ny * ((z) + Nz * (t)))
152 
153  int ipe = Communicator::self();
154 
155  int gx = Communicator::ipe(0);
156  int gy = Communicator::ipe(1);
157  int gz = Communicator::ipe(2);
158  int gt = Communicator::ipe(3);
159 
160 // vout.detailed(m_vl, "ipe = %d: (%d, %d, %d, %d)\n", ipe, gx, gy, gz, gt);
161 
162  int global_index = calc_global_index(Nx * gx, Ny * gy, Nz * gz, Nt * gt);
163 
164  // initial shift
165  sfmt_jump(&m_state, block_size * global_index, ch_poly);
166 
167  // generate random numbers
168  double *p = f.ptr(0);
169 
170  for (int j = 0; j < Nex; ++j) {
171  for (int t = 0; t < Nt; ++t) {
172  for (int z = 0; z < Nz; ++z) {
173  for (int y = 0; y < Ny; ++y) {
174  for (int x = 0; x < Nx; ++x) {
175  fill(true);
176  }
177 
178  // jump to next row
179  if (Lx - Nx != 0)
180  sfmt_jump_by_polynomial(&m_state, jump_y);
181  }
182 
183  if (Ly - Ny != 0)
184  sfmt_jump_by_polynomial(&m_state, jump_z);
185  }
186 
187  if (Lz - Nz != 0)
188  sfmt_jump_by_polynomial(&m_state, jump_t);
189  }
190 
191  if (Lt - Nt != 0)
192  sfmt_jump_by_polynomial(&m_state, jump_w);
193  }
194 
195  // restore original state and jump by global size.
196  m_state = rng_state;
197  sfmt_jump(&m_state, block_size * Lvol * Nex, ch_poly);
198 
199 
200 #undef calc_global_index
201 #undef calc_local_index
202  } // if communicator::size == 1
203 }
204 #endif /* ENABLE_SFMT_JUMP */
205 
206 //====================================================================
207 
208 // /**
209 // * SFMT internal state
210 // */
211 // struct SFMT_T {
212 // /** the 128-bit internal state array */
213 // w128_t state[SFMT_N];
214 // /** index counter to the 32-bit internal state array */
215 // int idx;
216 // };
217 //
218 // typedef struct SFMT_T sfmt_t;
219 
220 void RandomNumbers_SFMT::write_file(const std::string& filename)
221 {
222  vout.detailed(m_vl, "%s: save random number state to file %s\n", class_name.c_str(), filename.c_str());
223 
224  if (Communicator::is_primary()) {
225  std::ofstream out_file(filename.c_str());
226 
227  if (!out_file) {
228  vout.crucial(m_vl, "Error at %s: unable to open output file.\n", class_name.c_str());
229  exit(EXIT_FAILURE);
230  }
231 
232  for (int i = 0; i < SFMT_N; ++i) {
233  out_file << std::setw(8) << std::setfill('0') << std::hex << m_state.state[i].u[0] << " ";
234  out_file << std::setw(8) << std::setfill('0') << std::hex << m_state.state[i].u[1] << " ";
235  out_file << std::setw(8) << std::setfill('0') << std::hex << m_state.state[i].u[2] << " ";
236  out_file << std::setw(8) << std::setfill('0') << std::hex << m_state.state[i].u[3] << " ";
237  out_file << std::endl;
238  }
239 
240  out_file << std::dec << m_state.idx << std::endl;
241 
242  out_file.close();
243  }
244 }
245 
246 
247 //====================================================================
248 void RandomNumbers_SFMT::read_file(const std::string& filename)
249 {
250  vout.detailed(m_vl, "%s: read random number state from file %s\n", class_name.c_str(), filename.c_str());
251 
252  if (Communicator::is_primary()) {
253  std::ifstream in_file(filename.c_str());
254 
255  if (!in_file) {
256  vout.crucial(m_vl, "Error at %s: unable to open output file.\n", class_name.c_str());
257  exit(EXIT_FAILURE);
258  }
259 
260  for (int i = 0; i < SFMT_N; ++i) {
261  in_file >> std::hex >> m_state.state[i].u[0];
262  in_file >> std::hex >> m_state.state[i].u[1];
263  in_file >> std::hex >> m_state.state[i].u[2];
264  in_file >> std::hex >> m_state.state[i].u[3];
265  }
266 
267  in_file >> std::dec >> m_state.idx;
268 
269  in_file.close();
270  }
271 
272  Communicator::Base::broadcast(sizeof(sfmt_t), &m_state, 0);
273 }
274 
275 
276 //====================================================================
277 //============================================================END=====
278 #endif // USE_SFMTLIB
BridgeIO vout
Definition: bridgeIO.cpp:495
void detailed(const char *format,...)
Definition: bridgeIO.cpp:212
static int npe(const int dir)
logical grid extent
const double * ptr(const int jin, const int site, const int jex) const
Definition: field.h:142
static int self()
rank within small world.
Container of Field-type object.
Definition: field.h:39
int nvol() const
Definition: field.h:116
static int broadcast(size_t size, void *data, int sender)
static int ipe(const int dir)
logical coordinate of current proc.
static int Lvol()
int nin() const
Definition: field.h:115
int nex() const
Definition: field.h:117
void crucial(const char *format,...)
Definition: bridgeIO.cpp:178
static int size()
size of small world.
static bool is_primary()
check if the present node is primary in small communicator.