Bridge++  Ver. 1.2.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test_RandomNumbers_MT19937_Global.cpp
Go to the documentation of this file.
1 
14 #include "test.h"
15 #include "randomNumbers_MT19937.h"
16 #include "field_G.h"
17 #include "fieldIO_Text.h" // for gather field
18 #include "io_format_gauge.h"
19 
20 //====================================================================
22 
23 namespace Test_RandomNumbers_MT19937 {
24  const std::string test_name = "RandomNumbers.MT19937.Global";
25 
26  //- test-private parameters
27  namespace {
28  const std::string filename_input = "test_RandomNumbers_MT19937_Global.yaml";
29  const std::string filename_output = "stdout";
30 
31  class Parameters_Test_RandomNumbers : public Parameters {
32  public:
33  Parameters_Test_RandomNumbers()
34  {
35  Register_int("seed", 0);
36 
37  Register_string("verbose_level", "NULL");
38 
39  Register_double("expected_result", 0.0);
40  }
41  };
42  }
43 
44  //- prototype declaration
45  int test_global(void);
46 
47 #ifdef USE_TESTMANAGER_AUTOREGISTER
48  namespace {
49  static const bool is_registered = TestManager::RegisterTest(
50  test_name,
52  );
53  }
54 #endif
55 
56  //====================================================================
57  int test_global(void)
58  {
59  // #### parameter setup ####
60  Parameters *params_test = new Parameters_Test_RandomNumbers;
61  Parameters *params_all = new Parameters;
62 
63  params_all->Register_Parameters("Test_RandomNumbers", params_test);
64 
65  ParameterManager_YAML params_manager;
66  params_manager.read_params(filename_input, params_all);
67 
68  int seed = params_test->get_int("seed");
69  const string str_vlevel = params_test->get_string("verbose_level");
70 
71  const bool do_check = params_test->is_set("expected_result");
72  const double expected_result = do_check ? params_test->get_double("expected_result") : 0.0;
73 
75 
76  //- print input parameters
77  vout.general(vl, " seed = %d\n", seed);
78  vout.general(vl, " vlevel = %s\n", str_vlevel.c_str());
79  vout.general(vl, "\n");
80 
81 
82  // #### object setup #####
83  Timer *timer = new Timer(test_name);
84 
85 
86  // #### Execution main part ####
87  timer->start();
88 
89  vout.general(vl, "\n");
90  vout.general(vl, "Serial and Node-parallel test of Random Number Generator:\n");
91 
92  // sample field size
93  int nin = 8;
94  int nex = 4;
95 
96  int nvol = CommonParameters::Nvol();
97 
98  int lvol = CommonParameters::Lvol();
99 
100 
101  // buffer for checks
102  const size_t nsample = 1024;
103  double data[nsample];
104  for (size_t i = 0; i < nsample; ++i) {
105  data[i] = 0.0;
106  }
107 
108 
109  // 1. generate field in parallel
110  Field field1(nin, nvol, nex);
111 
112  if (true) {
113  RandomNumbers *rand = new RandomNumbers_MT19937(seed);
115 
116  // fill field with uniform random numbers
117  rand->uniform_lex_global(field1);
118 
119  // generate additional random numbers to check rng state.
120  for (size_t i = 0; i < nsample; ++i) {
121  data[i] = rand->get();
122  }
123 
124  delete rand;
125  }
126 
127  // 2. generate field at rank 0 with the same seed
128  Field field2(0, 0, 0);
129 
130  if (Communicator::is_primary()) {
131  RandomNumbers *rand = new RandomNumbers_MT19937(seed);
132 
133  field2.reset(nin, lvol, nex);
134 
135  double *p = field2.ptr(0);
136 
137  for (size_t i = 0, n = field2.size(); i < n; ++i) {
138  *p++ = rand->get();
139  }
140 
141  delete rand;
142  }
143 
144  // 3. gather parallel field to rank 0
145  Field field1b(0, 0, 0);
146 
147  if (Communicator::is_primary()) {
148  field1b.reset(nin, lvol, nex);
149  }
150 
152 
153  fieldio.gather(&field1b, &field1);
154 
155  // 4. compare
156  int err1 = 0;
157 
158  if (Communicator::is_primary()) {
159  if (field1b.size() != field2.size()) {
160  vout.crucial(vl, "%s: field size mismatch.\n", test_name.c_str());
161  abort();
162  }
163 
164  double *p1 = field1b.ptr(0);
165  double *p2 = field2.ptr(0);
166 
167  for (size_t i = 0, n = field2.size(); i < n; ++i) {
168  if (*p1++ != *p2++) ++err1;
169  }
170  }
171 
172  Communicator::broadcast(1, &err1, 0);
173  vout.general(vl, "%s: serial and parallel: err = %d\n", test_name.c_str(), err1);
174 
175  // 5. check rng state
176  int err2 = 0;
177  double buf[nsample];
178 
179  for (int ipe = 1, npe = Communicator::size(); ipe < npe; ++ipe) {
180  Communicator::send_1to1(nsample, buf, data, 0, ipe, ipe);
181 
182  if (Communicator::is_primary()) {
183  for (size_t i = 0; i < nsample; ++i) {
184  if (data[i] != buf[i]) ++err2;
185  }
186  }
187 
188  Communicator::broadcast(1, &err2, 0);
189  vout.general(vl, "%s: check local state at rank %d, err = %d\n", test_name.c_str(), ipe, err2);
190  }
191 
192  // 6. check save and restore
193 
194  int err3 = 0;
195 
196  if (true) {
199 
200  // save current state to file
201  rand->writefile("RNG_MT19937.state");
202 
203  vout.detailed("%s: number of samples = %lu\n", test_name.c_str(), nsample);
204 
205  for (size_t i = 0; i < nsample; ++i) {
206  data[i] = rand->get();
207  }
208 
209  // restore state from file
210  rand->readfile("RNG_MT19937.state");
211 
212  // check if same series are generated.
213  int err3_part = 0;
214 
215  for (size_t i = 0; i < nsample; ++i) {
216  if (data[i] != rand->get()) ++err3_part;
217  }
218 
219  Communicator::reduce_sum(1, &err3, &err3_part);
220 
221  vout.general(vl, "%s: save/restore test: err = %d\n", test_name.c_str(), err3);
222 
223  delete rand;
224  }
225 
226  // 7. check gaussian field
227 
228  field1.reset(nin, nvol, nex);
229 
230  if (true) {
231  RandomNumbers *rand = new RandomNumbers_MT19937(seed);
233 
234  // fill field with gaussian random numbers
235  rand->gauss_lex_global(field1);
236 
237  delete rand;
238  }
239 
240  if (Communicator::is_primary()) {
241  RandomNumbers *rand = new RandomNumbers_MT19937(seed);
242 
243  field2.reset(nin, lvol, nex);
244 
245  double *p = field2.ptr(0);
246 
247  if (field2.nin() % 2 == 0) {
248  double r1, r2;
249 
250  for (int j = 0, Nex = field2.nex(); j < Nex; ++j) {
251  for (int isite = 0, Nvol = field2.nvol(); isite < Nvol; ++isite) {
252  for (int i = 0, Nin = field2.nin(); i < Nin; i += 2) {
253  rand->gauss(r1, r2);
254  *p++ = r1;
255  *p++ = r2;
256  }
257  }
258  }
259  } else {
260  double r1, r2;
261 
262  for (int j = 0, Nex = field2.nex(); j < Nex; ++j) {
263  for (int isite = 0, Nvol = field2.nvol(); isite < Nvol; ++isite) {
264  for (int i = 0, Nin = field2.nin(); i < Nin; ++i) {
265  rand->gauss(r1, r2);
266  *p++ = r1;
267  }
268  }
269  }
270  }
271 
272  delete rand;
273  }
274 
275  if (Communicator::is_primary()) {
276  field1b.reset(nin, lvol, nex);
277  }
278 
279  fieldio.gather(&field1b, &field1);
280 
281  int err4 = 0;
282 
283  if (Communicator::is_primary()) {
284  if (field1b.size() != field2.size()) {
285  vout.crucial(vl, "%s: field size mismatch.\n", test_name.c_str());
286  abort();
287  }
288 
289  double *p1 = field1b.ptr(0);
290  double *p2 = field2.ptr(0);
291 
292  for (size_t i = 0, n = field2.size(); i < n; ++i) {
293  if (*p1++ != *p2++) ++err4;
294  }
295  }
296 
297  Communicator::broadcast(1, &err4, 0);
298  vout.general(vl, "%s: serial and parallel for gaussian: err = %d\n", test_name.c_str(), err4);
299 
300 
301  // 8. summary
302 
303  double result = err1 + err2 + err3 + err4;
304 
305  timer->report();
306 
307 
308  // #### tidy up ####
309  delete params_test;
310  delete params_all;
311 
312  delete timer;
313 
314 
315  if (do_check) {
316  return Test::verify(expected_result, result);
317  } else {
318  vout.detailed(vl, "check skipped: expected_result not set.\n\n");
319  return EXIT_SKIP;
320  }
321  }
322 } // namespace Test_RandomNumbers
#define EXIT_SKIP
Definition: test.h:17
BridgeIO vout
Definition: bridgeIO.cpp:207
void writefile(const std::string &)
void read_params(const std::string &params_file, Parameters *params)
read parameters from file.
void detailed(const char *format,...)
Definition: bridgeIO.cpp:50
virtual double get()=0
void set_parameter_verboselevel(const Bridge::VerboseLevel vl)
Definition: randomNumbers.h:55
virtual void uniform_lex_global(Field &)
uniform random number defined on global lattice.
void general(const char *format,...)
Definition: bridgeIO.cpp:38
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
FieldIO_Text class for file I/O of Field data in plain text format.
Definition: fieldIO_Text.h:33
const Format * ILDG
Definition: io_format.cpp:28
void readfile(const std::string &)
int get_int(const string &key) const
Definition: parameters.cpp:40
Class for parameters.
Definition: parameters.h:40
static int Lvol()
virtual void gauss_lex_global(Field &)
gaussian random number defined on global lattice.
static int send_1to1(int count, double *recv_buf, double *send_buf, int p_to, int p_from, int tag)
send array of double from rank p_from to rank p_to. communication distinguished by tag...
int nin() const
Definition: field.h:100
static bool RegisterTest(const std::string &key, const Test_function func)
Definition: testManager.h:79
bool is_set(const string &) const
Definition: parameters.cpp:366
double get_double(const string &key) const
Definition: parameters.cpp:25
void reset(const int Nin, const int Nvol, const int Nex, const element_type cmpl=COMPLEX)
Definition: field.h:82
int nex() const
Definition: field.h:102
void start()
Definition: timer.cpp:44
void crucial(const char *format,...)
Definition: bridgeIO.cpp:26
void Register_Parameters(const string &, Parameters *const)
Definition: parameters.cpp:359
static int size()
size of small world.
Base class of random number generators.
Definition: randomNumbers.h:40
Bridge::VerboseLevel vl
Definition: checker.cpp:18
VerboseLevel
Definition: bridgeIO.h:25
static int reduce_sum(int count, double *recv_buf, double *send_buf, int pattern=0)
make a global sum of an array of double over the communicator. pattern specifies the dimensions to be...
static int broadcast(int count, double *data, int sender)
broadcast array of double from sender.
Parameter manager with YAML parser.
Definition: timer.h:31
static bool is_primary()
check if the present node is primary in small communicator.
int verify(const double expected, const double result)
Definition: test.cpp:27
string get_string(const string &key) const
Definition: parameters.cpp:85
void gather(Field *vglobal, Field *vlocal)
gather data on parallel nodes to primary node.
Definition: fieldIO.cpp:115
void report(const Bridge::VerboseLevel vl=Bridge::GENERAL)
Definition: timer.cpp:128
static VerboseLevel set_verbose_level(const std::string &str)
Definition: bridgeIO.cpp:191
int size() const
Definition: field.h:106
void gauss(double &rn1, double &rn2)