LifeV
PartitionIO.hpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5 Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6 Copyright (C) 2010, 2011, 2012 EPFL, Politecnico di Milano, Emory University
7 
8 This file is part of LifeV.
9 
10 LifeV is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14 
15 LifeV is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 
27 /*!
28  @file
29  @brief Class that handles I/O of mesh parts (for offline partitioning mode)
30 
31  @date 10-05-2012
32  @author Radu Popescu <radu.popescu@epfl.ch>
33  @maintainer Radu Popescu <radu.popescu@epfl.ch>
34 */
35 
36 #ifndef PARTITION_IO_H_
37 #define PARTITION_IO_H_
38 
39 #include <algorithm>
40 
41 #include <Epetra_config.h>
42 
43 #include<lifev/core/LifeV.hpp>
44 
45 #ifdef LIFEV_HAS_HDF5
46 #ifdef HAVE_MPI
47 
48 #include <Epetra_MpiComm.h>
49 
50 #include <lifev/core/filter/HDF5IO.hpp>
51 
52 namespace LifeV
53 {
54 
55 /*!
56  @brief Class that handles I/O of mesh parts (for offline partitioning mode)
57  @author Radu Popescu radu.popescu@epfl.ch
58 
59  This class is used to write the mesh parts produced by (offline) mesh
60  partitioning into a single HDF5 container. This part is done with a single
61  MPI process (usually on a workstation).
62 
63  The class is later used during an online simulation (multiple MPI processes,
64  on a cluster, supercomputer etc.) to read the mesh parts.
65 
66  Usage:
67  - call the constructor (a default one is also available)
68  - if the default constructor was used, call setup method to initialize
69  the object
70  - call write method to store a set of mesh parts in the HDF5 file
71  - call read method to load the mesh part associate with the current
72  MPI process from the HDF5 file
73 
74  Creating, opening and closing the HDF5 file is done automatically by the
75  object.
76 
77  Description of the storage format:
78  N - number of mesh parts
79 
80  The HDF5 container contains 6 tables (num. of rows is the leading dimension):
81 
82  1. stats - N x 15 (unsigned integer) - each row belongs to a mesh part and
83  contains the following values, in order:
84  - N
85  - graph part size (unused)
86  - number of points
87  - number of boundary points
88  - number of vertices
89  - number of boundary vertices
90  - number of global vertices
91  - number of edges
92  - number of boundary edges
93  - number of global edges
94  - number of faces
95  - number of boundary faces
96  - number of global faces
97  - number of volumes
98  - number of global volumes
99  2. point_ids - (3 * N) x (maximum number of points in mesh parts) (unsigned
100  integer) - each mesh part uses three consecutive rows, with the following
101  contents:
102  - point markers
103  - point global ids
104  - point flags
105  3. point_coords - (3 * N) x (maximum number of points in mesh parts) (double)
106  each mesh part uses three consecutive rows, with the following contents:
107  - point x coordinates
108  - point y coordinates
109  - point z coordinates
110  4. edges - (5 * N) x (maximum number of edges in mesh parts) (unsigned
111  integer) - each mesh part uses three consecutive rows, with the following
112  contents:
113  - local ids of first point of edges
114  - local ids of second point of edges
115  - edge markers
116  - edge global ids
117  - edge flags
118  5. faces ((7 + num of face nodes) * N) x (maximum number of faces in mesh
119  parts) (unsigned integer) - each mesh part uses (7 + num of face nodes)
120  consecutive rows, with the following contents:
121  - one row for the local ids of each face node of the faces in the part
122  - face markers
123  - face global ids
124  - id of first neighbour element
125  - id of second neighbour element
126  - position of first neighbour element
127  - position of second neighbour element
128  - face flags
129  6. elements ((3 + num of element nodes) * N) x (maximum number of elements
130  in mesh parts) (unsigned integer) - each mesh part uses (2 + num of
131  element nodes) consecutive rows, with the following contents:
132  - one row for the local ids of each element node of the elements in
133  the mesh part
134  - element markers
135  - element global ids
136  - element flag
137 */
138 template<typename MeshType>
139 class PartitionIO
140 {
141 public:
142  //! @name Public Types
143  //@{
144  typedef MeshType mesh_Type;
145  typedef std::shared_ptr<mesh_Type> meshPtr_Type;
146  typedef std::vector<meshPtr_Type> meshParts_Type;
147  typedef std::shared_ptr<meshParts_Type> meshPartsPtr_Type;
148  // TODO: enable the following two typedefs if I decide to also
149  // write the graph to the HDF5 container
150  // typedef std::vector<std::vector<Int> > table_Type;
151  // typedef std::shared_ptr<table_Type> tablePtr_Type;
152  typedef std::shared_ptr<Epetra_MpiComm> commPtr_Type;
153  //@}
154 
155  //! \name Constructors & Destructors
156  //@{
157  //! Default empty constructor
158  PartitionIO() {}
159 
160  //! Constructor
161  /*!
162  * Non-empty constructor
163  * \param fileName the name of the HDF5 file to be used
164  * \param comm pointer to Epetra_Comm
165  * \param transposeInFile (default false) write/read tables transposed
166  * in the HDF5. This option is available because the transposed
167  * format may be faster on certain machines. Leave as default
168  * unless certain that it works for a given machine.
169  */
170  PartitionIO (const std::string& fileName,
171  const commPtr_Type& comm,
172  const bool transposeInFile = false);
173 
174  //! Empty destructor
175  virtual ~PartitionIO() {}
176  //@}
177 
178  //! \name Public Methods
179  //@{
180  //! Initialization method
181  /*!
182  * Initialization method that is used with the default constructor
183  * \param fileName the name of the HDF5 file to be used
184  * \param comm pointer to Epetra_Comm
185  * \param transposeInFile (default false) write/read tables transposed
186  * in the HDF5. This option is available because the transposed
187  * format may be faster on certain machines. Leave as default
188  * unless certain that it works for a given machine.
189  */
190  void setup (const std::string& fileName,
191  const commPtr_Type& comm,
192  const bool transposeInFile = false);
193  //! Write method
194  /*!
195  * Call this method to write the mesh parts to disk
196  * \param meshParts pointer to a vector containing pointers to the mesh
197  * parts (RegionMesh objects). This pointer is released after
198  * writing, so the mesh parts can be cleared from memory
199  */
200  void write (const meshPartsPtr_Type& meshParts);
201  //! Read method
202  /*!
203  * Call this method to read from the HDF5 file the mesh part associated
204  * with the rank of the current MPI process
205  * \param meshPart pointer to a RegionMesh that will contain the mesh
206  * part. If the RegionMesh has been initialized and contains any
207  * state, it will be destroyed before reading
208  */
209  void read (meshPtr_Type& meshPart);
210  //@}
211 
212 private:
213  // Copy constructor and assignment operator are disabled
214  PartitionIO (const PartitionIO&);
215  PartitionIO& operator= (const PartitionIO&);
216 
217  //! Private Methods
218  //@{
219  // Methods for writing
220  void writeStats();
221  void writePoints();
222  void writeEdges();
223  void writeFaces();
224  void writeElements();
225  // Methods for reading
226  void readStats();
227  void readPoints();
228  void readEdges();
229  void readFaces();
230  void readElements();
231  //@}
232 
233  //! Private Data Members
234  //@{
235  commPtr_Type M_comm;
236  UInt M_myRank;
237  std::string M_fileName;
238  bool M_transposeInFile;
239  meshPartsPtr_Type M_meshPartsOut;
240  meshPtr_Type M_meshPartIn;
241  // Mesh geometry
242  UInt M_elementNodes;
243  UInt M_faceNodes;
244  UInt M_maxNumPoints;
245  UInt M_maxNumEdges;
246  UInt M_maxNumFaces;
247  UInt M_maxNumElements;
248  UInt M_numParts;
249  // Counters when loading the mesh part
250  UInt M_numPoints;
251  UInt M_numEdges;
252  UInt M_numFaces;
253  UInt M_numElements;
254  //HDF5 I/O filter
255  HDF5IO M_HDF5IO;
256  // Buffers for reading/writing
257  std::vector<UInt> M_uintBuffer;
258  std::vector<Real> M_realBuffer;
259  //@}
260 }; // class PartitionIO
261 
262 template<typename MeshType>
263 inline PartitionIO<MeshType>::PartitionIO (const std::string& fileName,
264  const commPtr_Type& comm,
265  const bool transposeInFile) :
266  M_comm (comm),
267  M_fileName (fileName),
268  M_transposeInFile (transposeInFile),
269  M_maxNumPoints (0),
270  M_maxNumEdges (0),
271  M_maxNumFaces (0),
272  M_maxNumElements (0)
273 {
274  M_elementNodes = MeshType::elementShape_Type::S_numPoints;
275  M_faceNodes = MeshType::elementShape_Type::GeoBShape::S_numPoints;
276 
277  M_myRank = M_comm->MyPID();
278 }
279 
280 template<typename MeshType>
281 inline void PartitionIO<MeshType>::setup (const std::string& fileName,
282  const commPtr_Type& comm,
283  const bool transposeInFile)
284 {
285  M_comm = comm;
286  M_fileName = fileName;
287  M_transposeInFile = transposeInFile;
288  M_maxNumPoints = 0;
289  M_maxNumEdges = 0;
290  M_maxNumFaces = 0;
291  M_maxNumElements = 0;
292 
293  M_elementNodes = MeshType::elementShape_Type::S_numPoints;
294  M_faceNodes = MeshType::elementShape_Type::GeoBShape::S_numPoints;
295 }
296 
297 template<typename MeshType>
298 void PartitionIO<MeshType>::write (const meshPartsPtr_Type& meshParts)
299 {
300  M_meshPartsOut = meshParts;
301  M_numParts = M_meshPartsOut->size();
302 
303  M_HDF5IO.openFile (M_fileName, M_comm, false);
304  writeStats();
305  writePoints();
306  writeEdges();
307  writeFaces();
308  writeElements();
309  M_HDF5IO.closeFile();
310 
311  M_meshPartsOut.reset();
312 }
313 
314 template<typename MeshType>
315 void PartitionIO<MeshType>::read (meshPtr_Type& meshPart)
316 {
317  meshPart.reset();
318  M_meshPartIn.reset (new mesh_Type);
319 
320  M_HDF5IO.openFile (M_fileName, M_comm, true);
321  readStats();
322  readPoints();
323  readEdges();
324  readFaces();
325  readElements();
326  M_HDF5IO.closeFile();
327 
328  meshPart = M_meshPartIn;
329  M_meshPartIn.reset();
330 }
331 
332 template<typename MeshType>
333 void PartitionIO<MeshType>::writeStats()
334 {
335  // Write mesh partition stats (N = number of parts)
336  // This is an N x 15 table of int
337  hsize_t currentSpaceDims[2];
338  hsize_t currentCount[2];
339  if (! M_transposeInFile)
340  {
341  currentSpaceDims[0] = M_numParts;
342  currentSpaceDims[1] = 15;
343  currentCount[0] = 1;
344  currentCount[1] = currentSpaceDims[1];
345  }
346  else
347  {
348  currentSpaceDims[0] = 15;
349  currentSpaceDims[1] = M_numParts;
350  currentCount[0] = currentSpaceDims[0];
351  currentCount[1] = 1;
352  }
353 
354  // Create new table
355  M_HDF5IO.createTable ("stats", H5T_STD_U32BE, currentSpaceDims);
356 
357  // Fill buffer
358  M_uintBuffer.resize (15);
359  for (UInt i = 0; i < M_numParts; ++i)
360  {
361  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
362  M_uintBuffer[0] = M_numParts;
363  // Next one is unused. I'll put it to keep compatibility
364  // in case I decide to write the graphs
365  M_uintBuffer[1] = 0;
366  M_uintBuffer[2] = currentPart.numPoints();
367  if (M_uintBuffer[2] > M_maxNumPoints)
368  {
369  M_maxNumPoints = M_uintBuffer[2];
370  }
371  M_uintBuffer[3] = currentPart.numBPoints();
372  M_uintBuffer[4] = currentPart.numVertices();
373  M_uintBuffer[5] = currentPart.numBVertices();
374  M_uintBuffer[6] = currentPart.numGlobalVertices();
375  M_uintBuffer[7] = currentPart.numEdges();
376  if (M_uintBuffer[7] > M_maxNumEdges)
377  {
378  M_maxNumEdges = M_uintBuffer[7];
379  }
380  M_uintBuffer[8] = currentPart.numBEdges();
381  M_uintBuffer[9] = currentPart.numGlobalEdges();
382  M_uintBuffer[10] = currentPart.numFaces();
383  if (M_uintBuffer[10] > M_maxNumFaces)
384  {
385  M_maxNumFaces = M_uintBuffer[10];
386  }
387  M_uintBuffer[11] = currentPart.numBFaces();
388  M_uintBuffer[12] = currentPart.numGlobalFaces();
389  M_uintBuffer[13] = currentPart.numVolumes();
390  if (M_uintBuffer[13] > M_maxNumElements)
391  {
392  M_maxNumElements = M_uintBuffer[13];
393  }
394  M_uintBuffer[14] = currentPart.numGlobalVolumes();
395 
396  hsize_t currentOffset[2];
397  if (! M_transposeInFile)
398  {
399  currentOffset[0] = i;
400  currentOffset[1] = 0;
401  }
402  else
403  {
404  currentOffset[0] = 0;
405  currentOffset[1] = i;
406  }
407  M_HDF5IO.write ("stats", H5T_NATIVE_UINT, currentCount, currentOffset,
408  &M_uintBuffer[0]);
409  }
410 
411  M_HDF5IO.closeTable ("stats");
412 }
413 
414 template<typename MeshType>
415 void PartitionIO<MeshType>::writePoints()
416 {
417  // Write points (N = number of parts)
418  // Two tables: one is (3 * N) x max_num_points of int
419  // second is (3 * N) x max_num_points of real
420  hsize_t currentSpaceDims[2];
421  hsize_t currentCount[2];
422  if (! M_transposeInFile)
423  {
424  currentSpaceDims[0] = 3 * M_numParts;
425  currentSpaceDims[1] = M_maxNumPoints;
426  currentCount[0] = 3;
427  currentCount[1] = currentSpaceDims[1];
428  }
429  else
430  {
431  currentSpaceDims[0] = M_maxNumPoints;
432  currentSpaceDims[1] = 3 * M_numParts;
433  currentCount[0] = currentSpaceDims[0];
434  currentCount[1] = 3;
435  }
436 
437  M_HDF5IO.createTable ("point_ids", H5T_STD_U32BE, currentSpaceDims);
438  M_HDF5IO.createTable ("point_coords", H5T_IEEE_F64BE, currentSpaceDims);
439 
440  // Fill buffer
441  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
442  M_realBuffer.resize (currentCount[0] * currentCount[1], 0);
443  UInt stride = currentCount[1];
444  if (! M_transposeInFile)
445  {
446  for (UInt i = 0; i < M_numParts; ++i)
447  {
448  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
449  for (UInt j = 0; j < currentPart.numPoints(); ++j)
450  {
451  M_uintBuffer[j] = currentPart.pointList[j].markerID();
452  M_uintBuffer[stride + j] = currentPart.point (j).id();
453  M_uintBuffer[2 * stride + j] =
454  static_cast<int> (currentPart.pointList[j].flag() );
455  M_realBuffer[j] = currentPart.pointList[j].x();
456  M_realBuffer[stride + j] = currentPart.pointList[j].y();
457  M_realBuffer[2 * stride + j] = currentPart.pointList[j].z();
458  }
459 
460  hsize_t currentOffset[2] = {i* currentCount[0], 0};
461  M_HDF5IO.write ("point_ids", H5T_NATIVE_UINT, currentCount,
462  currentOffset, &M_uintBuffer[0]);
463  M_HDF5IO.write ("point_coords", H5T_NATIVE_DOUBLE, currentCount,
464  currentOffset, &M_realBuffer[0]);
465  }
466  }
467  else
468  {
469  for (UInt i = 0; i < M_numParts; ++i)
470  {
471  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
472  for (UInt j = 0; j < currentPart.numPoints(); ++j)
473  {
474  M_uintBuffer[stride * j] = currentPart.pointList[j].markerID();
475  M_uintBuffer[stride * j + 1] = currentPart.point (j).id();
476  M_uintBuffer[stride * j + 2] =
477  static_cast<int> (currentPart.pointList[j].flag() );
478  M_realBuffer[stride * j] = currentPart.pointList[j].x();
479  M_realBuffer[stride * j + 1] = currentPart.pointList[j].y();
480  M_realBuffer[stride * j + 2] = currentPart.pointList[j].z();
481  }
482 
483  hsize_t currentOffset[2] = {0, i* currentCount[1]};
484  M_HDF5IO.write ("point_ids", H5T_NATIVE_UINT, currentCount,
485  currentOffset, &M_uintBuffer[0]);
486  M_HDF5IO.write ("point_coords", H5T_NATIVE_DOUBLE, currentCount,
487  currentOffset, &M_realBuffer[0]);
488  }
489  }
490  M_realBuffer.resize (0);
491 
492  M_HDF5IO.closeTable ("point_ids");
493  M_HDF5IO.closeTable ("point_coords");
494 }
495 
496 template<typename MeshType>
497 void PartitionIO<MeshType>::writeEdges()
498 {
499  // Write edges (N = number of parts)
500  // Table is (5 * N) x max_num_edges of int
501  hsize_t currentSpaceDims[2];
502  hsize_t currentCount[2];
503  if (! M_transposeInFile)
504  {
505  currentSpaceDims[0] = 5 * M_numParts;
506  currentSpaceDims[1] = M_maxNumEdges;
507  currentCount[0] = 5;
508  currentCount[1] = currentSpaceDims[1];
509  }
510  else
511  {
512  currentSpaceDims[0] = M_maxNumEdges;
513  currentSpaceDims[1] = 5 * M_numParts;
514  currentCount[0] = currentSpaceDims[0];
515  currentCount[1] = 5;
516  }
517 
518  M_HDF5IO.createTable ("edges", H5T_STD_U32BE, currentSpaceDims);
519 
520  // Fill buffer
521  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
522  UInt stride = currentCount[1];
523  if (! M_transposeInFile)
524  {
525  for (UInt i = 0; i < M_numParts; ++i)
526  {
527  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
528  for (UInt j = 0; j < currentPart.numEdges(); ++j)
529  {
530  M_uintBuffer[j] = currentPart.edgeList[j].point (0).localId();
531  M_uintBuffer[stride + j] =
532  currentPart.edgeList[j].point (1).localId();
533  M_uintBuffer[2 * stride + j] =
534  currentPart.edgeList[j].markerID();
535  M_uintBuffer[3 * stride + j] = currentPart.edgeList[j].id();
536  M_uintBuffer[4 * stride + j] =
537  static_cast<int> (currentPart.edgeList[j].flag() );
538  }
539 
540  hsize_t currentOffset[2] = {i* currentCount[0], 0};
541  M_HDF5IO.write ("edges", H5T_NATIVE_UINT, currentCount,
542  currentOffset, &M_uintBuffer[0]);
543  }
544  }
545  else
546  {
547  for (UInt i = 0; i < M_numParts; ++i)
548  {
549  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
550  for (UInt j = 0; j < currentPart.numEdges(); ++j)
551  {
552  M_uintBuffer[stride * j] =
553  currentPart.edgeList[j].point (0).localId();
554  M_uintBuffer[stride * j + 1] =
555  currentPart.edgeList[j].point (1).localId();
556  M_uintBuffer[stride * j + 2] =
557  currentPart.edgeList[j].markerID();
558  M_uintBuffer[stride * j + 3] = currentPart.edgeList[j].id();
559  M_uintBuffer[stride * j + 4] =
560  static_cast<int> (currentPart.edgeList[j].flag() );
561  }
562 
563  hsize_t currentOffset[2] = {0, i* currentCount[1]};
564  M_HDF5IO.write ("edges", H5T_NATIVE_UINT, currentCount,
565  currentOffset, &M_uintBuffer[0]);
566  }
567  }
568 
569  M_HDF5IO.closeTable ("edges");
570 }
571 
572 template<typename MeshType>
573 void PartitionIO<MeshType>::writeFaces()
574 {
575  // Write faces (N = number of parts)
576  // Table is ((7 + num_face_nodes * N) x max_num_faces of int
577  hsize_t currentSpaceDims[2];
578  hsize_t currentCount[2];
579  if (! M_transposeInFile)
580  {
581  currentSpaceDims[0] = (7 + M_faceNodes) * M_numParts;
582  currentSpaceDims[1] = M_maxNumFaces;
583  currentCount[0] = 7 + M_faceNodes;
584  currentCount[1] = currentSpaceDims[1];
585  }
586  else
587  {
588  currentSpaceDims[0] = M_maxNumFaces;
589  currentSpaceDims[1] = (7 + M_faceNodes) * M_numParts;
590  currentCount[0] = currentSpaceDims[0];
591  currentCount[1] = 7 + M_faceNodes;
592  }
593 
594  M_HDF5IO.createTable ("faces", H5T_STD_U32BE, currentSpaceDims);
595 
596  // Fill buffer
597  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
598  UInt stride = currentCount[1];
599  if (! M_transposeInFile)
600  {
601  for (UInt i = 0; i < M_numParts; ++i)
602  {
603  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
604  for (UInt j = 0; j < currentPart.numFaces(); ++j)
605  {
606  for (UInt k = 0; k < M_faceNodes; ++k)
607  {
608  M_uintBuffer[k * stride + j] =
609  currentPart.faceList[j].point (k).localId();
610  }
611  M_uintBuffer[M_faceNodes * stride + j] =
612  currentPart.faceList[j].markerID();
613  M_uintBuffer[ (M_faceNodes + 1) * stride + j] =
614  currentPart.faceList[j].id();
615  M_uintBuffer[ (M_faceNodes + 2) * stride + j] =
616  currentPart.faceList[j].firstAdjacentElementIdentity();
617  M_uintBuffer[ (M_faceNodes + 3) * stride + j] =
618  currentPart.faceList[j].secondAdjacentElementIdentity();
619  M_uintBuffer[ (M_faceNodes + 4) * stride + j] =
620  currentPart.faceList[j].firstAdjacentElementPosition();
621  M_uintBuffer[ (M_faceNodes + 5) * stride + j] =
622  currentPart.faceList[j].secondAdjacentElementPosition();
623  M_uintBuffer[ (M_faceNodes + 6) * stride + j] =
624  static_cast<int> (currentPart.faceList[j].flag() );
625  }
626 
627  hsize_t currentOffset[2] = {i* currentCount[0], 0};
628  M_HDF5IO.write ("faces", H5T_NATIVE_UINT, currentCount,
629  currentOffset, &M_uintBuffer[0]);
630  }
631  }
632  else
633  {
634  for (UInt i = 0; i < M_numParts; ++i)
635  {
636  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
637  for (UInt j = 0; j < currentPart.numFaces(); ++j)
638  {
639  for (UInt k = 0; k < M_faceNodes; ++k)
640  {
641  M_uintBuffer[stride * j + k] =
642  currentPart.faceList[j].point (k).localId();
643  }
644  M_uintBuffer[stride * j + M_faceNodes] =
645  currentPart.faceList[j].markerID();
646  M_uintBuffer[stride * j + M_faceNodes + 1] =
647  currentPart.faceList[j].id();
648  M_uintBuffer[stride * j + M_faceNodes + 2] =
649  currentPart.faceList[j].firstAdjacentElementIdentity();
650  M_uintBuffer[stride * j + M_faceNodes + 3] =
651  currentPart.faceList[j].secondAdjacentElementIdentity();
652  M_uintBuffer[stride * j + M_faceNodes + 4] =
653  currentPart.faceList[j].firstAdjacentElementPosition();
654  M_uintBuffer[stride * j + M_faceNodes + 5] =
655  currentPart.faceList[j].secondAdjacentElementPosition();
656  M_uintBuffer[stride * j + M_faceNodes + 6] =
657  static_cast<int> (currentPart.faceList[j].flag() );
658  }
659 
660  hsize_t currentOffset[2] = {0, i* currentCount[1]};
661  M_HDF5IO.write ("faces", H5T_NATIVE_UINT, currentCount,
662  currentOffset, &M_uintBuffer[0]);
663  }
664  }
665 
666  M_HDF5IO.closeTable ("faces");
667 }
668 
669 template<typename MeshType>
670 void PartitionIO<MeshType>::writeElements()
671 {
672  // Write elements (N = number of parts)
673  // Table is ((3 + num_element_nodes * N) x max_num_elements of int
674  hsize_t currentSpaceDims[2];
675  hsize_t currentCount[2];
676  if (! M_transposeInFile)
677  {
678  currentSpaceDims[0] = (3 + M_elementNodes) * M_numParts;
679  currentSpaceDims[1] = M_maxNumElements;
680  currentCount[0] = 3 + M_elementNodes;
681  currentCount[1] = currentSpaceDims[1];
682  }
683  else
684  {
685  currentSpaceDims[0] = M_maxNumElements;
686  currentSpaceDims[1] = (3 + M_elementNodes) * M_numParts;
687  currentCount[0] = currentSpaceDims[0];;
688  currentCount[1] = 3 + M_elementNodes;
689  }
690 
691  M_HDF5IO.createTable ("elements", H5T_STD_U32BE, currentSpaceDims);
692 
693  // Fill buffer
694  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
695  UInt stride = currentCount[1];
696  if (! M_transposeInFile)
697  {
698  for (UInt i = 0; i < M_numParts; ++i)
699  {
700  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
701  for (UInt j = 0; j < currentPart.numVolumes(); ++j)
702  {
703  for (UInt k = 0; k < M_elementNodes; ++k)
704  {
705  M_uintBuffer[k * stride + j] =
706  currentPart.volumeList[j].point (k).localId();
707  }
708  M_uintBuffer[M_elementNodes * stride + j] =
709  currentPart.volumeList[j].markerID();
710  M_uintBuffer[ (M_elementNodes + 1) * stride + j] =
711  currentPart.volumeList[j].id();
712  M_uintBuffer[ (M_elementNodes + 2) * stride + j] =
713  static_cast<int> (currentPart.volumeList[j].flag() );
714  }
715 
716  hsize_t currentOffset[2] = {i* currentCount[0], 0};
717  M_HDF5IO.write ("elements", H5T_NATIVE_UINT, currentCount,
718  currentOffset, &M_uintBuffer[0]);
719  }
720  }
721  else
722  {
723  for (UInt i = 0; i < M_numParts; ++i)
724  {
725  mesh_Type& currentPart = (* (*M_meshPartsOut) [i]);
726  for (UInt j = 0; j < currentPart.numVolumes(); ++j)
727  {
728  for (UInt k = 0; k < M_elementNodes; ++k)
729  {
730  M_uintBuffer[stride * j + k] =
731  currentPart.volumeList[j].point (k).localId();
732  }
733  M_uintBuffer[stride * j + M_elementNodes] =
734  currentPart.volumeList[j].markerID();
735  M_uintBuffer[stride * j + M_elementNodes + 1] =
736  currentPart.volumeList[j].id();
737  M_uintBuffer[stride * j + M_elementNodes + 2] =
738  static_cast<int> (currentPart.volumeList[j].flag() );
739  }
740 
741  hsize_t currentOffset[2] = {0, i* currentCount[1]};
742  M_HDF5IO.write ("elements", H5T_NATIVE_UINT, currentCount,
743  currentOffset, &M_uintBuffer[0]);
744  }
745  }
746 
747  M_HDF5IO.closeTable ("elements");
748 }
749 
750 template<typename MeshType>
751 void PartitionIO<MeshType>::readStats()
752 {
753  // Write mesh partition stats (N = number of parts)
754  // This is an N x 15 table of int
755  hsize_t currentSpaceDims[2];
756  hsize_t currentCount[2];
757  hsize_t currentOffset[2];
758 
759  M_HDF5IO.openTable ("stats", currentSpaceDims);
760 
761  if (! M_transposeInFile)
762  {
763  currentCount[0] = 1;
764  currentCount[1] = currentSpaceDims[1];
765  currentOffset[0] = M_myRank;
766  currentOffset[1] = 0;
767  }
768  else
769  {
770  currentCount[0] = currentSpaceDims[0];
771  currentCount[1] = 1;
772  currentOffset[0] = 0;
773  currentOffset[1] = M_myRank;
774  }
775 
776  // Fill buffer
777  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
778  M_HDF5IO.read ("stats", H5T_NATIVE_UINT, currentCount, currentOffset,
779  &M_uintBuffer[0]);
780 
781  M_HDF5IO.closeTable ("stats");
782 
783  // Insert stats into mesh partition object
784  M_numPoints = M_uintBuffer[2];
785  M_meshPartIn->setMaxNumPoints (M_uintBuffer[2], true);
786  M_meshPartIn->setNumBPoints (M_uintBuffer[3]);
787 
788  // Vertices
789  M_meshPartIn->setNumVertices (M_uintBuffer[4]);
790  M_meshPartIn->setNumBVertices (M_uintBuffer[5]);
791  M_meshPartIn->setNumGlobalVertices (M_uintBuffer[6]);
792 
793  // Edges
794  M_numEdges = M_uintBuffer[7];
795  M_meshPartIn->setNumEdges (M_uintBuffer[7]);
796  M_meshPartIn->setMaxNumEdges (M_uintBuffer[7], true);
797  M_meshPartIn->setNumBEdges (M_uintBuffer[8]);
798  M_meshPartIn->setMaxNumGlobalEdges (M_uintBuffer[9]);
799 
800  // Faces
801  M_numFaces = M_uintBuffer[10];
802  M_meshPartIn->setNumFaces (M_uintBuffer[10]);
803  M_meshPartIn->setMaxNumFaces (M_uintBuffer[10], true);
804  M_meshPartIn->setNumBFaces (M_uintBuffer[11]);
805  M_meshPartIn->setMaxNumGlobalFaces (M_uintBuffer[12]);
806 
807  // Volumes
808  M_numElements = M_uintBuffer[13];
809  M_meshPartIn->setMaxNumVolumes (M_uintBuffer[13], true);
810  M_meshPartIn->setMaxNumGlobalVolumes (M_uintBuffer[14]);
811 }
812 
813 template<typename MeshType>
814 void PartitionIO<MeshType>::readPoints()
815 {
816  // Read mesh points (N = number of parts)
817  // There are two tables: a (3 * N) x max_num_points table of int and
818  // a (3 * N) x max_num_points table of real
819  hsize_t currentSpaceDims[2];
820  hsize_t currentCount[2];
821  hsize_t currentOffset[2];
822 
823  //hid_t realDataset = H5Dopen(M_fileId, "point_coords", H5P_DEFAULT);
824 
825  M_HDF5IO.openTable ("point_ids", currentSpaceDims);
826  M_HDF5IO.openTable ("point_coords", currentSpaceDims);
827 
828  if (! M_transposeInFile)
829  {
830  currentCount[0] = 3;
831  currentCount[1] = currentSpaceDims[1];
832  currentOffset[0] = currentCount[0] * M_myRank;
833  currentOffset[1] = 0;
834  }
835  else
836  {
837  currentCount[0] = currentSpaceDims[0];
838  currentCount[1] = 3;
839  currentOffset[0] = 0;
840  currentOffset[1] = currentCount[1] * M_myRank;
841  }
842 
843  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
844  M_realBuffer.resize (currentCount[0] * currentCount[1], 0);
845  M_HDF5IO.read ("point_ids", H5T_NATIVE_UINT, currentCount, currentOffset,
846  &M_uintBuffer[0]);
847  M_HDF5IO.read ("point_coords", H5T_NATIVE_DOUBLE, currentCount,
848  currentOffset, &M_realBuffer[0]);
849 
850  M_HDF5IO.closeTable ("point_ids");
851  M_HDF5IO.closeTable ("point_coords");
852 
853  // Insert points into the mesh partition object
854  M_meshPartIn->pointList.reserve (M_numPoints);
855  M_meshPartIn->_bPoints.reserve (M_meshPartIn->numBPoints() );
856 
857  typename MeshType::point_Type* pp = 0;
858 
859  UInt stride = currentCount[1];
860  if (! M_transposeInFile)
861  {
862  for (UInt j = 0; j < M_numPoints; ++j)
863  {
864  pp = & ( M_meshPartIn->addPoint ( false, false ) );
865  pp->replaceFlag (
866  static_cast<flag_Type> (M_uintBuffer[2 * stride + j]) );
867  pp->setMarkerID (M_uintBuffer[j]);
868  pp->x() = M_realBuffer[j];
869  pp->y() = M_realBuffer[stride + j];
870  pp->z() = M_realBuffer[2 * stride + j];
871  pp->setId (M_uintBuffer[stride + j]);
872  }
873  }
874  else
875  {
876  for (UInt j = 0; j < M_numPoints; ++j)
877  {
878  pp = & ( M_meshPartIn->addPoint ( false, false ) );
879  pp->replaceFlag (
880  static_cast<flag_Type> (M_uintBuffer[stride * j + 2]) );
881  pp->setMarkerID (M_uintBuffer[stride * j]);
882  pp->x() = M_realBuffer[stride * j];
883  pp->y() = M_realBuffer[stride * j + 1];
884  pp->z() = M_realBuffer[stride * j + 2];
885  pp->setId (M_uintBuffer[stride * j + 1]);
886  }
887  }
888  M_realBuffer.resize (0);
889 }
890 
891 template<typename MeshType>
892 void PartitionIO<MeshType>::readEdges()
893 {
894  // Read mesh edges (N = number of parts)
895  // Read a (5 * N) x max_num_edges table of int and
896  hsize_t currentSpaceDims[2];
897  hsize_t currentCount[2];
898  hsize_t currentOffset[2];
899 
900  M_HDF5IO.openTable ("edges", currentSpaceDims);
901 
902  if (! M_transposeInFile)
903  {
904  currentCount[0] = 5;
905  currentCount[1] = currentSpaceDims[1];
906  currentOffset[0] = currentCount[0] * M_myRank;
907  currentOffset[1] = 0;
908  }
909  else
910  {
911  currentCount[0] = currentSpaceDims[0];
912  currentCount[1] = 5;
913  currentOffset[0] = 0;
914  currentOffset[1] = currentCount[1] * M_myRank;
915  }
916 
917  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
918  M_HDF5IO.read ("edges", H5T_NATIVE_UINT, currentCount, currentOffset,
919  &M_uintBuffer[0]);
920 
921  M_HDF5IO.closeTable ("edges");
922 
923  M_meshPartIn->edgeList.reserve (M_numEdges);
924 
925  typename MeshType::edge_Type* pe;
926 
927  UInt stride = currentCount[1];
928  if (! M_transposeInFile)
929  {
930  for (UInt j = 0; j < M_numEdges; ++j)
931  {
932  pe = & (M_meshPartIn->addEdge (false) );
933  pe->replaceFlag (
934  static_cast<flag_Type> (M_uintBuffer[4 * stride + j]) );
935  pe->setId (M_uintBuffer[3 * stride + j]);
936  pe->setPoint (0, M_meshPartIn->point (M_uintBuffer[j]) );
937  pe->setPoint (1, M_meshPartIn->point (M_uintBuffer[stride + j]) );
938  pe->setMarkerID (M_uintBuffer[2 * stride + j]);
939  }
940  }
941  else
942  {
943  for (UInt j = 0; j < M_numEdges; ++j)
944  {
945  pe = & (M_meshPartIn->addEdge (false) );
946  pe->replaceFlag (
947  static_cast<flag_Type> (M_uintBuffer[stride * j + 4]) );
948  pe->setId (M_uintBuffer[stride * j + 3]);
949  pe->setPoint (0, M_meshPartIn->point (M_uintBuffer[stride * j]) );
950  pe->setPoint (1, M_meshPartIn->point (M_uintBuffer[stride * j + 1]) );
951  pe->setMarkerID (M_uintBuffer[stride * j + 2]);
952  }
953  }
954 }
955 
956 template<typename MeshType>
957 void PartitionIO<MeshType>::readFaces()
958 {
959  // read mesh faces (N = number of parts)
960  // Read a ((7 + num_face_points) * N) x max_num_faces table of int
961  hsize_t currentSpaceDims[2];
962  hsize_t currentCount[2];
963  hsize_t currentOffset[2];
964 
965  M_HDF5IO.openTable ("faces", currentSpaceDims);
966 
967  if (! M_transposeInFile)
968  {
969  currentCount[0] = 7 + M_faceNodes;
970  currentCount[1] = currentSpaceDims[1];
971  currentOffset[0] = currentCount[0] * M_myRank;
972  currentOffset[1] = 0;
973  }
974  else
975  {
976  currentCount[0] = currentSpaceDims[0];
977  currentCount[1] = 7 + M_faceNodes;
978  currentOffset[0] = 0;
979  currentOffset[1] = currentCount[1] * M_myRank;
980  }
981 
982  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
983  M_HDF5IO.read ("faces", H5T_NATIVE_UINT, currentCount, currentOffset,
984  &M_uintBuffer[0]);
985 
986  M_HDF5IO.closeTable ("faces");
987 
988  typename MeshType::face_Type* pf = 0;
989 
990  M_meshPartIn->faceList.reserve (M_numFaces);
991 
992  UInt stride = currentCount[1];
993  if (! M_transposeInFile)
994  {
995  for (UInt j = 0; j < M_numFaces; ++j)
996  {
997  pf = & (M_meshPartIn->addFace (false) );
998  pf->replaceFlag (
999  static_cast<flag_Type> (M_uintBuffer[ (6 + M_faceNodes)
1000  * stride + j]) );
1001  pf->setId (M_uintBuffer[ (M_faceNodes + 1) * stride + j]);
1002  pf->firstAdjacentElementIdentity() =
1003  M_uintBuffer[ (M_faceNodes + 2) * stride + j];
1004  pf->secondAdjacentElementIdentity() =
1005  M_uintBuffer[ (M_faceNodes + 3) * stride + j];
1006  pf->firstAdjacentElementPosition() =
1007  M_uintBuffer[ (M_faceNodes + 4) * stride + j];
1008  pf->secondAdjacentElementPosition() =
1009  M_uintBuffer[ (M_faceNodes + 5) * stride + j];
1010  pf->setMarkerID (M_uintBuffer[M_faceNodes * stride + j]);
1011  for (UInt k = 0; k < M_faceNodes; ++k)
1012  {
1013  pf->setPoint (k, M_meshPartIn->point (
1014  M_uintBuffer[k * stride + j]) );
1015  }
1016  }
1017  }
1018  else
1019  {
1020  for (UInt j = 0; j < M_numFaces; ++j)
1021  {
1022  pf = & (M_meshPartIn->addFace (false) );
1023  pf->replaceFlag (
1024  static_cast<flag_Type> (M_uintBuffer[stride * j
1025  + M_faceNodes + 6]) );
1026  pf->setId (M_uintBuffer[stride * j + M_faceNodes + 1]);
1027  pf->firstAdjacentElementIdentity() =
1028  M_uintBuffer[stride * j + M_faceNodes + 2];
1029  pf->secondAdjacentElementIdentity() =
1030  M_uintBuffer[stride * j + M_faceNodes + 3];
1031  pf->firstAdjacentElementPosition() =
1032  M_uintBuffer[stride * j + M_faceNodes + 4];
1033  pf->secondAdjacentElementPosition() =
1034  M_uintBuffer[stride * j + M_faceNodes + 5];
1035  pf->setMarkerID (M_uintBuffer[ (7 + M_faceNodes) * j + M_faceNodes]);
1036  for (UInt k = 0; k < M_faceNodes; ++k)
1037  {
1038  pf->setPoint (k, M_meshPartIn->point (
1039  M_uintBuffer[stride * j + k]) );
1040  }
1041  }
1042  }
1043 
1044  M_meshPartIn->setLinkSwitch ("HAS_ALL_FACETS");
1045  M_meshPartIn->setLinkSwitch ("FACETS_HAVE_ADIACENCY");
1046 }
1047 
1048 template<typename MeshType>
1049 void PartitionIO<MeshType>::readElements()
1050 {
1051  // Read mesh elements (N = number of parts)
1052  // Read a ((3 + num_element_points) * N) x max_num_elements table of int
1053  hsize_t currentSpaceDims[2];
1054  hsize_t currentCount[2];
1055  hsize_t currentOffset[2];
1056 
1057  M_HDF5IO.openTable ("elements", currentSpaceDims);
1058 
1059  if (! M_transposeInFile)
1060  {
1061  currentCount[0] = 3 + M_elementNodes;
1062  currentCount[1] = currentSpaceDims[1];
1063  currentOffset[0] = currentCount[0] * M_myRank;
1064  currentOffset[1] = 0;
1065  }
1066  else
1067  {
1068  currentCount[0] = currentSpaceDims[0];
1069  currentCount[1] = 3 + M_elementNodes;
1070  currentOffset[0] = 0;
1071  currentOffset[1] = currentCount[1] * M_myRank;
1072  }
1073 
1074  M_uintBuffer.resize (currentCount[0] * currentCount[1], 0);
1075  M_HDF5IO.read ("elements", H5T_NATIVE_UINT, currentCount, currentOffset,
1076  &M_uintBuffer[0]);
1077 
1078  M_HDF5IO.closeTable ("elements");
1079 
1080  M_meshPartIn->volumeList.reserve (M_numElements);
1081 
1082  typename MeshType::volume_Type* pv = 0;
1083 
1084  UInt stride = currentCount[1];
1085  if (! M_transposeInFile)
1086  {
1087  for (UInt j = 0; j < M_numElements; ++j)
1088  {
1089  pv = & (M_meshPartIn->addVolume() );
1090  pv->replaceFlag (
1091  static_cast<flag_Type> (M_uintBuffer[ (M_elementNodes + 2) * stride + j]) );
1092  pv->setId (M_uintBuffer[ (M_elementNodes + 1) * stride + j]);
1093  pv->setLocalId (j);
1094  for (UInt k = 0; k < M_elementNodes; ++k)
1095  {
1096  pv->setPoint (k, M_meshPartIn->point (
1097  M_uintBuffer[k * stride + j]) );
1098  }
1099  pv->setMarkerID (M_uintBuffer[M_elementNodes * stride + j]);
1100  }
1101  }
1102  else
1103  {
1104  for (UInt j = 0; j < M_numElements; ++j)
1105  {
1106  pv = & (M_meshPartIn->addVolume() );
1107  pv->replaceFlag (
1108  static_cast<flag_Type> (M_uintBuffer[stride * j + M_elementNodes + 2]) );
1109  pv->setId (M_uintBuffer[stride * j + M_elementNodes + 1]);
1110  pv->setLocalId (j);
1111  for (UInt k = 0; k < M_elementNodes; ++k)
1112  {
1113  pv->setPoint (k, M_meshPartIn->point (
1114  M_uintBuffer[stride * j + k]) );
1115  }
1116  pv->setMarkerID (M_uintBuffer[stride * j + M_elementNodes]);
1117  }
1118  }
1119 
1120  M_meshPartIn->updateElementEdges (false, false);
1121  M_meshPartIn->updateElementFaces (false, false);
1122 }
1123 
1124 } /* namespace LifeV */
1125 
1126 #endif /* HAVE_MPI */
1127 #endif /* LIFEV_HAS_HDF5 */
1128 #endif /* PARTITION_IO_H_ */