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