Bridge++  Version 1.4.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fieldIO_Binary_Parallel.cpp
Go to the documentation of this file.
1 
14 // this code only makes sense in MPI environment.
15 #ifdef USE_MPI
16 
18 
19 const std::string FieldIO_Binary_Parallel::class_name = "FieldIO_Binary_Parallel";
20 
21 //====================================================================
23  : FieldIO(format),
24  m_is_initialized(false),
25  m_nvol(0), m_nin_file(0), m_nex_file(0)
26 {}
27 
28 //====================================================================
29 FieldIO_Binary_Parallel::~FieldIO_Binary_Parallel()
30 {
31  finalize();
32 }
33 
34 //====================================================================
35 void FieldIO_Binary_Parallel::read_file(Field *u, string filename)
36 {
37  static const char _function_name[] = "FieldIO_Binary_Parallel::read_file";
38 
39  if (!u) {
40  vout.crucial(m_vl, "Warning at %s: field is null.\n", _function_name);
41  return;
42  }
43 
44  initialize(u);
45 
46  MPI_File fh;
47  int ret;
48 
49  // fetch data from file into buffer: buffer is in file order.
50  double *buf = new double [m_nin_file * m_nvol * m_nex_file];
51  if (!buf) {
52  vout.crucial(m_vl, "Error at %s: allocate buffer failed.\n", _function_name);
53  exit(EXIT_FAILURE);
54  }
55 
56 #ifdef USE_BGNET
57  ret = MPI_File_open(MPI_COMM_WORLD, const_cast<char *>(filename.c_str()), MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
58 #else
59  ret = MPI_File_open(Communicator_impl::world(), const_cast<char *>(filename.c_str()), MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
60 #endif
61  if (ret) {
62  vout.crucial(m_vl, "Error at %s: MPI_File_open failed.\n", _function_name);
63  exit(EXIT_FAILURE);
64  }
65 
66  ret = MPI_File_set_view(fh, 0, m_type_vector, m_type_tiled, const_cast<char *>("native"), MPI_INFO_NULL);
67  if (ret) {
68  vout.crucial(m_vl, "Error at %s: MPI_File_set_view failed.\n", _function_name);
69  exit(EXIT_FAILURE);
70  }
71 
72  ret = MPI_File_read_all(fh, (void *)buf, m_nvol * m_nex_file, m_type_vector, MPI_STATUS_IGNORE);
73  if (ret) {
74  vout.crucial(m_vl, "Error at %s: MPI_File_read_all failed.\n", _function_name);
75  exit(EXIT_FAILURE);
76  }
77 
78  ret = MPI_File_close(&fh);
79  if (ret) {
80  vout.crucial(m_vl, "Error at %s: MPI_File_close failed.\n", _function_name);
81  exit(EXIT_FAILURE);
82  }
83 
84  if (!is_bigendian()) {
85  convert_endian(buf, sizeof(double), m_nvol * m_nin_file * m_nex_file);
86  }
87 
88  // unpack buffer
89  double *p = buf;
90 
91  for (int j = 0; j < m_nex_file; ++j) {
92  for (int isite = 0; isite < m_nvol; ++isite) {
93  for (int i = 0; i < m_nin_file; ++i) {
94  int s, t;
95  m_format->file_to_field(s, t, i, j);
96 
97  u->set(s, isite, t, *p++);
98  }
99  }
100  }
101 
102  delete [] buf;
103 
104  finalize();
105 }
106 
107 
108 //====================================================================
109 void FieldIO_Binary_Parallel::write_file(Field *u, string filename)
110 {
111  static const char _function_name[] = "FieldIO_Binary_Parallel::write_file";
112 
113  if (!u) {
114  vout.crucial(m_vl, "Warning at %s: field is null.\n", _function_name);
115  }
116 
117  initialize(u);
118 
119  double *buf = new double [m_nin_file * m_nvol * m_nex_file];
120  if (!buf) {
121  vout.crucial(m_vl, "Error at %s: allocate buffer failed.\n", _function_name);
122  exit(EXIT_FAILURE);
123  }
124 
125  // pack buffer
126  double *p = buf;
127 
128  for (int j = 0; j < m_nex_file; ++j) {
129  for (int isite = 0; isite < m_nvol; ++isite) {
130  for (int i = 0; i < m_nin_file; ++i) {
131  int s, t;
132  m_format->file_to_field(s, t, i, j);
133 
134  *p++ = u->cmp(s, isite, t);
135  }
136  }
137  }
138 
139  if (!is_bigendian()) {
140  convert_endian(buf, sizeof(double), m_nin_file * m_nvol * m_nex_file);
141  }
142 
143  MPI_File fh;
144  int ret;
145 
146 #ifdef USE_BGNET
147  ret = MPI_File_open(MPI_COMM_WORLD, const_cast<char *>(filename.c_str()), MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
148 #else
149  ret = MPI_File_open(Communicator_impl::world(), const_cast<char *>(filename.c_str()), MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
150 #endif
151  if (ret) {
152  vout.crucial(m_vl, "Error at %s: MPI_File_open failed.\n", _function_name);
153  exit(EXIT_FAILURE);
154  }
155 
156  ret = MPI_File_set_view(fh, 0, m_type_vector, m_type_tiled, const_cast<char *>("native"), MPI_INFO_NULL);
157  if (ret) {
158  vout.crucial(m_vl, "Error at %s: MPI_File_set_view failed.\n", _function_name);
159  exit(EXIT_FAILURE);
160  }
161 
162  ret = MPI_File_write_all(fh, (void *)buf, m_nvol * m_nex_file, m_type_vector, MPI_STATUS_IGNORE);
163  if (ret) {
164  vout.crucial(m_vl, "Error at %s: MPI_File_write_all failed.\n", _function_name);
165  exit(EXIT_FAILURE);
166  }
167 
168  ret = MPI_File_close(&fh);
169  if (ret) {
170  vout.crucial(m_vl, "Error at %s: MPI_File_close failed.\n", _function_name);
171  exit(EXIT_FAILURE);
172  }
173 
174  delete [] buf;
175 
176  finalize();
177 }
178 
179 
180 //====================================================================
181 int FieldIO_Binary_Parallel::initialize(const Field* v)
182 {
183  static const char _function_name[] = "FieldIO_Binary_Parallel::initialize";
184 
185  // N.B. trivial layout returns 0 for nin/nex_file.
186  int nin_file = m_format->nin() ? m_format->nin() : v->nin();
187  int nex_file = m_format->nex() ? m_format->nex() : v->nex();
188  int nvol = v->nvol();
189 
190  // check if layout is already generated and recyclable.
191  if (m_is_initialized
192  && nin_file == m_nin_file
193  && nex_file == m_nex_file
194  && nvol == m_nvol)
195  {
196  vout.detailed(m_vl, "%s: layout recycled.\n", _function_name);
197  return EXIT_SUCCESS;
198  }
199 
200  // first, cleanup pre-existing layout, if any.
201  clear_layout();
202 
203  // local parameters
204  m_nin_file = nin_file;
205  m_nex_file = nex_file;
206 
207  int ndim = CommonParameters::Ndim();
208 
209  int *global_dims = new int[ndim];
210  global_dims[0] = CommonParameters::Lx();
211  global_dims[1] = CommonParameters::Ly();
212  global_dims[2] = CommonParameters::Lz();
213  global_dims[3] = CommonParameters::Lt();
214 
215  int *local_dims = new int[ndim];
216  local_dims[0] = CommonParameters::Nx();
217  local_dims[1] = CommonParameters::Ny();
218  local_dims[2] = CommonParameters::Nz();
219  local_dims[3] = CommonParameters::Nt();
220 
221  m_nvol = 1;
222  for (int i = 0; i < ndim; ++i) {
223  m_nvol *= local_dims[i];
224  }
225 
226  int *grid_pos = new int[ndim];
227  for (int i = 0; i < ndim; ++i) {
228  grid_pos[i] = Communicator::ipe(i);
229  }
230 
231  int *starts = new int[ndim];
232  for (int i = 0; i < ndim; ++i) {
233  starts[i] = local_dims[i] * grid_pos[i];
234  }
235 
236  int ret = 0;
237 
238  // MPI_Datatype m_type_vector;
239  ret = MPI_Type_contiguous(sizeof(double) * m_nin_file, MPI_BYTE, &m_type_vector);
240  if (ret) {
241  vout.crucial(m_vl, "%s: MPI_Type_Contiguous failed.\n", _function_name);
242  exit(EXIT_FAILURE);
243  }
244 
245  ret = MPI_Type_commit(&m_type_vector);
246  if (ret) {
247  vout.crucial(m_vl, "%s: MPI_Type_commit failed.\n", _function_name);
248  exit(EXIT_FAILURE);
249  }
250 
251  // MPI_Datatype m_type_tiled;
252  ret = MPI_Type_create_subarray(ndim, global_dims, local_dims, starts, MPI_ORDER_FORTRAN, m_type_vector, &m_type_tiled);
253  if (ret) {
254  vout.crucial(m_vl, "%s: MPI_Type_create_subarray failed.\n", _function_name);
255  exit(EXIT_FAILURE);
256  }
257 
258  ret = MPI_Type_commit(&m_type_tiled);
259  if (ret) {
260  vout.crucial(m_vl, "%s: MPI_Type_commit failed.\n", _function_name);
261  exit(EXIT_FAILURE);
262  }
263 
264  delete [] starts;
265  delete [] grid_pos;
266  delete [] local_dims;
267  delete [] global_dims;
268 
269  // initialization done.
270  m_is_initialized = true;
271 
272  vout.detailed(m_vl, "%s: layout initialized.\n", _function_name);
273 
274  return EXIT_SUCCESS;
275 }
276 
277 //====================================================================
278 int FieldIO_Binary_Parallel::clear_layout()
279 {
280  const char _function_name[] = "FieldIO_Binary_Parallel::clear_layout";
281 
282  if (m_is_initialized) {
283  m_nin_file = 0;
284  m_nex_file = 0;
285  m_nvol = 0;
286 
287  int ret = 0;
288 
289  ret = MPI_Type_free(&m_type_vector);
290  if (ret) {
291  vout.crucial(m_vl, "%s: MPI_Type_free for type_vector failed.\n", _function_name);
292  exit(EXIT_FAILURE);
293  }
294 
295  ret = MPI_Type_free(&m_type_tiled);
296  if (ret) {
297  vout.crucial(m_vl, "%s: MPI_Type_free for type_tiled failed.\n", _function_name);
298  exit(EXIT_FAILURE);
299  }
300 
301  m_is_initialized = false;
302  }
303 
304  return EXIT_SUCCESS;
305 }
306 
307 
308 //====================================================================
309 int FieldIO_Binary_Parallel::finalize()
310 {
311  static const char _function_name[] = "FieldIO_Binary_Parallel::finalize";
312 
313  clear_layout();
314 
315  vout.detailed(m_vl, "%s via MPI I/O finalize done.\n", class_name.c_str());
316 
317  return EXIT_SUCCESS;
318 }
319 
320 
321 //====================================================================
322 #endif
323 
324 //====================================================================
325 //============================================================END=====
BridgeIO vout
Definition: bridgeIO.cpp:495
void detailed(const char *format,...)
Definition: bridgeIO.cpp:212
void set(const int jin, const int site, const int jex, double v)
Definition: field.h:164
virtual void file_to_field(int &s, int &t, const int i, const int j) const =0
virtual int nex() const =0
Container of Field-type object.
Definition: field.h:39
virtual int nin() const =0
int nvol() const
Definition: field.h:116
double cmp(const int jin, const int site, const int jex) const
Definition: field.h:132
static int ipe(const int dir)
logical coordinate of current proc.
static bool is_bigendian()
Definition: fieldIO.cpp:203
FieldIO_Binary_Parallel(const IO_Format::Format *format)
void write_file(Field *v, string filename)
int nin() const
Definition: field.h:115
int nex() const
Definition: field.h:117
const IO_Format::Format * m_format
Definition: fieldIO.h:62
void crucial(const char *format,...)
Definition: bridgeIO.cpp:178
void read_file(Field *v, string filename)
static const std::string class_name
static void convert_endian(void *buf, size_t size, size_t nmemb)
check if machine byte order is big-endian.
Definition: fieldIO.cpp:225
FieldIO class for file I/O of space-time distributed data.
Definition: fieldIO.h:53
Bridge::VerboseLevel m_vl
Definition: fieldIO.h:64