Bridge++  Version 1.5.4
 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 
17 #include "Field/field_G.h"
18 #include "IO/fieldIO_Text.h" // for gather field
19 #include "IO/io_format_gauge.h"
20 
21 //====================================================================
23 
32 namespace Test_RandomNumbers_MT19937 {
33  const std::string test_name = "RandomNumbers.MT19937.Global";
34 
35  //- test-private parameters
36  namespace {
37  const std::string filename_input = "test_RandomNumbers_MT19937_Global.yaml";
38  }
39 
40  //- prototype declaration
41  int test_global(void);
42 
43 #ifdef USE_TESTMANAGER_AUTOREGISTER
44  namespace {
45  static const bool is_registered = TestManager::RegisterTest(
46  test_name,
48  );
49  }
50 #endif
51 
52  //====================================================================
53  int test_global(void)
54  {
55  // #### parameter setup ####
56 
57  const Parameters params_all = ParameterManager::read(filename_input);
58 
59  const Parameters params_test = params_all.lookup("Test_RandomNumbers");
60 
61  const int iseed = params_test.get_int("int_seed");
62  const string str_vlevel = params_test.get_string("verbose_level");
63 
64  const bool do_check = params_test.is_set("expected_result");
65  const double expected_result = do_check ? params_test.get_double("expected_result") : 0.0;
66 
67  const Bridge::VerboseLevel vl = vout.set_verbose_level(str_vlevel);
68 
69  //- print input parameters
70  vout.general(vl, " iseed = %d\n", iseed);
71  vout.general(vl, " vlevel = %s\n", str_vlevel.c_str());
72  vout.general(vl, "\n");
73 
74 
75  // #### object setup #####
76  const unique_ptr<Timer> timer(new Timer(test_name));
77 
78 
79  // #### Execution main part ####
80  timer->start();
81 
82  vout.general(vl, "\n");
83  vout.general(vl, "Serial and Node-parallel test of Random Number Generator:\n");
84 
85  // sample field size
86  const int nin = 8;
87  const int nex = 4;
88 
89  const int nvol = CommonParameters::Nvol();
90  const long_t lvol = CommonParameters::Lvol();
91 
92 
93  // buffer for checks
94  const size_t nsample = 1024;
95  double data[nsample];
96  for (size_t i = 0; i < nsample; ++i) {
97  data[i] = 0.0;
98  }
99 
100 
101  // 1. generate field in parallel
102  Field field1(nin, nvol, nex);
103 
104  if (true) {
107 
108  // fill field with uniform random numbers
109  rand->uniform_lex_global(field1);
110 
111  // generate additional random numbers to check rng state.
112  for (size_t i = 0; i < nsample; ++i) {
113  data[i] = rand->get();
114  }
115  }
116 
117  // 2. generate field at rank 0 with the same seed
118  Field field2(0, 0, 0);
119 
120  if (Communicator::is_primary()) {
122 
123  field2.reset(nin, lvol, nex);
124 
125  double *p = field2.ptr(0);
126 
127  for (size_t i = 0, n = field2.size(); i < n; ++i) {
128  *p++ = rand->get();
129  }
130  }
131 
132  // 3. gather parallel field to rank 0
133  Field field1b(0, 0, 0);
134 
135  if (Communicator::is_primary()) {
136  field1b.reset(nin, lvol, nex);
137  }
138 
140 
141  fieldio.gather(&field1b, &field1);
142 
143  // 4. compare
144  int err1 = 0;
145 
146  if (Communicator::is_primary()) {
147  if (field1b.size() != field2.size()) {
148  vout.crucial(vl, "Error at %s: field size mismatch.\n", test_name.c_str());
149  exit(EXIT_FAILURE);
150  }
151 
152  double *p1 = field1b.ptr(0);
153  double *p2 = field2.ptr(0);
154 
155  for (size_t i = 0, n = field2.size(); i < n; ++i) {
156  if (*p1++ != *p2++) ++err1;
157  }
158  }
159 
160  Communicator::broadcast(1, &err1, 0);
161  vout.general(vl, "%s: serial and parallel: err = %d\n", test_name.c_str(), err1);
162 
163  // 5. check rng state
164  int err2 = 0;
165  double buf[nsample];
166 
167  for (int ipe = 1, npe = Communicator::size(); ipe < npe; ++ipe) {
168  Communicator::send_1to1(nsample, buf, data, 0, ipe, ipe);
169 
170  if (Communicator::is_primary()) {
171  for (size_t i = 0; i < nsample; ++i) {
172  if (data[i] != buf[i]) ++err2;
173  }
174  }
175 
176  Communicator::broadcast(1, &err2, 0);
177  vout.general(vl, "%s: check local state at rank %d, err = %d\n", test_name.c_str(), ipe, err2);
178  }
179 
180  // 6. check save and restore
181  int err3 = 0;
182 
183  if (true) {
186 
187  // save current state to file
188  rand->write_file("RNG_MT19937.state");
189 
190  vout.detailed("%s: number of samples = %lu\n", test_name.c_str(), nsample);
191 
192  for (size_t i = 0; i < nsample; ++i) {
193  data[i] = rand->get();
194  }
195 
196  // restore state from file
197  rand->read_file("RNG_MT19937.state");
198 
199  // check if same series are generated.
200  int err3_part = 0;
201 
202  for (size_t i = 0; i < nsample; ++i) {
203  if (data[i] != rand->get()) ++err3_part;
204  }
205 
206  Communicator::reduce_sum(1, &err3, &err3_part);
207 
208  vout.general(vl, "%s: save/restore test: err = %d\n", test_name.c_str(), err3);
209  }
210 
211  // 7. check gaussian field
212  field1.reset(nin, nvol, nex);
213 
214  if (true) {
217 
218  // fill field with gaussian random numbers
219  rand->gauss_lex_global(field1);
220  }
221 
222  if (Communicator::is_primary()) {
224 
225  field2.reset(nin, lvol, nex);
226 
227  double *p = field2.ptr(0);
228 
229  if (field2.nin() % 2 == 0) {
230  double r1, r2;
231 
232  for (int j = 0, Nex = field2.nex(); j < Nex; ++j) {
233  for (int isite = 0, Nvol = field2.nvol(); isite < Nvol; ++isite) {
234  for (int i = 0, Nin = field2.nin(); i < Nin; i += 2) {
235  rand->gauss(r1, r2);
236  *p++ = r1;
237  *p++ = r2;
238  }
239  }
240  }
241  } else {
242  double r1, r2;
243 
244  for (int j = 0, Nex = field2.nex(); j < Nex; ++j) {
245  for (int isite = 0, Nvol = field2.nvol(); isite < Nvol; ++isite) {
246  for (int i = 0, Nin = field2.nin(); i < Nin; ++i) {
247  rand->gauss(r1, r2);
248  *p++ = r1;
249  }
250  }
251  }
252  }
253  }
254 
255  if (Communicator::is_primary()) {
256  field1b.reset(nin, lvol, nex);
257  }
258 
259  fieldio.gather(&field1b, &field1);
260 
261  int err4 = 0;
262 
263  if (Communicator::is_primary()) {
264  if (field1b.size() != field2.size()) {
265  vout.crucial(vl, "Error at %s: field size mismatch.\n", test_name.c_str());
266  exit(EXIT_FAILURE);
267  }
268 
269  double *p1 = field1b.ptr(0);
270  double *p2 = field2.ptr(0);
271 
272  for (size_t i = 0, n = field2.size(); i < n; ++i) {
273  if (*p1++ != *p2++) ++err4;
274  }
275  }
276 
277  Communicator::broadcast(1, &err4, 0);
278  vout.general(vl, "%s: serial and parallel for gaussian: err = %d\n", test_name.c_str(), err4);
279 
280 
281  // 8. summary
282  const double result = err1 + err2 + err3 + err4;
283 
284  timer->report();
285 
286 
287  if (do_check) {
288  return Test::verify(result, expected_result);
289  } else {
290  vout.detailed(vl, "check skipped: expected_result not set.\n\n");
291  return EXIT_SKIP;
292  }
293  }
294 } // namespace Test_RandomNumbers
#define EXIT_SKIP
Definition: test.h:17
BridgeIO vout
Definition: bridgeIO.cpp:503
void detailed(const char *format,...)
Definition: bridgeIO.cpp:216
virtual double get()=0
const double * ptr(const int jin, const int site, const int jex) const
Definition: field.h:153
void set_parameter_verboselevel(const Bridge::VerboseLevel vl)
Definition: randomNumbers.h:64
virtual void uniform_lex_global(Field &)
uniform random number defined on global lattice.
void general(const char *format,...)
Definition: bridgeIO.cpp:197
Container of Field-type object.
Definition: field.h:45
int nvol() const
Definition: field.h:127
FieldIO_Text class for file I/O of Field data in plain text format.
Definition: fieldIO_Text.h:37
const Format * ILDG
Definition: io_format.cpp:28
int get_int(const string &key) const
Definition: parameters.cpp:192
Class for parameters.
Definition: parameters.h:46
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:126
void write_file(const std::string &)
Parameters lookup(const string &key) const
Definition: parameters.h:79
static bool RegisterTest(const std::string &key, const Test_function func)
Definition: testManager.h:69
double get_double(const string &key) const
Definition: parameters.cpp:175
int nex() const
Definition: field.h:128
void reset(const int Nin, const int Nvol, const int Nex, const element_type cmpl=Element_type::COMPLEX)
Definition: field.h:95
bool is_set(const string &key) const
Definition: parameters.cpp:528
long long_t
definition of long for Bridge++
Definition: bridge_long.h:46
void start()
Definition: timer.cpp:44
void read_file(const std::string &)
save and load random number status.
void crucial(const char *format,...)
Definition: bridgeIO.cpp:178
static void read(const std::string &params_file, Parameters &params)
int verify(const double result, const double expected, double eps)
Definition: test.cpp:27
static int size()
size of small world.
Bridge::VerboseLevel vl
VerboseLevel
Definition: bridgeIO.h:42
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.
Definition: timer.h:31
static bool is_primary()
check if the present node is primary in small communicator.
string get_string(const string &key) const
Definition: parameters.cpp:221
void gather(Field *vglobal, Field *vlocal)
gather data on parallel nodes to primary node.
Definition: fieldIO.cpp:119
void report(const Bridge::VerboseLevel vl=Bridge::GENERAL)
Definition: timer.cpp:128
void gauss(double &rand1, double &rand2)
static long_t Lvol()
static VerboseLevel set_verbose_level(const std::string &str)
Definition: bridgeIO.cpp:131
int size() const
Definition: field.h:132