HILA
Loading...
Searching...
No Matches
field_io.h
1#ifndef HILA_FIELD_IO_H_
2#define HILA_FIELD_IO_H_
3
4//////////////////////////////////////////////////////////////////////
5// This file collects Field<> I/O routines
6
7#include "plumbing/field.h"
8
9namespace hila {
10// Define this as template, in order to avoid code generation if the function is not needed -
11// a bit crazy
12template <typename IS, std::enable_if_t<std::is_same<IS, std::ifstream>::value, int> = 0>
13bool open_input_file(const std::string &filename, IS &inputfile) {
14 bool ok = true;
15 if (hila::myrank() == 0) {
16 inputfile.open(filename, std::ios::in | std::ios::binary);
17 if (inputfile.fail()) {
18 hila::out0 << "ERROR in opening file " << filename << '\n';
19 ok = false;
20 }
21 }
23 if (!ok)
25
26 return ok;
27}
28
29template <typename OS, std::enable_if_t<std::is_same<OS, std::ofstream>::value, int> = 0>
30bool open_output_file(const std::string &filename, OS &outputfile, bool binary = true,
31 int precision = 8) {
32 bool ok = true;
33 if (hila::myrank() == 0) {
34 std::ios::openmode mode = std::ios::out | std::ios::trunc;
35 if (binary)
36 mode |= std::ios::binary;
37
38 outputfile.open(filename, mode);
39 outputfile.precision(precision);
40 if (outputfile.fail()) {
41 hila::out0 << "ERROR in opening file " << filename << '\n';
42 ok = false;
43 }
44 }
46 if (!ok)
48
49 return ok;
50}
51
52
53template <typename S, std::enable_if_t<std::is_same<S, std::ofstream>::value ||
54 std::is_same<S, std::ifstream>::value,
55 int> = 0>
56bool close_file(const std::string &filename, S &fstream) {
57 bool error = false;
58 if (hila::myrank() == 0) {
59 fstream.close();
60 if (fstream.fail()) {
61 hila::out0 << "ERROR in reading/writing file " << filename << '\n';
62 error = true;
63 }
64 }
65 hila::broadcast(error);
66
67 if (error)
69
70 return !error;
71}
72
73} // namespace hila
74
75//////////////////////////////////////////////////////////////////////////////////
76
77/// Write the field to a file stream
78template <typename T>
79void Field<T>::write(std::ofstream &outputfile, bool binary, int precision) const {
80 constexpr size_t sites_per_write = WRITE_BUFFER_SIZE / sizeof(T);
81 constexpr size_t write_size = sites_per_write * sizeof(T);
82
83 if (!binary)
84 outputfile.precision(precision);
85
86 std::vector<CoordinateVector> coord_list(sites_per_write);
87 T *buffer = (T *)memalloc(write_size);
88 auto mylat = fs->mylattice;
89 CoordinateVector size = mylat.size();
90
91 for (size_t i = 0; i < mylat.volume(); i += sites_per_write) {
92 size_t sites = std::min(sites_per_write, mylat.volume() - i);
93 for (size_t j = 0; j < sites; j++)
94 coord_list[j] = mylat->global_coordinates(i + j);
95
96 if (sites < sites_per_write)
97 coord_list.resize(sites);
98
99 fs->gather_elements(buffer, coord_list);
100 if (hila::myrank() == 0) {
101 if (binary) {
102 outputfile.write((char *)buffer, sites * sizeof(T));
103 } else {
104 for (size_t j = 0; j < sites; j++) {
105 outputfile << buffer[j] << '\n';
106 }
107 }
108 }
109 }
110
111 std::free(buffer);
112}
113
114/// Write the Field to a named file replacing the file
115template <typename T>
116void Field<T>::write(const std::string &filename, bool binary, int precision) const {
117 std::ofstream outputfile;
118 hila::open_output_file(filename, outputfile, binary);
119 write(outputfile, binary, precision);
120 hila::close_file(filename, outputfile);
121}
122
123/// Write a list of fields into an output stream
124template <typename T>
125static void write_fields(std::ofstream &outputfile, Field<T> &last) {
126 last.write(outputfile);
127}
128
129template <typename T, typename... fieldtypes>
130static void write_fields(std::ofstream &outputfile, Field<T> &next, fieldtypes &...fields) {
131 next.write(outputfile);
132 write_fields(outputfile, fields...);
133}
134
135/// Write a list of fields to a file
136template <typename... fieldtypes>
137static void write_fields(const std::string &filename, fieldtypes &...fields) {
138 std::ofstream outputfile;
139 hila::open_output_file(filename, outputfile);
140 write_fields(outputfile, fields...);
141 hila::close_file(filename, outputfile);
142}
143
144/////////////////////////////////////////////////////////////////////////////////
145
146/// Read the Field from a stream
147template <typename T>
148void Field<T>::read(std::ifstream &inputfile) {
149 constexpr size_t sites_per_read = WRITE_BUFFER_SIZE / sizeof(T);
150 constexpr size_t read_size = sites_per_read * sizeof(T);
151
152 if (!this->is_allocated())
153 this->allocate();
154
155 mark_changed(ALL);
156
157 std::vector<CoordinateVector> coord_list(sites_per_read);
158 T *buffer = (T *)memalloc(read_size);
159 auto mylat = fs->mylattice;
160 CoordinateVector size = mylat.size();
161
162 for (size_t i = 0; i < mylat.volume(); i += sites_per_read) {
163 size_t sites = std::min(sites_per_read, mylat.volume() - i);
164 for (size_t j = 0; j < sites; j++)
165 coord_list[j] = mylat->global_coordinates(i + j);
166
167 if (sites < sites_per_read)
168 coord_list.resize(sites);
169
170 if (hila::myrank() == 0)
171 inputfile.read((char *)buffer, sites * sizeof(T));
172
173 fs->scatter_elements(buffer, coord_list);
174 }
175
176 std::free(buffer);
177}
178
179/// Read the Field from a stream
180template <typename T>
181void Field<T>::read(std::ifstream &inputfile, const CoordinateVector& insize) {
182 constexpr size_t sites_per_read = WRITE_BUFFER_SIZE / sizeof(T);
183 constexpr size_t read_size = sites_per_read * sizeof(T);
184
185 if (!this->is_allocated())
186 this->allocate();
187
188 mark_changed(ALL);
189
190 std::vector<CoordinateVector> coord_list(sites_per_read);
191 T *buffer = (T *)memalloc(read_size);
192
193 CoordinateVector lsize = lattice.size();
194 int scalef[NDIM];
195 size_t tvol = 1;
196 size_t scvol = 1;
197 foralldir(d) {
198 scalef[d] = lsize[d] / insize[d];
199 tvol *= insize[d];
200 scvol *= scalef[d];
201 }
202
203 for (size_t i = 0; i < tvol; i += sites_per_read) {
204 size_t sites = std::min(sites_per_read, tvol - i);
205 if (hila::myrank() == 0) {
206 inputfile.read((char *)buffer, sites * sizeof(T));
207 }
208
209 for (size_t j = 0; j < sites; j++) {
210 size_t ind = i + j;
211 foralldir(dir) {
212 coord_list[j][dir] = ind % insize[dir];
213 ind /= insize[dir];
214 }
215 }
216
217 if (sites < sites_per_read) {
218 coord_list.resize(sites);
219 }
220
221 fs->scatter_elements(buffer, coord_list);
222
223 // if input lattice fits multiple times on the current lattice size,
224 // replicate input lattice to fill current lattice:
225 for (size_t sci = 1; sci < scvol; ++sci) {
226 std::vector<CoordinateVector> tcoord_list(coord_list.size());
227 size_t ind = sci;
228 foralldir(dir) {
229 int tsf = ind % scalef[dir];
230 ind /= scalef[dir];
231 for (size_t j = 0; j < sites; j++) {
232 tcoord_list[j][dir] = (coord_list[j][dir] + tsf * insize[dir]) % lsize[dir];
233 }
234 }
235 fs->scatter_elements(buffer, tcoord_list);
236 }
237 }
238
239 std::free(buffer);
240}
241
242// Read Field contents from the beginning of a file
243template <typename T>
244void Field<T>::read(const std::string &filename) {
245 std::ifstream inputfile;
246 hila::open_input_file(filename, inputfile);
247 read(inputfile);
248 hila::close_file(filename, inputfile);
249}
250
251// Read a list of fields from an input stream
252template <typename T>
253static void read_fields(std::ifstream &inputfile, Field<T> &last) {
254 last.read_from_stream(inputfile);
255}
256
257template <typename T, typename... fieldtypes>
258static void read_fields(std::ifstream &inputfile, Field<T> &next, fieldtypes &...fields) {
259 next.read_from_stream(inputfile);
260 read_fields(inputfile, fields...);
261}
262
263// Read a list of fields from a file
264template <typename... fieldtypes>
265static void read_fields(const std::string &filename, fieldtypes &...fields) {
266 std::ifstream inputfile;
267 hila::open_input_file(filename, inputfile);
268 read_fields(inputfile, fields...);
269 hila::close_file(filename, inputfile);
270}
271
272
273///////////////////////////////////////////////////////////////////////////////
274
275/// Write a "subspace" of the original lattice
276/// Each element is written on a single line
277/// TODO: more formatting?
278
279template <typename T>
280void Field<T>::write_subvolume(std::ofstream &outputfile, const CoordinateVector &cmin,
281 const CoordinateVector &cmax, int precision) const {
282
283 constexpr size_t sites_per_write = WRITE_BUFFER_SIZE / sizeof(T);
284
285 size_t sites = 1;
286 int line_len = 1; // number of elements on 1st non-trivial dimension
287 foralldir(d) {
288 assert(cmin[d] >= 0 && cmax[d] >= cmin[d] && cmax[d] < fs->mylattice.size(d) &&
289 "subvolume size mismatch");
290 sites *= cmax[d] - cmin[d] + 1;
291
292 if (line_len == 1)
293 line_len = sites;
294 }
295
296 size_t n_write = std::min(sites_per_write, sites);
297
298 std::vector<CoordinateVector> coord_list(n_write);
299 T *buffer = (T *)memalloc(n_write * sizeof(T));
300
302
303 size_t i = 0, j = 0;
304
305 if (hila::myrank() == 0) {
306 outputfile.precision(precision);
307 }
308
309 forcoordinaterange(c, cmin, cmax) {
310 coord_list[i] = c;
311 i++;
312 j++;
313 if (i == n_write || j == sites) {
314 if (i < n_write)
315 coord_list.resize(i);
316
317 fs->gather_elements(buffer, coord_list);
318
319 if (hila::myrank() == 0) {
320 for (size_t k = 0; k < i; k++) {
321 for (int l = 0; l < sizeof(T) / sizeof(hila::arithmetic_type<T>); l++) {
322 outputfile << hila::get_number_in_var(buffer[k], l) << ' ';
323 }
324 outputfile << '\n';
325 }
326 }
327 i = 0;
328 }
329 }
330}
331
332
333template <typename T>
334void Field<T>::write_subvolume(const std::string &filename, const CoordinateVector &cmin,
335 const CoordinateVector &cmax, int precision) const {
336
337 std::ofstream out;
338 hila::open_output_file(filename, out, false);
339 write_subvolume(out, cmin, cmax, precision);
340 hila::close_file(filename, out);
341}
342
343// Write a subspace (slice) of the original lattice. Here
344// slice[d] = fixed coordinate value, or < 0: run the dimension through.
345// For example, slice = {5,2,-1,0}; prints the line along z-axis at (x,y,t) = (5,2,0)
346// Outf is either filename or ofstream
347
348template <typename T>
349template <typename outf_type>
350void Field<T>::write_slice(outf_type &outf, const CoordinateVector &slice, int precision) const {
351
352 static_assert(std::is_same<outf_type, std::string>::value ||
353 std::is_same<outf_type, std::ofstream>::value,
354 "file name / output stream argument in write_slice()?");
355
356 CoordinateVector cmin, cmax;
357 foralldir(d) {
358 if (slice[d] < 0) {
359 cmin[d] = 0;
360 cmax[d] = fs->mylattice.size(d) - 1;
361 } else {
362 cmin[d] = cmax[d] = slice[d];
363 }
364 }
365 write_subvolume(outf, cmin, cmax, precision);
366}
367
368
369#endif
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:62
void write_subvolume(std::ofstream &outputfile, const CoordinateVector &cmin, const CoordinateVector &cmax, int precision=6) const
Definition field_io.h:280
void write(std::ofstream &outputfile, bool binary=true, int precision=8) const
Write the field to a file stream.
Definition field_io.h:79
void read(std::ifstream &inputfile)
Read the Field from a stream.
Definition field_io.h:148
int size(Direction d) const
lattice.size() -> CoordinateVector or lattice.size(d) -> int returns the dimensions of the lattice,...
Definition lattice.h:433
static constexpr int size()
Returns size of Vector or square Matrix.
Definition matrix.h:248
#define foralldir(d)
Macro to loop over (all) Direction(s)
Definition coordinates.h:80
constexpr Parity ALL
bit pattern: 011
This files containts definitions for the Field class and the classes required to define it such as fi...
Implement hila::swap for gauge fields.
Definition array.h:982
int myrank()
rank of this node
Definition com_mpi.cpp:237
std::ostream out0
This writes output only from main process (node 0)
T broadcast(T &var, int rank=0)
Broadcast the value of var to all MPI ranks from rank (default=0).
Definition com_mpi.h:170
void terminate(int status)
hila::arithmetic_type< T > get_number_in_var(const T &var, int i)
Definition type_tools.h:118
#define WRITE_BUFFER_SIZE
Definition params.h:71