1
// Copyright (C) 2009 Niclas Jansson.
2
// Licensed under the GNU LGPL Version 2.1.
4
// First added: 2009-09-09
5
// Last changed: 2011-04-19
10
#include <dolfin/la/Vector.h>
11
#include <dolfin/mesh/Mesh.h>
12
#include <dolfin/mesh/MeshEditor.h>
13
#include <dolfin/mesh/Vertex.h>
14
#include <dolfin/function/Function.h>
15
#include <dolfin/io/Checkpoint.h>
22
using namespace dolfin;
23
//-----------------------------------------------------------------------------
24
Checkpoint::Checkpoint() : state(CHECKPOINT), restart_state(OPEN), n(0),
25
hdr_initialized(false), disp_initialized(false)
28
//-----------------------------------------------------------------------------
29
Checkpoint::~Checkpoint()
32
//-----------------------------------------------------------------------------
33
void Checkpoint::hdr_init(Mesh& mesh, bool static_mesh)
36
if(!hdr_initialized || !static_mesh)
38
hdr.num_coords = mesh.numVertices() * mesh.geometry().dim();
39
hdr.num_entities = mesh.type().numEntities(0);
40
hdr.num_centities = mesh.numCells() * hdr.num_entities;
41
hdr.type = mesh.type().cellType();
42
hdr.tdim = mesh.topology().dim();
43
hdr.gdim = mesh.geometry().dim();
44
hdr.num_vertices = mesh.numVertices();
45
hdr.num_cells = mesh.numCells();
46
hdr.num_ghosts = mesh.distdata().num_ghost(0);
47
hdr.num_shared = mesh.distdata().num_shared(0);
51
uint local_data[5] = {hdr.num_coords,
57
memset(&hdr.offsets[0], 0, 5 * sizeof(uint));
58
#if ( MPI_VERSION > 1 )
59
MPI_Exscan(&local_data[0], &hdr.offsets[0], 5,
60
MPI_UNSIGNED, MPI_SUM, MPI::DOLFIN_COMM);
62
MPI_Scan(&local_data[0], &hdr.offsets[0], 5,
63
MPI_UNSIGNED, MPI_SUM, MPI::DOLFIN_COMM);
65
hdr.offsets[0] -= local_data[0];
66
hdr.offsets[1] -= local_data[1];
67
hdr.offsets[2] -= local_data[2];
68
hdr.offsets[3] -= local_data[3];
69
hdr.offsets[4] -= local_data[4];
72
if (!disp_initialized || !static_mesh)
74
memset(&hdr.disp[0], 0, 5 * sizeof(uint));
75
MPI_Allreduce(&local_data[0], &hdr.disp[0], 5, MPI_UNSIGNED,
76
MPI_SUM, MPI::DOLFIN_COMM);
77
disp_initialized = true;
83
hdr_initialized = true;
86
//-----------------------------------------------------------------------------
87
void Checkpoint::write(std::string fname, uint id, real t, Mesh& mesh,
88
std::vector<Function *> func,
89
std::vector<Vector *> vec, bool static_mesh)
92
message("Writing checkpoint (%s%d) at time %g", fname.c_str(), n%2, t);
93
std::ostringstream _fname;
95
if( MPI::numProcesses() > 1)
96
_fname << fname << (n++)%2 << "_" << MPI::processNumber() << ".chkp";
98
_fname << fname << (n++)%2 << ".chkp";
100
std::ofstream out(_fname.str().c_str(), std::ofstream::binary);
102
out.write((char *) &id, sizeof(uint));
103
out.write((char *) &t, sizeof(real));
106
_fname << fname << (n++)%2 << ".chkp";
109
MPI_File_open(dolfin::MPI::DOLFIN_COMM, (char *) _fname.str().c_str(),
110
MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &out);
111
MPI_File_set_size(out, 0);
114
MPI_File_write_all(out, &id, 1, MPI_UNSIGNED, MPI_STATUS_IGNORE);
115
MPI_File_write_all(out, &t, 1, MPI_DOUBLE, MPI_STATUS_IGNORE);
117
byte_offset += sizeof(uint);
118
byte_offset += sizeof(real);
121
hdr_init(mesh, static_mesh);
127
MPI_File_close(&out);
136
//-----------------------------------------------------------------------------
137
void Checkpoint::restart(std::string fname)
140
if (restart_state != OPEN)
141
error("Shut her down, Scotty, she's sucking mud again!");
143
std::ostringstream _fname;
145
if( MPI::numProcesses() > 1)
146
_fname << fname << "_" << MPI::processNumber() << ".chkp";
148
_fname << fname << ".chkp";
150
_fname << fname << ".chkp";
154
MPI_File_open(dolfin::MPI::DOLFIN_COMM, (char *) _fname.str().c_str(),
155
MPI_MODE_RDONLY, MPI_INFO_NULL, &in);
156
MPI_File_read_all(in, &_id, 1, MPI_UNSIGNED, MPI_STATUS_IGNORE);
157
MPI_File_read_all(in, &_t, 1, MPI_DOUBLE, MPI_STATUS_IGNORE);
158
byte_offset = sizeof(uint) + sizeof(real);
160
in.open(_fname.str().c_str(), std::ifstream::binary);
161
in.read((char *) &_id, sizeof(uint));
162
in.read((char *) &_t, sizeof(real));
164
message("Restarting from time %g checkpoint id %d", _t, _id);
167
restart_state = MESH;
170
//-----------------------------------------------------------------------------
171
void Checkpoint::load(Mesh& mesh)
173
if (restart_state != MESH)
174
error("Shut her down, Scotty, she's sucking mud again!");
177
uint pe_size = MPI::numProcesses();
178
uint pe_rank = MPI::processNumber();
180
MPI_File_read_at_all(in, byte_offset + pe_rank * sizeof(chkp_mesh_hdr),
181
&hdr, sizeof(chkp_mesh_hdr), MPI_BYTE, MPI_STATUS_IGNORE);
182
byte_offset += pe_size * sizeof(chkp_mesh_hdr);
184
in.read((char *)&hdr, sizeof(chkp_mesh_hdr));
186
real *coords = new real[hdr.num_coords];
189
MPI_File_read_at_all(in, byte_offset + hdr.offsets[0] * sizeof(real),
190
coords, hdr.num_coords, MPI_DOUBLE, MPI_STATUS_IGNORE);
191
byte_offset += hdr.disp[0] * sizeof(real);
193
in.read((char *)coords, (hdr.num_coords) * sizeof(real));
198
editor.open(_mesh, hdr.type, hdr.tdim, hdr.gdim);
199
editor.initVertices(hdr.num_vertices);
202
for(uint i = 0 ; i < hdr.num_coords; i += hdr.gdim)
207
editor.addVertex(vi++, coords[i], coords[i+1]); break;
209
editor.addVertex(vi++, coords[i], coords[i+1], coords[i+2]); break;
215
editor.initCells(hdr.num_cells);
217
uint *cells = new uint[hdr.num_centities];
219
MPI_File_read_at_all(in, byte_offset + hdr.offsets[1] * sizeof(uint),
220
cells, hdr.num_centities, MPI_UNSIGNED, MPI_STATUS_IGNORE);
221
byte_offset += hdr.disp[1] * sizeof(uint);
223
in.read((char *)cells, (hdr.num_centities) * sizeof(uint));
228
for (uint i = 0; i < hdr.num_centities; i += hdr.num_entities)
231
for (uint j = 0; j < hdr.num_entities; j++)
232
v.push_back(cells[i + j]);
233
editor.addCell(ci++, v);
238
if (MPI::numProcesses() > 1)
240
uint *mapping = new uint[_mesh.numVertices()];
242
MPI_File_read_at_all(in, byte_offset + hdr.offsets[2] * sizeof(uint),
243
mapping, hdr.num_vertices, MPI_UNSIGNED, MPI_STATUS_IGNORE);
244
byte_offset += hdr.disp[2] * sizeof(uint);
246
in.read((char *)mapping, hdr.num_vertices * sizeof(uint));
248
for (VertexIterator v(_mesh); !v.end(); ++v)
249
_mesh.distdata().set_map(v->index(), mapping[v->index()], 0);
252
uint *ghosts = new uint[2 * hdr.num_ghosts];
254
MPI_File_read_at_all(in, byte_offset + hdr.offsets[3] * sizeof(uint),
255
ghosts, 2*hdr.num_ghosts, MPI_UNSIGNED, MPI_STATUS_IGNORE);
256
byte_offset += hdr.disp[3] * sizeof(uint);
258
in.read((char *)ghosts, 2*hdr.num_ghosts * sizeof(uint));
260
for (uint i = 0; i < 2 * hdr.num_ghosts; i += 2)
262
_mesh.distdata().set_ghost(ghosts[i], 0);
263
_mesh.distdata().set_ghost_owner(ghosts[i], ghosts[i+1], 0);
267
uint *shared = new uint[hdr.num_shared];
269
MPI_File_read_at_all(in, byte_offset + hdr.offsets[4] * sizeof(uint),
270
shared, hdr.num_shared, MPI_UNSIGNED, MPI_STATUS_IGNORE);
271
byte_offset += hdr.disp[4] * sizeof(uint);
273
in.read((char *)shared, hdr.num_shared * sizeof(uint));
275
for(uint i = 0; i < hdr.num_shared; i++)
276
_mesh.distdata().set_shared(shared[i], 0);
281
mesh.distdata().invalid_numbering();
284
restart_state = FUNC;
287
//-----------------------------------------------------------------------------
288
void Checkpoint::load(std::vector<Function *> func)
290
if (restart_state != FUNC)
291
error("Shut her down, Scotty, she's sucking mud again!");
293
std::vector<Function *>::iterator it;
295
uint pe_rank = MPI::processNumber();
296
uint pe_size = MPI::numProcesses();
297
uint vector_offset[3];
298
// FIXME store max(local_size)
299
for (it = func.begin(); it != func.end(); ++it)
302
MPI_File_read_at_all(in, byte_offset + pe_rank * 3 * sizeof(uint),
303
&vector_offset[0], 3, MPI_UNSIGNED, MPI_STATUS_IGNORE);
304
byte_offset += pe_size * 3 * sizeof(uint);
305
local_size = vector_offset[1];
307
in.read((char *)&local_size, sizeof(uint));
309
real *values = new real[local_size];
311
MPI_File_read_at_all(in, byte_offset + vector_offset[0] * sizeof(real),
312
values, vector_offset[1], MPI_DOUBLE, MPI_STATUS_IGNORE);
313
byte_offset += vector_offset[2] * sizeof(real);
315
in.read((char *)values, local_size * sizeof(real));
318
(*it)->vector().set(values);
319
(*it)->vector().apply();
326
//-----------------------------------------------------------------------------
327
void Checkpoint::load(std::vector<Vector *> vec)
329
if (restart_state != VEC)
330
error("Shut her down, Scotty, she's sucking mud again!");
332
std::vector<Vector *>::iterator it;
334
uint pe_rank = MPI::processNumber();
335
uint pe_size = MPI::numProcesses();
336
uint vector_offset[3];
337
for (it = vec.begin(); it != vec.end(); ++it)
340
MPI_File_read_at_all(in, byte_offset + pe_rank * 3 * sizeof(uint),
341
&vector_offset[0], 3, MPI_UNSIGNED, MPI_STATUS_IGNORE);
342
byte_offset += pe_size * 3 * sizeof(uint);
343
local_size = vector_offset[1];
345
in.read((char *)&local_size, sizeof(uint));
347
real *values = new real[local_size];
349
MPI_File_read_at_all(in, byte_offset + vector_offset[0] * sizeof(real),
350
values, vector_offset[1], MPI_DOUBLE, MPI_STATUS_IGNORE);
351
byte_offset += vector_offset[3] * sizeof(double);
353
in.read((char *)values, local_size * sizeof(real));
366
//-----------------------------------------------------------------------------
367
void Checkpoint::write(Mesh& mesh, chkp_outstream& out)
371
uint pe_size = MPI::numProcesses();
372
uint pe_rank = MPI::processNumber();
374
MPI_File_write_at_all(out, byte_offset + pe_rank * sizeof(chkp_mesh_hdr),
375
&hdr, sizeof(chkp_mesh_hdr), MPI_BYTE, MPI_STATUS_IGNORE);
376
byte_offset += pe_size * sizeof(chkp_mesh_hdr);
378
MPI_File_write_at_all(out, byte_offset + hdr.offsets[0] * sizeof(real),
379
mesh.coordinates(), hdr.num_coords, MPI_DOUBLE, MPI_STATUS_IGNORE);
380
byte_offset += hdr.disp[0] * sizeof(real);
382
MPI_File_write_at_all(out, byte_offset + hdr.offsets[1] * sizeof(uint),
383
mesh.cells(), hdr.num_centities, MPI_UNSIGNED, MPI_STATUS_IGNORE);
384
byte_offset += hdr.disp[1] * sizeof(uint);
387
out.write((char *)&hdr, sizeof(chkp_mesh_hdr));
388
out.write((char *)mesh.coordinates(), hdr.num_coords * sizeof(real));
389
out.write((char *)mesh.cells(), hdr.num_centities * sizeof(uint));
392
if (MPI::numProcesses() > 1)
394
uint *mapping = new uint[mesh.numVertices()];
395
for (VertexIterator v(mesh); !v.end(); ++v)
396
mapping[v->index()] = mesh.distdata().get_global(*v);
398
MPI_File_write_at_all(out, byte_offset + hdr.offsets[2] * sizeof(uint),
399
mapping, hdr.num_vertices, MPI_UNSIGNED, MPI_STATUS_IGNORE);
400
byte_offset += hdr.disp[2] * sizeof(uint);
402
out.write((char *)mapping, hdr.num_vertices * sizeof(uint));
406
uint *ghosts = new uint[2 * hdr.num_ghosts];
407
uint *gp = &ghosts[0];
408
for (MeshGhostIterator g(mesh.distdata(), 0); !g.end(); ++g)
414
MPI_File_write_at_all(out, byte_offset + hdr.offsets[3] * sizeof(uint),
415
ghosts, 2 * hdr.num_ghosts, MPI_UNSIGNED, MPI_STATUS_IGNORE);
416
byte_offset += hdr.disp[3] * sizeof(uint);
418
out.write((char *)ghosts, 2 * hdr.num_ghosts * sizeof(uint));
422
uint *shared = new uint[hdr.num_shared];
423
uint *sp = &shared[0];
424
for (MeshSharedIterator s(mesh.distdata(), 0); !s.end(); ++s)
427
MPI_File_write_at_all(out, byte_offset + hdr.offsets[4] * sizeof(uint),
428
shared, hdr.num_shared, MPI_UNSIGNED, MPI_STATUS_IGNORE);
429
byte_offset += hdr.disp[4] * sizeof(uint);
431
out.write((char *)shared, hdr.num_shared * sizeof(uint));
438
//-----------------------------------------------------------------------------
439
void Checkpoint::write(std::vector<Function *> func, chkp_outstream& out)
441
std::vector<Function *>::iterator it;
444
for (it = func.begin(); it != func.end(); ++it)
446
if((*it)->type() != Function::discrete)
447
error("Checkpoint restart only implemented for discrete functions");
448
max_size = std::max(max_size, (*it)->vector().local_size());
451
real *values = new real[max_size];
453
uint vector_offset[3];
454
uint pe_size = MPI::numProcesses();
455
uint pe_rank = MPI::processNumber();
458
for (it = func.begin(); it != func.end(); ++it)
460
uint local_size = (*it)->vector().local_size();
461
(*it)->vector().get(values);
464
vector_offset[0] = (*it)->vector().offset();
465
vector_offset[1] = (*it)->vector().local_size();
466
vector_offset[2] = (*it)->vector().size();
468
MPI_File_write_at_all(out, byte_offset + pe_rank * 3 * sizeof(uint),
469
&vector_offset[0], 3, MPI_UNSIGNED, MPI_STATUS_IGNORE);
470
byte_offset += pe_size * 3 * sizeof(uint);
472
MPI_File_write_at_all(out, byte_offset + vector_offset[0] * sizeof(real),
473
values, vector_offset[1], MPI_DOUBLE, MPI_STATUS_IGNORE);
474
byte_offset += (*it)->vector().size() * sizeof(real);
476
out.write((char *)&local_size, sizeof(uint));
477
out.write((char *)values, (*it)->vector().local_size() * sizeof(real));
483
//-----------------------------------------------------------------------------
484
void Checkpoint::write(std::vector<Vector *> vec, chkp_outstream& out)
486
std::vector<Vector *>::iterator it;
489
for (it = vec.begin(); it != vec.end(); ++it)
490
max_size = std::max(max_size, (*it)->local_size());
492
real *values = new real[max_size];
494
uint vector_offset[3];
495
uint pe_size = MPI::numProcesses();
496
uint pe_rank = MPI::processNumber();
498
for (it = vec.begin(); it != vec.end(); ++it)
504
vector_offset[0] = (*it)->offset();
505
vector_offset[1] = (*it)->local_size();
506
vector_offset[2] = (*it)->size();
508
MPI_File_write_at_all(out, byte_offset + pe_rank * 3 * sizeof(uint),
509
&vector_offset[0], 3, MPI_UNSIGNED, MPI_STATUS_IGNORE);
510
byte_offset += pe_size * 3 * sizeof(uint);
512
MPI_File_write_at_all(out, byte_offset + vector_offset[0] * sizeof(real),
513
values, vector_offset[1], MPI_DOUBLE, MPI_STATUS_IGNORE);
514
byte_offset += vector_offset[2] * sizeof(real);
516
uint local_size = (*it)->local_size();
517
out.write((char *)&local_size, sizeof(uint));
518
out.write((char *)values, (*it)->local_size() * sizeof(real));
524
//-----------------------------------------------------------------------------