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