* fixed bug in h5bl_defin3dchunkdims call that was using variables addresses ins

* added new MultiBlock module that is used for efficiently loading regular
rectilinear grid blocks (using chunking) and handling ghost zones in a
distributed-memory environment
** still need to add the "halo exchange" routine for reshuffling ghost regions
** performed some basic testing of read/write functionality

~Mark
This commit is contained in:
Marc Howison
2009-06-24 18:11:39 +00:00
parent 3d1ed0e92a
commit 0e853656cd
20 changed files with 1605 additions and 71 deletions
+8
View File
@@ -33,6 +33,13 @@ src/H5BlockReadWrite.h -text
src/H5BlockReadWriteF.c -text
src/H5BlockReadWriteF90.inc -text
src/H5BlockTypes.h -text
src/H5MultiBlock.c -text
src/H5MultiBlock.h -text
src/H5MultiBlockErrors.h -text
src/H5MultiBlockPrivate.h -text
src/H5MultiBlockReadWrite.c -text
src/H5MultiBlockReadWrite.h -text
src/H5MultiBlockTypes.h -text
src/H5Part.c -text
src/H5Part.h -text
src/H5PartErrors.h -text
@@ -44,6 +51,7 @@ src/Makefile.am -text
src/TestUnderscore.f -text
src/TestUnderscoreC.c -text
src/generate-h5bl-readwrite.py -text
src/generate-h5multi-readwrite.py -text
test/Bench.c -text
test/BlockTestSpecs.txt -text
test/H5BlockDissolveGhosts.c -text
+37 -36
View File
@@ -182,6 +182,11 @@ _H5Block_close (
if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR;
b->memshape = -1;
}
if ( b->create_prop != H5P_DEFAULT ) {
herr = H5Pclose ( b->create_prop );
if ( herr < 0 ) return HANDLE_H5P_CLOSE_ERR ("create_prop");
b->create_prop = H5P_DEFAULT;
}
free ( f->block );
f->block = NULL;
f->close_block = NULL;
@@ -674,7 +679,7 @@ _dissolve_ghostzones (
\internal
*/
h5part_int64_t
static h5part_int64_t
_release_hyperslab (
H5PartFile *f /*!< IN: file handle */
) {
@@ -720,7 +725,7 @@ H5BlockDefine3DFieldLayout(
) {
SET_FNAME ( "H5BlockDefine3DFieldLayout" );
INIT( f );
BLOCK_INIT( f );
struct H5BlockStruct *b = f->block;
struct H5BlockPartition *p = &b->user_layout[f->myproc];
@@ -731,7 +736,7 @@ H5BlockDefine3DFieldLayout(
p->k_start = k_start;
p->k_end = k_end;
_normalize_partition( p );
_normalize_partition ( p );
h5part_int64_t herr = _allgather ( f );
if ( herr < 0 ) return HANDLE_MPI_ALLGATHER_ERR;
@@ -760,13 +765,13 @@ H5BlockDefine3DFieldLayout(
h5part_int64_t
H5BlockDefine3DChunkDims(
H5PartFile *f, /*!< IN: File handle */
const h5part_int64_t i, /*!< IN: size of \c i */
const h5part_int64_t j, /*!< IN: size of \c j */
const h5part_int64_t k /*!< IN: size of \c k */
const h5part_int64_t i, /*!< IN: size of \c i */
const h5part_int64_t j, /*!< IN: size of \c j */
const h5part_int64_t k /*!< IN: size of \c k */
) {
SET_FNAME ( "H5BlockDefine3DChunkDims" );
INIT( f );
BLOCK_INIT( f );
struct H5BlockStruct *b = f->block;
@@ -782,6 +787,8 @@ H5BlockDefine3DChunkDims(
(long long)b->chunk[0] );
b->create_prop = H5Pcreate (H5P_DATASET_CREATE);
if (b->create_prop < 0) return HANDLE_H5P_CREATE_ERR;
herr_t herr = H5Pset_chunk ( b->create_prop, 3, b->chunk );
if ( herr < 0 ) return HANDLE_H5P_SET_CHUNK_ERR;
@@ -804,7 +811,7 @@ H5BlockGet3DChunkDims(
) {
SET_FNAME ( "H5BlockGet3DChunkDims" );
INIT( f );
BLOCK_INIT( f );
struct H5BlockStruct *b = f->block;
@@ -869,7 +876,7 @@ H5Block3dGetPartitionOfProc (
) {
SET_FNAME ( "H5Block3dGetProcOf" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_LAYOUT ( f );
if ( ( proc < 0 ) || ( proc >= f->nprocs ) )
@@ -909,7 +916,7 @@ H5Block3dGetReducedPartitionOfProc (
) {
SET_FNAME ( "H5Block3dGetProcOf" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_LAYOUT ( f );
if ( ( proc < 0 ) || ( proc >= f->nprocs ) )
@@ -945,7 +952,7 @@ H5Block3dGetProcOf (
) {
SET_FNAME ( "H5Block3dGetProcOf" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_LAYOUT ( f );
struct H5BlockPartition *layout = f->block->write_layout;
@@ -1060,8 +1067,8 @@ _H5Block_close_field_group (
\return \c H5PART_SUCCESS or error code
*/
static h5part_int64_t
_select_hyperslab_for_reading (
h5part_int64_t
_H5Block_select_hyperslab_for_reading (
H5PartFile *f, /*!< IN: file handle */
hid_t dataset
) {
@@ -1155,6 +1162,7 @@ _H5Block_read_data (
hid_t type /*!< IN: data type */
) {
h5part_int64_t herr;
struct H5BlockStruct *b = f->block;
#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 8
@@ -1164,7 +1172,7 @@ _H5Block_read_data (
#endif
if ( dataset_id < 0 ) return HANDLE_H5D_OPEN_ERR ( name );
h5part_int64_t herr = _select_hyperslab_for_reading ( f, dataset_id );
herr = _H5Block_select_hyperslab_for_reading ( f, dataset_id );
if ( herr < 0 ) return herr;
herr = H5Dread (
@@ -1172,7 +1180,7 @@ _H5Block_read_data (
type,
f->block->memshape,
f->block->diskshape,
H5P_DEFAULT,
f->xfer_prop,
data );
if ( herr < 0 ) return HANDLE_H5D_READ_ERR ( name, f->timestep );
@@ -1400,7 +1408,6 @@ _H5Block_write_data (
herr_t herr;
hid_t dataset;
hid_t create_prop = H5P_DEFAULT;
struct H5BlockStruct *b = f->block;
#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 8
@@ -1420,7 +1427,6 @@ _H5Block_write_data (
b->shape,
b->create_prop );
#endif
if ( dataset < 0 ) return HANDLE_H5D_CREATE_ERR ( name, f->timestep );
herr = H5Dwrite (
@@ -1435,11 +1441,6 @@ _H5Block_write_data (
herr = H5Dclose ( dataset );
if ( herr < 0 ) return HANDLE_H5D_CLOSE_ERR;
if ( create_prop != H5P_DEFAULT ) {
herr = H5Pclose ( create_prop );
if ( herr < 0 ) return HANDLE_H5P_CLOSE_ERR ( "create_prop" );
}
return H5PART_SUCCESS;
}
@@ -1458,7 +1459,7 @@ H5BlockGetNumFields (
) {
SET_FNAME ( "H5BlockGetNumFields" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
if ( ! _H5Part_have_group ( f->timegroup, H5BLOCK_GROUPNAME_BLOCK ) )
@@ -1558,7 +1559,7 @@ H5BlockGetFieldInfo (
) {
SET_FNAME ( "H5BlockGetFieldInfo" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
h5part_int64_t herr = _H5Part_get_object_name (
@@ -1591,7 +1592,7 @@ H5BlockGetFieldInfoByName (
) {
SET_FNAME ( "H5BlockGetFieldInfo" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
return _get_field_info (
@@ -1620,7 +1621,7 @@ _write_field_attrib (
h5part_int64_t herr = _H5Block_open_field_group ( f, field_name );
if ( herr < 0 ) return herr;
_H5Part_write_attrib (
herr = _H5Part_write_attrib (
f->block->field_group_id,
attrib_name,
attrib_type,
@@ -1653,7 +1654,7 @@ H5BlockWriteFieldAttrib (
) {
SET_FNAME ( "H5BlockWriteFieldAttrib" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE( f );
CHECK_TIMEGROUP( f );
@@ -1681,7 +1682,7 @@ H5BlockWriteFieldAttribString (
) {
SET_FNAME ( "H5BlockWriteFieldAttribString" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE( f );
CHECK_TIMEGROUP( f );
@@ -1706,7 +1707,7 @@ H5BlockGetNumFieldAttribs (
) {
SET_FNAME ( "H5BlockGetNumFieldAttribs" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
h5part_int64_t herr = _H5Block_open_field_group ( f, field_name );
@@ -1744,7 +1745,7 @@ H5BlockGetFieldAttribInfo (
) {
SET_FNAME ( "H5BlockGetFieldAttribInfo" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
h5part_int64_t herr = _H5Block_open_field_group ( f, field_name );
@@ -1815,7 +1816,7 @@ H5BlockReadFieldAttrib (
) {
SET_FNAME ( "H5PartReadFieldAttrib" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
return _read_field_attrib (
@@ -1840,7 +1841,7 @@ H5Block3dGetFieldOrigin (
) {
SET_FNAME ( "H5BlockSetFieldOrigin" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
h5part_float64_t origin[3];
@@ -1874,7 +1875,7 @@ H5Block3dSetFieldOrigin (
) {
SET_FNAME ( "H5BlockSetFieldOrigin" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE( f );
CHECK_TIMEGROUP( f );
@@ -1906,7 +1907,7 @@ H5Block3dGetFieldSpacing (
) {
SET_FNAME ( "H5BlockGetFieldSpacing" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
h5part_float64_t spacing[3];
@@ -1940,7 +1941,7 @@ H5Block3dSetFieldSpacing (
) {
SET_FNAME ( "H5BlockSetFieldSpacing" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE( f );
CHECK_TIMEGROUP( f );
@@ -1970,7 +1971,7 @@ H5BlockHasFieldData (
) {
SET_FNAME ( "H5BlockHasFieldData" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP( f );
if ( ! _H5Part_have_group ( f->timegroup, H5BLOCK_GROUPNAME_BLOCK ) ) {
+1
View File
@@ -34,6 +34,7 @@
_H5Part_get_funcname(), \
H5PART_ERR_INVAL, \
"Group \"%s\" already exists", name )
#define HANDLE_H5S_CREATE_SIMPLE_3D_ERR( dims ) \
(*_err_handler) ( \
_H5Part_get_funcname(), \
+4 -4
View File
@@ -99,14 +99,14 @@ h5bl_define3dlayout (
h5part_int64_t
h5bl_define3dchunkdims (
h5part_int64_t *f,
const h5part_int64_t i,
const h5part_int64_t j,
const h5part_int64_t k
const h5part_int64_t *i,
const h5part_int64_t *j,
const h5part_int64_t *k
) {
H5PartFile *filehandle = (H5PartFile*)(size_t)*f;
return H5BlockDefine3DChunkDims ( filehandle, i, j, k );
return H5BlockDefine3DChunkDims ( filehandle, *i, *j, *k );
}
h5part_int64_t
+7 -1
View File
@@ -3,7 +3,7 @@
#define H5BLOCK_GROUPNAME_BLOCK "Block"
#define INIT( f ) { \
#define BLOCK_INIT( f ) { \
h5part_int64_t herr = _H5Block_init ( f ); \
if ( herr < 0 ) return herr; \
}
@@ -34,6 +34,12 @@ _H5Block_create_field_group (
H5PartFile *f,
const char *name
);
h5part_int64_t
_H5Block_select_hyperslab_for_reading (
H5PartFile *f,
hid_t dataset
);
h5part_int64_t
_H5Block_write_data (
+16 -16
View File
@@ -31,7 +31,7 @@ H5Block3dWriteScalarFieldFloat64 (
) {
SET_FNAME ( "H5Block3dWriteScalarFieldFloat64" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -67,7 +67,7 @@ H5Block3dReadScalarFieldFloat64 (
) {
SET_FNAME ( "H5Block3dReadScalarFieldFloat64" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -106,7 +106,7 @@ H5Block3dWrite3dVectorFieldFloat64 (
) {
SET_FNAME ( "H5Block3dWrite3dVectorFieldFloat64" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -150,7 +150,7 @@ H5Block3dRead3dVectorFieldFloat64 (
) {
SET_FNAME ( "H5Block3dRead3dVectorFieldFloat64" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -189,7 +189,7 @@ H5Block3dWriteScalarFieldFloat32 (
) {
SET_FNAME ( "H5Block3dWriteScalarFieldFloat32" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -225,7 +225,7 @@ H5Block3dReadScalarFieldFloat32 (
) {
SET_FNAME ( "H5Block3dReadScalarFieldFloat32" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -264,7 +264,7 @@ H5Block3dWrite3dVectorFieldFloat32 (
) {
SET_FNAME ( "H5Block3dWrite3dVectorFieldFloat32" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -308,7 +308,7 @@ H5Block3dRead3dVectorFieldFloat32 (
) {
SET_FNAME ( "H5Block3dRead3dVectorFieldFloat32" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -347,7 +347,7 @@ H5Block3dWriteScalarFieldInt64 (
) {
SET_FNAME ( "H5Block3dWriteScalarFieldInt64" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -383,7 +383,7 @@ H5Block3dReadScalarFieldInt64 (
) {
SET_FNAME ( "H5Block3dReadScalarFieldInt64" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -422,7 +422,7 @@ H5Block3dWrite3dVectorFieldInt64 (
) {
SET_FNAME ( "H5Block3dWrite3dVectorFieldInt64" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -466,7 +466,7 @@ H5Block3dRead3dVectorFieldInt64 (
) {
SET_FNAME ( "H5Block3dRead3dVectorFieldInt64" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -505,7 +505,7 @@ H5Block3dWriteScalarFieldInt32 (
) {
SET_FNAME ( "H5Block3dWriteScalarFieldInt32" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -541,7 +541,7 @@ H5Block3dReadScalarFieldInt32 (
) {
SET_FNAME ( "H5Block3dReadScalarFieldInt32" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -580,7 +580,7 @@ H5Block3dWrite3dVectorFieldInt32 (
) {
SET_FNAME ( "H5Block3dWrite3dVectorFieldInt32" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -624,7 +624,7 @@ H5Block3dRead3dVectorFieldInt32 (
) {
SET_FNAME ( "H5Block3dRead3dVectorFieldInt32" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
+779
View File
@@ -0,0 +1,779 @@
/*!
\defgroup h5multiblock_c_api H5MultiBlock C API
This package includes C code for writing and reading 3D datasets intended
for distributed memory applications. The underlying file format is H5Part,
a simple data storage schema and API derived from HDF5. In particular, we
use the H5Block subset of H5Part for managing 3D field data. To achieve large
contiguous reads and writes, the datasets use HDF5's chunking mechanism to
reorder the layout on disk such that local subfields (or "blocks") of the
3D field are stored contiguously (as opposed to storing an entire column
contiguously, as in the Fortran column-major layout for an array). We refer
to this chunked layout as "multiblock" and the column-major layout as
"uniblock." Multiblocked datasets exhibit the following constraints:
* All blocks must be the same size (a requirement of the HDF5 chunking
mechanism).
* The block dimensions must divide the field dimensions, to prevent fringe
data that will lower performance by interfering with contiguous I/O
operations.
* For load-balancing purposes, the total number of blocks that the field
is decomposed into must be a multiple of the number of nodes in the
distributed system. (For ease of implementation, we require that the
number of blocks equal the number of nodes.)
*/
/*!
\internal
\defgroup h5multiblock_static H5MultiBlock Static
*/
/*!
\internal
\defgroup h5multiblock_private H5MultiBlock Private
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <hdf5.h>
#include "H5Part.h"
#include "H5PartErrors.h"
#include "H5PartPrivate.h"
#include "H5Block.h"
#include "H5BlockTypes.h"
#include "H5BlockErrors.h"
#include "H5BlockPrivate.h"
#include "H5MultiBlock.h"
#include "H5MultiBlockTypes.h"
#include "H5MultiBlockErrors.h"
#include "H5MultiBlockPrivate.h"
#ifdef PARALLEL_IO
/*******************************************************************************
* Static functions
*******************************************************************************/
/*!
\ingroup h5multiblock_static
\internal
Check whether \c f points to a valid file handle.
\return H5PART_SUCCESS or error code
*/
static h5part_int64_t
_file_is_valid (
const H5PartFile *f /*!< IN: file handle */
) {
if ( f == NULL )
return H5PART_ERR_BADFD;
if ( f->file == 0 )
return H5PART_ERR_BADFD;
if ( f->block == NULL )
return H5PART_ERR_BADFD;
if ( f->multiblock == NULL )
return H5PART_ERR_BADFD;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_static
\internal
Gets the block decomposition and offsets.
\return H5PART_SUCCESS or error code
*/
static h5part_int64_t
_get_decomp_and_offsets (
const H5PartFile *f /*!< IN: file handle */
) {
h5part_int64_t i, j, k;
h5part_int64_t nblocks;
struct H5MultiBlockStruct *mb = f->multiblock;
mb->decomp[0] = mb->field_dims[0] / mb->block_dims[0];
mb->decomp[1] = mb->field_dims[1] / mb->block_dims[1];
mb->decomp[2] = mb->field_dims[2] / mb->block_dims[2];
_H5Part_print_debug ("PROC[%d]: Block decomposition: (%ld,%ld,%ld)",
f->myproc,
mb->decomp[0],
mb->decomp[1],
mb->decomp[2] );
i = f->myproc % mb->decomp[0];
j = (f->myproc / mb->decomp[0]) % mb->decomp[1];
k = f->myproc / (mb->decomp[0] * mb->decomp[1]);
/* keep track of blocks that border the edges of the field */
if (i == 0) mb->field_edges | H5MB_EDGE_X0;
if (i == mb->decomp[0] - 1) mb->field_edges | H5MB_EDGE_X1;
if (j == 0) mb->field_edges | H5MB_EDGE_Y0;
if (j == mb->decomp[1] - 1) mb->field_edges | H5MB_EDGE_Y1;
if (j == 0) mb->field_edges | H5MB_EDGE_Z0;
if (j == mb->decomp[2] - 1) mb->field_edges | H5MB_EDGE_Z1;
mb->offsets[0] = i * mb->block_dims[0];
mb->offsets[1] = j * mb->block_dims[1];
mb->offsets[2] = k * mb->block_dims[2];
_H5Part_print_debug ("PROC[%d]: Block offsets: (%ld,%ld,%ld)",
f->myproc,
mb->offsets[0],
mb->offsets[1],
mb->offsets[0] );
nblocks = mb->decomp[0] * mb->decomp[1] * mb->decomp[2];
if (f->myproc == 0) {
_H5Part_print_info ("Number of blocks: %ld", nblocks);
}
if (nblocks != f->nprocs) {
return HANDLE_H5PART_BLOCK_DECOMP_ERR;
}
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_static
\internal
Calculates an integer \c divisor of \c m that is >= the \c n root of \c m.
Used for finding block decompositions for an arbitrary number of processors.
\return \c divisor
*/
static int
_nth_root_int_divisor (const int m, const int n)
{
int i, root;
double p;
p = 1.0 / (double) n;
root = (int) ceil ( pow ((double) m, p) );
for (i=root; i<=m; i++)
{
if (m % i == 0) return i;
}
return i;
}
/*!
\ingroup h5multiblock_static
\internal
Allocates a block using the dimensions read from the file and the halo
radii specified by the user.
\return H5PART_SUCCESS or error code
*/
static h5part_int64_t
_alloc_block (
const H5PartFile *f, /*!< IN: file handle */
char **data, /*!< IN/OUT: buffer to alloc */
hid_t type /*!< IN: HDF5 datatype of buffer */
) {
char *buffer;
size_t datasize;
size_t nelems;
struct H5MultiBlockStruct *mb = f->multiblock;
/* size of datatype */
datasize = H5Tget_size ( type );
/* number of elements */
nelems = mb->block_dims[0] + 2*mb->halo_radii[0];
nelems *= mb->block_dims[1] + 2*mb->halo_radii[1];
nelems *= mb->block_dims[2] + 2*mb->halo_radii[2];
buffer = (char*) malloc ( nelems * datasize );
if ( ! buffer ) return HANDLE_H5PART_NOMEM_ERR;
*data = buffer;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_static
\internal
Takes a contiguous buffer of data and rearranges it in place to add padding
with \c radius layers. Assumes that \c buffer is already large enough to
perform this operation.
\return H5PART_SUCCESS or error code
*/
static h5part_int64_t
_pad_block (
const H5PartFile *f, /*!< IN: file handle */
char *data, /*!< IN/OUT: buffer to pad */
hid_t type /*!< IN: HDF5 datatype of buffer */
) {
size_t datasize;
h5part_int64_t j, k;
h5part_int64_t iDst, iSrc;
h5part_int64_t xSize, xySize;
h5part_int64_t hxSize, hxySize;
h5part_int64_t hxInset;
struct H5MultiBlockStruct *mb = f->multiblock;
/* size of datatype */
datasize = H5Tget_size ( type );
/* size of row in original block */
xSize = mb->block_dims[0] * datasize;
/* size of slab in original block */
xySize = xSize * mb->block_dims[1];
/* size of row/slab with halo regions */
hxSize = (mb->block_dims[0] + 2*mb->halo_radii[0]) * datasize;
hxySize = hxSize * (mb->block_dims[1] + 2*mb->halo_radii[1]);
/* inset of row in halo region */
hxInset = mb->halo_radii[0] * datasize;
for (k=(mb->block_dims[2]-1);k>=0;k--)
{
for (j=(mb->block_dims[1]-1);j>=0;j--)
{
iSrc = k*xySize + j*xSize;
iDst = (k + mb->halo_radii[2]) * hxySize +
(j + mb->halo_radii[1]) * hxSize +
hxInset;
memcpy ( data + iDst, data + iSrc, xSize );
}
}
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_static
\internal
Exchanges halo regions among neighboring blocks using MPI.
\return H5PART_SUCCESS or error code
*/
static h5part_int64_t
_halo_exchange (
const H5PartFile *f, /*!< IN: file handle */
char *data, /*!< IN/OUT: local buffer */
hid_t type /*!< IN: HDF5 datatype of buffer */
) {
return H5PART_SUCCESS;
}
/*******************************************************************************
* Private functions
*******************************************************************************/
/*!
\ingroup h5multiblock_private
\internal
Initialize H5MultiBlock internal structure.
\return H5PART_SUCCESS or error code
*/
h5part_int64_t
_H5MultiBlock_init (
H5PartFile *f /*!< IN: file handle */
) {
struct H5MultiBlockStruct *mb;
BLOCK_INIT( f );
if (f->multiblock != NULL) return H5PART_SUCCESS;
f->multiblock =
(struct H5MultiBlockStruct*) malloc( sizeof (*f->multiblock) );
if ( f->multiblock == NULL ) {
return HANDLE_H5PART_NOMEM_ERR;
}
mb = f->multiblock;
mb->field_edges = 0;
mb->halo = 0;
mb->read = 0;
mb->have_decomp = 0;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_private
\internal
Free H5MultiBlock internal struct;
\return H5PART_SUCCESS or error code
*/
h5part_int64_t
_H5MultiBlock_close (
H5PartFile *f /*!< IN: file handle */
) {
free ( f->multiblock );
f->multiblock = NULL;
f->close_multiblock = NULL;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_private
\internal
Read a multiblock field \c name into the buffer starting at \c data
using the current time-step and the block decomposition and dimensions
defined in the file.
\return H5PART_SUCCESS or error code
*/
h5part_int64_t
_H5MultiBlock_read_data (
H5PartFile *f, /*!< IN: file handle */
const char *field_name, /*!< IN: Name of field */
char **data, /*!< OUT: ptr to read buffer ptr*/
hid_t type /*!< IN: HDF5 datatype of buffer */
) {
MULTIBLOCK_INIT( f );
hid_t dataset_id;
hid_t dataspace_id;
int rank;
h5part_int64_t herr;
struct H5BlockStruct *b = f->block;
struct H5MultiBlockStruct *mb = f->multiblock;
char * const fname = _H5Part_get_funcname();
herr = _H5Block_open_field_group ( f, field_name );
if ( herr < 0 ) return herr;
#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 8
dataset_id = H5Dopen2 ( b->field_group_id, "0", H5P_DEFAULT );
#else
dataset_id = H5Dopen ( b->field_group_id, "0" );
#endif
if ( dataset_id < 0 ) return HANDLE_H5D_OPEN_ERR ( "0" );
/* read block dimensions from field attribute */
herr = _H5Part_read_attrib (
b->field_group_id,
H5MULTIBLOCK_ATTR_NAME,
mb->block_dims );
if ( herr < 0 ) return herr;
_H5Part_print_debug ("PROC[%d]: Block dimensions: (%ld,%ld,%ld)",
f->myproc,
mb->block_dims[0],
mb->block_dims[1],
mb->block_dims[2] );
dataspace_id = H5Dget_space ( dataset_id );
if ( dataspace_id < 0 ) return HANDLE_H5D_GET_SPACE_ERR;
rank = H5Sget_simple_extent_dims (
dataspace_id,
(hsize_t*)mb->field_dims,
NULL );
if ( rank < 0 ) return HANDLE_H5S_GET_SIMPLE_EXTENT_DIMS_ERR;
if ( rank != 3 ) return HANDLE_H5PART_DATASET_RANK_ERR ( rank, 3 );
herr = _alloc_block ( f, data, type );
if ( herr < 0 ) return herr;
herr = _get_decomp_and_offsets ( f );
if ( herr < 0 ) return herr;
mb->have_decomp = 1;
herr = H5BlockDefine3DFieldLayout ( f,
mb->offsets[0], mb->offsets[0] + mb->block_dims[0] - 1,
mb->offsets[1], mb->offsets[1] + mb->block_dims[1] - 1,
mb->offsets[2], mb->offsets[2] + mb->block_dims[2] - 1);
if ( herr < 0 ) return herr;
_H5Part_set_funcname ( fname );
herr = _H5Block_select_hyperslab_for_reading ( f, dataset_id );
if ( herr < 0 ) return herr;
herr = H5Dread (
dataset_id,
type,
f->block->memshape,
f->block->diskshape,
f->xfer_prop,
*data );
if ( herr < 0 ) return HANDLE_H5D_READ_ERR ( field_name, f->timestep );
herr = H5Dclose ( dataset_id );
if ( herr < 0 ) return HANDLE_H5D_CLOSE_ERR;
herr = _H5Block_close_field_group ( f );
if ( herr < 0 ) return herr;
if ( mb->halo ) {
_pad_block ( f, *data, type );
_halo_exchange ( f, *data, type );
}
mb->read = 1;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_private
\internal
Write a multiblock field \c name from the buffer starting at \c data
to the current time-step using the defined block decomposition and dimensions.
\return H5PART_SUCCESS or error code
*/
h5part_int64_t
_H5MultiBlock_write_data (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to write */
const void* data, /*!< IN: data buffer */
hid_t type /*!< IN: HDF5 datatype */
) {
MULTIBLOCK_INIT( f );
CHECK_WRITABLE_MODE( f );
CHECK_TIMEGROUP( f );
CHECK_DECOMP ( f );
hid_t dataset;
h5part_int64_t herr;
struct H5BlockStruct *b = f->block;
struct H5MultiBlockStruct *mb = f->multiblock;
char * const fname = _H5Part_get_funcname();
herr = H5BlockDefine3DFieldLayout ( f,
mb->offsets[0], mb->offsets[0] + mb->block_dims[0] - 1,
mb->offsets[1], mb->offsets[1] + mb->block_dims[1] - 1,
mb->offsets[2], mb->offsets[2] + mb->block_dims[2] - 1);
if ( herr < 0 ) return herr;
herr = H5BlockDefine3DChunkDims( f,
mb->block_dims[0],
mb->block_dims[1],
mb->block_dims[2]);
if ( herr < 0 ) return herr;
_H5Part_set_funcname ( fname );
herr = _H5Block_create_field_group ( f, name );
if ( herr < 0 ) return herr;
#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 8
dataset = H5Dcreate2 (
b->field_group_id,
"0",
type,
b->shape,
H5P_DEFAULT,
b->create_prop,
H5P_DEFAULT );
#else
dataset = H5Dcreate (
b->field_group_id,
"0",
type,
b->shape,
b->create_prop );
#endif
if ( dataset < 0 ) return HANDLE_H5D_CREATE_ERR ( name, f->timestep );
herr = H5Dwrite (
dataset,
type,
b->memshape,
b->diskshape,
f->xfer_prop,
data );
if ( herr < 0 ) return HANDLE_H5D_WRITE_ERR ( name, f->timestep );
herr = H5Dclose ( dataset );
if ( herr < 0 ) return HANDLE_H5D_CLOSE_ERR;
/* write out the block dimensions to a special field attribute */
herr = _H5Part_write_attrib (
f->block->field_group_id,
H5MULTIBLOCK_ATTR_NAME,
H5T_NATIVE_INT64,
mb->block_dims,
3 );
if ( herr < 0 ) return herr;
herr = _H5Block_close_field_group ( f );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
/*******************************************************************************
* Public API
*******************************************************************************/
/*!
\ingroup h5multiblock_c_api
Define the radius for halo exchanges between the blocks. Blocks on the edges
of the field will be padded with zero values out to the radius.
\return \c H5PART_SUCCESS on success
*/
h5part_int64_t
H5MultiBlock3dDefineRadius (
H5PartFile *f, /* IN: file handle */
const h5part_int64_t r /* IN: radius for i, j and k directions*/
) {
SET_FNAME ( "H5MultiBlock3dDefineRadius" );
MULTIBLOCK_INIT( f );
struct H5MultiBlockStruct *mb = f->multiblock;
mb->halo_radii[0] =
mb->halo_radii[1] =
mb->halo_radii[2] = r;
mb->halo = 1;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Define the radii for halo exchanges between the blocks. Blocks on the edges
of the field will be padded with zero values out to the radius.
Different radii can be set for each direction.
\return \c H5PART_SUCCESS on success
*/
h5part_int64_t
H5MultiBlock3dDefineRadii (
H5PartFile *f, /* IN: file handle */
const h5part_int64_t ri, /* IN: radius for i direction */
const h5part_int64_t rj, /* IN: radius for j direction */
const h5part_int64_t rk /* IN: radius for k direction */
) {
SET_FNAME ( "H5MultiBlock3dDefineRadii" );
MULTIBLOCK_INIT( f );
struct H5MultiBlockStruct *mb = f->multiblock;
mb->halo_radii[0] = rk;
mb->halo_radii[1] = rj;
mb->halo_radii[2] = ri;
mb->halo = 1;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Define the field and block dimensions for writing.
\return \c H5PART_SUCCESS on success
\c H5PART_ERR_INVAL if block dims do not divide field dims
*/
h5part_int64_t
H5MultiBlock3dDefineDims (
H5PartFile *f, /* IN: file handle */
const h5part_int64_t *field_dims, /* IN: field dimensions */
const h5part_int64_t *block_dims /* IN: block dimensions */
) {
SET_FNAME ( "H5MultiBlock3dDefineDims" );
MULTIBLOCK_INIT ( f );
struct H5MultiBlockStruct *mb = f->multiblock;
mb->field_dims[0] = field_dims[0];
mb->field_dims[1] = field_dims[1];
mb->field_dims[2] = field_dims[2];
mb->block_dims[0] = block_dims[0];
mb->block_dims[1] = block_dims[1];
mb->block_dims[2] = block_dims[2];
h5part_int64_t herr = _get_decomp_and_offsets ( f );
if ( herr < 0 ) return H5PART_ERR_INVAL;
mb->have_decomp = 1;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Returns the field dimensions of the last field that was read.
\return \c H5PART_SUCCESS on success<br>
\c H5PART_ERR_INVAL if no field has been read yet
*/
h5part_int64_t
H5MultiBlock3dGetFieldDims(
H5PartFile *f,
h5part_int64_t *dims
) {
SET_FNAME ( "H5MultiBlock3dGetFieldDims" );
MULTIBLOCK_INIT ( f );
struct H5MultiBlockStruct *mb = f->multiblock;
if ( ! mb->read ) return H5PART_ERR_INVAL;
dims[0] = mb->field_dims[0];
dims[1] = mb->field_dims[1];
dims[2] = mb->field_dims[2];
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Returns the block dimensions of the last field that was read.
\return \c H5PART_SUCCESS on success<br>
\c H5PART_ERR_INVAL if no field has been read yet
*/
h5part_int64_t
H5MultiBlock3dGetBlockDims(
H5PartFile *f, /* IN: file handle */
const char *field_name, /* IN: field name */
h5part_int64_t *dims /* OUT: block dimensions */
) {
SET_FNAME ( "H5MultiBlock3dGetBlockDims" );
MULTIBLOCK_INIT ( f );
struct H5MultiBlockStruct *mb = f->multiblock;
if ( ! mb->read ) return H5PART_ERR_INVAL;
dims[0] = mb->block_dims[0];
dims[1] = mb->block_dims[1];
dims[2] = mb->block_dims[2];
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Return the offsets for the block belonging to processor \c proc.
\return \c H5PART_SUCCESS on success<br>
\c H5PART_ERR_INVAL if proc is invalid
*/
h5part_int64_t
H5MultiBlock3dGetOffsetsOfProc (
H5PartFile *f, /* IN: file handle */
const h5part_int64_t proc, /* IN: processor number */
h5part_int64_t *offsets /* OUT: 3d array of offsets */
) {
SET_FNAME ( "H5MultiBlock3dGetOffsetsOfProc" );
MULTIBLOCK_INIT ( f );
if ( ( proc < 0 ) || ( proc >= f->nprocs ) )
return H5PART_ERR_INVAL;
struct H5MultiBlockStruct *mb = f->multiblock;
offsets[0] = mb->offsets[0];
offsets[1] = mb->offsets[1];
offsets[2] = mb->offsets[2];
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Finds a 3D block decomposition for an arbitrary number of processors
\c nprocs.
\return \c H5PART_SUCCESS on success<br>
\c H5PART_ERR_INVAL if the decomp doesn't have \c nprocs blocks
*/
h5part_int64_t
H5MultiBlock3dCalculateDecomp (
const int nprocs, /*!< IN: number of processors/blocks */
h5part_int64_t *decomp /*!< OUT: 3D block decomposition */
) {
decomp[0] = _nth_root_int_divisor (nprocs, 3);
decomp[1] = _nth_root_int_divisor (nprocs / decomp[0], 2);
decomp[2] = nprocs / decomp[0] / decomp[1];
if (decomp[0] * decomp[1] * decomp[2] != nprocs) {
return H5PART_ERR_INVAL;
}
return H5PART_SUCCESS;
}
#endif
+67
View File
@@ -0,0 +1,67 @@
#ifndef __H5MULTIBLOCK_H
#define __H5MULTIBLOCK_H
#ifdef __cplusplus
extern "C" {
#endif
/*!
Include read/write call variants for different data types and
field dimensions.
*/
#include "H5MultiBlockReadWrite.h"
#define H5MULTIBLOCK_ATTR_NAME "__BlockDims__"
h5part_int64_t
H5MultiBlock3dDefineRadius (
H5PartFile *f,
const h5part_int64_t r
);
h5part_int64_t
H5MultiBlock3dDefineRadii (
H5PartFile *f,
const h5part_int64_t ri,
const h5part_int64_t rj,
const h5part_int64_t rk
);
h5part_int64_t
H5MultiBlock3dDefineDims (
H5PartFile *f,
const h5part_int64_t *field_dims,
const h5part_int64_t *block_dims
);
h5part_int64_t
H5MultiBlock3dGetFieldDims(
H5PartFile *f,
h5part_int64_t *dims
);
h5part_int64_t
H5MultiBlock3dGetBlockDims(
H5PartFile *f,
const char *field_name,
h5part_int64_t *dims
);
h5part_int64_t
H5MultiBlock3dGetOffsetsOfProc (
H5PartFile *f,
const h5part_int64_t proc,
h5part_int64_t *offsets
);
h5part_int64_t
H5MultiBlock3dCalculateDecomp (
const int nprocs,
h5part_int64_t *decomp
);
#ifdef __cplusplus
}
#endif
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef __H5MULTIBLOCKERRORS_H
#define __H5MULTIBLOCKERRORS_H
#define _err_handler H5PartGetErrorHandler()
#define CHECK_DECOMP( f ) \
if ( ! f->multiblock->have_decomp ) \
return (*_err_handler) ( \
_H5Part_get_funcname(), \
H5PART_ERR_DECOMP, \
"No dimensions defined." )
#define HANDLE_H5PART_BLOCK_DECOMP_ERR \
(*_err_handler) ( \
_H5Part_get_funcname(), \
H5PART_ERR_DECOMP, \
"Number of blocks does not equal number of procs" );
#endif
+35
View File
@@ -0,0 +1,35 @@
#ifndef __H5MULTIBLOCKPRIVATE_H
#define __H5MULTIBLOCKPRIVATE_H
#define MULTIBLOCK_INIT( f ) { \
h5part_int64_t herr = _H5MultiBlock_init ( f ); \
if ( herr < 0 ) return herr; \
}
h5part_int64_t
_H5MultiBlock_init (
H5PartFile *f
);
h5part_int64_t
_H5MultiBlock_close (
H5PartFile *f
);
h5part_int64_t
_H5MultiBlock_write_data (
H5PartFile *f,
const char *field_name,
const void *data,
const hid_t type
);
h5part_int64_t
_H5MultiBlock_read_data (
H5PartFile *f,
const char *field_name,
char **data,
hid_t type
);
#endif
+239
View File
@@ -0,0 +1,239 @@
#include <stdlib.h>
#include <string.h>
#include <hdf5.h>
#include "H5Part.h"
#include "H5PartErrors.h"
#include "H5PartPrivate.h"
#include "H5MultiBlockErrors.h"
#include "H5MultiBlockPrivate.h"
/*!
\ingroup h5multiblock_c_api
Write a multiblock field \c name from the buffer starting at \c data
to the current time-step using the defined block decomposition and dimensions.
Values are floating points (64-bit).
You must use the Fortran indexing scheme to access items in \c data.
\return \c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock3dWriteFieldFloat64 (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to write */
const h5part_float64_t *data /*!< IN: data to write */
) {
SET_FNAME( "H5MultiBlock3dWriteFieldFloat64" );
h5part_int64_t herr;
herr = _H5MultiBlock_write_data ( f, name, data, H5T_NATIVE_DOUBLE );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Allocate a buffer to hold a block from a multiblock field and place the
pointer in \c data, then read the block into the buffer. Uses the block
decomposition specified in the file and the defined halo radius.
Values are floating points (64-bit).
You must use the Fortran indexing scheme to access items in \c data.
\return \c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock3dReadFieldFloat64 (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to read */
h5part_float64_t **data /*!< OUT: ptr to read buffer */
) {
SET_FNAME( "H5MultiBlock3dReadFieldFloat64" );
h5part_int64_t herr;
herr = _H5MultiBlock_read_data ( f, name, (char**) data, H5T_NATIVE_DOUBLE );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Write a multiblock field \c name from the buffer starting at \c data
to the current time-step using the defined block decomposition and dimensions.
Values are floating points (32-bit).
You must use the Fortran indexing scheme to access items in \c data.
\return \c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock3dWriteFieldFloat32 (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to write */
const h5part_float32_t *data /*!< IN: data to write */
) {
SET_FNAME( "H5MultiBlock3dWriteFieldFloat32" );
h5part_int64_t herr;
herr = _H5MultiBlock_write_data ( f, name, data, H5T_NATIVE_FLOAT );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Allocate a buffer to hold a block from a multiblock field and place the
pointer in \c data, then read the block into the buffer. Uses the block
decomposition specified in the file and the defined halo radius.
Values are floating points (32-bit).
You must use the Fortran indexing scheme to access items in \c data.
\return \c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock3dReadFieldFloat32 (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to read */
h5part_float32_t **data /*!< OUT: ptr to read buffer */
) {
SET_FNAME( "H5MultiBlock3dReadFieldFloat32" );
h5part_int64_t herr;
herr = _H5MultiBlock_read_data ( f, name, (char**) data, H5T_NATIVE_FLOAT );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Write a multiblock field \c name from the buffer starting at \c data
to the current time-step using the defined block decomposition and dimensions.
Values are integers (64-bit).
You must use the Fortran indexing scheme to access items in \c data.
\return \c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock3dWriteFieldInt64 (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to write */
const h5part_int64_t *data /*!< IN: data to write */
) {
SET_FNAME( "H5MultiBlock3dWriteFieldInt64" );
h5part_int64_t herr;
herr = _H5MultiBlock_write_data ( f, name, data, H5T_NATIVE_INT64 );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Allocate a buffer to hold a block from a multiblock field and place the
pointer in \c data, then read the block into the buffer. Uses the block
decomposition specified in the file and the defined halo radius.
Values are integers (64-bit).
You must use the Fortran indexing scheme to access items in \c data.
\return \c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock3dReadFieldInt64 (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to read */
h5part_int64_t **data /*!< OUT: ptr to read buffer */
) {
SET_FNAME( "H5MultiBlock3dReadFieldInt64" );
h5part_int64_t herr;
herr = _H5MultiBlock_read_data ( f, name, (char**) data, H5T_NATIVE_INT64 );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Write a multiblock field \c name from the buffer starting at \c data
to the current time-step using the defined block decomposition and dimensions.
Values are integers (32-bit).
You must use the Fortran indexing scheme to access items in \c data.
\return \c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock3dWriteFieldInt32 (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to write */
const h5part_int32_t *data /*!< IN: data to write */
) {
SET_FNAME( "H5MultiBlock3dWriteFieldInt32" );
h5part_int64_t herr;
herr = _H5MultiBlock_write_data ( f, name, data, H5T_NATIVE_INT32 );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
/*!
\ingroup h5multiblock_c_api
Allocate a buffer to hold a block from a multiblock field and place the
pointer in \c data, then read the block into the buffer. Uses the block
decomposition specified in the file and the defined halo radius.
Values are integers (32-bit).
You must use the Fortran indexing scheme to access items in \c data.
\return \c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock3dReadFieldInt32 (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to read */
h5part_int32_t **data /*!< OUT: ptr to read buffer */
) {
SET_FNAME( "H5MultiBlock3dReadFieldInt32" );
h5part_int64_t herr;
herr = _H5MultiBlock_read_data ( f, name, (char**) data, H5T_NATIVE_INT32 );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
+71
View File
@@ -0,0 +1,71 @@
#ifndef __H5MULTIBLOCKREADWRITE_H
#define __H5MULTIBLOCKREADWRITE_H
#ifdef __cplusplus
extern "C" {
#endif
h5part_int64_t
H5MultiBlock3dWriteFieldFloat64 (
H5PartFile *f,
const char *name,
const h5part_float64_t *data
);
h5part_int64_t
H5MultiBlock3dReadFieldFloat64 (
H5PartFile *f,
const char *name,
h5part_float64_t **data
);
h5part_int64_t
H5MultiBlock3dWriteFieldFloat32 (
H5PartFile *f,
const char *name,
const h5part_float32_t *data
);
h5part_int64_t
H5MultiBlock3dReadFieldFloat32 (
H5PartFile *f,
const char *name,
h5part_float32_t **data
);
h5part_int64_t
H5MultiBlock3dWriteFieldInt64 (
H5PartFile *f,
const char *name,
const h5part_int64_t *data
);
h5part_int64_t
H5MultiBlock3dReadFieldInt64 (
H5PartFile *f,
const char *name,
h5part_int64_t **data
);
h5part_int64_t
H5MultiBlock3dWriteFieldInt32 (
H5PartFile *f,
const char *name,
const h5part_int32_t *data
);
h5part_int64_t
H5MultiBlock3dReadFieldInt32 (
H5PartFile *f,
const char *name,
h5part_int32_t **data
);
#ifdef __cplusplus
}
#endif
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef __H5MULTIBLOCKTYPES_H
#define __H5MULTIBLOCKTYPES_H
struct H5MultiBlockStruct {
h5part_int64_t halo_radii[3];
h5part_int64_t block_dims[3];
h5part_int64_t field_dims[3];
h5part_int64_t decomp[3];
h5part_int64_t offsets[3];
char field_edges;
int read;
int halo;
int have_decomp;
};
#define H5PART_ERR_DECOMP -102
#define H5MB_EDGE_X0 0x01
#define H5MB_EDGE_X1 0x02
#define H5MB_EDGE_Y0 0x04
#define H5MB_EDGE_Y1 0x08
#define H5MB_EDGE_Z0 0x10
#define H5MB_EDGE_Z1 0x20
#endif
+13 -3
View File
@@ -100,7 +100,7 @@ Last modified on April 19, 2007.
static unsigned _debug = 0;
static h5part_int64_t _h5part_errno = H5PART_SUCCESS;
static h5part_error_handler _err_handler = H5PartReportErrorHandler;
static char *__funcname = "NONE";
static char *__funcname;
/********** Declaration of private functions ******/
@@ -512,6 +512,14 @@ H5PartCloseFile (
f->close_block = NULL;
}
#ifdef PARALLEL_IO
if ( f->multiblock && f->close_multiblock ) {
(*f->close_multiblock) ( f );
f->multiblock = NULL;
f->close_multiblock = NULL;
}
#endif
if( f->shape > 0 ) {
r = H5Sclose( f->shape );
if ( r < 0 ) HANDLE_H5S_CLOSE_ERR;
@@ -2878,6 +2886,7 @@ _init ( void ) {
herr_t r5;
if ( ! __init ) {
_H5Part_set_funcname ( "NONE" );
#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 8
r5 = H5Eset_auto2 ( H5E_DEFAULT, _h5_error_handler, NULL );
#else
@@ -3033,14 +3042,15 @@ _H5Part_print_debug_detail (
void
_H5Part_set_funcname (
char * const fname
char * const fname
) {
__funcname = fname;
}
const char *
char * const
_H5Part_get_funcname (
void
) {
return __funcname;
}
+5
View File
@@ -14,6 +14,11 @@ extern "C" {
#include "H5PartTypes.h"
#include "H5Block.h"
#ifdef PARALLEL_IO
#include "H5MultiBlock.h"
#endif
/* error values */
#define H5PART_SUCCESS 0
#define H5PART_ERR_NOMEM -12
+1 -1
View File
@@ -47,7 +47,7 @@ _H5Part_set_funcname (
char * const fname
);
const char *
char * const
_H5Part_get_funcname (
void
);
+5 -2
View File
@@ -81,6 +81,11 @@ struct H5PartFile {
struct H5BlockStruct *block;
h5part_int64_t (*close_block)(struct H5PartFile *f);
#ifdef PARALLEL_IO
struct H5MultiBlockStruct *multiblock;
h5part_int64_t (*close_multiblock)(struct H5PartFile *f);
#endif
};
typedef struct H5PartFile H5PartFile;
@@ -89,6 +94,4 @@ typedef struct H5PartFile H5PartFile;
# define SEEK_END 2
#endif
#endif
+13 -4
View File
@@ -40,13 +40,18 @@ lib_LIBRARIES = @MTARGET@
EXTRA_LIBRARIES = libH5Part.a libH5PartF.a
# Header files that I wish to install in $(prefix)/include
include_HEADERS = H5Part.h H5PartTypes.h H5PartErrors.h H5Block.h H5BlockReadWrite.h H5BlockTypes.h H5BlockErrors.h H5Part.inc H5PartF90.inc H5BlockF90.inc H5BlockReadWriteF90.inc @UNDERSCORE_H@
include_HEADERS = H5Part.h H5PartTypes.h H5PartErrors.h \
H5Block.h H5BlockReadWrite.h H5BlockTypes.h H5BlockErrors.h \
H5MultiBlock.h H5MultiBlockReadWrite.h H5MultiBlockTypes.h H5MultiBlockErrors.h \
H5Part.inc H5PartF90.inc \
H5BlockF90.inc H5BlockReadWriteF90.inc \
@UNDERSCORE_H@
# Listing of all possible headers that I may include
EXTRA_HEADERS = H5PartPrivate.h H5BlockPrivate.h
EXTRA_HEADERS = H5PartPrivate.h H5BlockPrivate.h H5MultiBlockPrivate.h
# Listing of sources
libH5Part_a_SOURCES = H5Part.c H5Block.c H5BlockReadWrite.c
libH5Part_a_SOURCES = H5Part.c H5Block.c H5BlockReadWrite.c H5MultiBlock.c H5MultiBlockReadWrite.c
libH5PartF_a_SOURCES = H5PartF.c H5BlockF.c H5BlockReadWriteF.c
@@ -55,7 +60,7 @@ H5Part.inc: H5PartF90.inc
# Specific building instruction (What compilers to use...)
# ------------ Serial Lib build commands ------------
libH5Part.a: H5Part.o H5Block.o H5BlockReadWrite.o
libH5Part.a: H5Part.o H5Block.o H5BlockReadWrite.o H5MultiBlock.o H5MultiBlockReadWrite.o
${AR} rucs $@ $^
libH5PartF.a: H5Part.o H5PartF.o H5Block.o H5BlockF.o H5BlockReadWrite.o H5BlockReadWriteF.o
@@ -70,6 +75,10 @@ H5Block.o: H5Block.c H5Part.h H5PartPrivate.h H5PartTypes.h H5Block.h H5BlockTyp
H5BlockF.o: H5BlockF.c Underscore.h H5Block.h
H5BlockReadWrite.o: H5BlockReadWrite.c H5Part.h H5PartPrivate.h H5PartTypes.h H5Block.h H5BlockPrivate.h H5BlockReadWrite.h H5BlockTypes.h
H5BlockReadWriteF.o: H5BlockF.c Underscore.h H5Block.h H5BlockReadWrite.h
H5MultiBlock.o: H5MultiBlock.c
H5MultiBlockF.o: H5MultiBlockF.c
H5MultiBlockReadWrite.o: H5MultiBlockReadWrite.c
H5MultiBlockReadWriteF.o: H5MultiBlockReadWriteF.c
# ----------- Build Parallel H5Part Stuff ------------
+4 -4
View File
@@ -97,7 +97,7 @@ H5Block#DIM#dWriteScalarField#TYPE_ABV# (
) {
SET_FNAME ( "H5Block#DIM#dWriteScalarField#TYPE_ABV#" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -135,7 +135,7 @@ H5Block#DIM#dReadScalarField#TYPE_ABV# (
) {
SET_FNAME ( "H5Block#DIM#dReadScalarField#TYPE_ABV#" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -268,7 +268,7 @@ H5Block#DIM#dWrite3dVectorField#TYPE_ABV# (
) {
SET_FNAME ( "H5Block#DIM#dWrite3dVectorField#TYPE_ABV#" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_WRITABLE_MODE ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
@@ -314,7 +314,7 @@ H5Block#DIM#dRead3dVectorField#TYPE_ABV# (
) {
SET_FNAME ( "H5Block#DIM#dRead3dVectorField#TYPE_ABV#" );
INIT ( f );
BLOCK_INIT ( f );
CHECK_TIMEGROUP ( f );
CHECK_LAYOUT ( f );
+256
View File
@@ -0,0 +1,256 @@
#!/usr/bin/python
c_head = """
#include <stdlib.h>
#include <string.h>
#include <hdf5.h>
#include "H5Part.h"
#include "H5PartErrors.h"
#include "H5PartPrivate.h"
#include "H5MultiBlockErrors.h"
#include "H5MultiBlockPrivate.h"
"""
h_head = """
#ifndef __H5MULTIBLOCKREADWRITE_H
#define __H5MULTIBLOCKREADWRITE_H
#ifdef __cplusplus
extern "C" {
#endif
"""
h_tail = """
#ifdef __cplusplus
}
#endif
#endif
"""
fc_head = """
#include "H5Part.h"
#include "H5PartPrivate.h"
#include "H5Block.h"
#include "H5BlockReadWrite.h"
#include "Underscore.h"
#if defined(F77_SINGLE_UNDERSCORE)
#define F77NAME(a,b) a
#elif defined(F77_CRAY_UNDERSCORE)
#define F77NAME(a,b) b
#elif defined(F77_NO_UNDERSCORE)
#else
#error Error, no way to determine how to construct fortran bindings
#endif
"""
fi_head = """
INTERFACE
"""
fi_tail = """
END INTERFACE
"""
write_h = """
h5part_int64_t
H5MultiBlock#DIM#dWriteField#TYPE_ABV# (
H5PartFile *f,
const char *name,
const h5part_#TYPE_H5P#_t *data
);
"""
read_h = """
h5part_int64_t
H5MultiBlock#DIM#dReadField#TYPE_ABV# (
H5PartFile *f,
const char *name,
h5part_#TYPE_H5P#_t **data
);
"""
write_c = """
/*!
\\ingroup h5multiblock_c_api
Write a multiblock field \\c name from the buffer starting at \\c data
to the current time-step using the defined block decomposition and dimensions.
Values are #TYPE_FULL#.
You must use the Fortran indexing scheme to access items in \\c data.
\\return \\c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock#DIM#dWriteField#TYPE_ABV# (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to write */
const h5part_#TYPE_H5P#_t *data /*!< IN: data to write */
) {
SET_FNAME( "H5MultiBlock#DIM#dWriteField#TYPE_ABV#" );
h5part_int64_t herr;
herr = _H5MultiBlock_write_data ( f, name, data, #TYPE_HDF5# );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
"""
read_c = """
/*!
\\ingroup h5multiblock_c_api
Allocate a buffer to hold a block from a multiblock field and place the
pointer in \\c data, then read the block into the buffer. Uses the block
decomposition specified in the file and the defined halo radius.
Values are #TYPE_FULL#.
You must use the Fortran indexing scheme to access items in \\c data.
\\return \\c H5PART_SUCCESS or error code
*/
h5part_int64_t
H5MultiBlock#DIM#dReadField#TYPE_ABV# (
H5PartFile *f, /*!< IN: file handle */
const char *name, /*!< IN: name of dataset to read */
h5part_#TYPE_H5P#_t **data /*!< OUT: ptr to read buffer */
) {
SET_FNAME( "H5MultiBlock#DIM#dReadField#TYPE_ABV#" );
h5part_int64_t herr;
herr = _H5MultiBlock_read_data ( f, name, (char**) data, #TYPE_HDF5# );
if ( herr < 0 ) return herr;
return H5PART_SUCCESS;
}
"""
write_fi = """
INTEGER*8 FUNCTION h5multi_#DIM#d_write_field_#TYPE_F90_ABV# ( filehandle, name, data )
INTEGER*8, INTENT(IN) :: filehandle
CHARACTER(LEN=*), INTENT(IN) :: name
#TYPE_F90#, INTENT(IN) :: data(*)
END FUNCTION
"""
read_fi = """
INTEGER*8 FUNCTION h5multi_#DIM#d_read_field_#TYPE_F90_ABV# ( filehandle, name, data )
INTEGER*8, INTENT(IN) :: filehandle
CHARACTER(LEN=*), INTENT(IN) :: name
#TYPE_F90#, INTENT(OUT) :: data(*)
END FUNCTION
"""
write_fc = """
#if ! defined(F77_NO_UNDERSCORE)
#define h5multi_#DIM#d_write_field_#TYPE_F90_ABV# F77NAME ( \\
h5multi_#DIM#d_write_field_#TYPE_F90_ABV#_, \\
H5MULTI_#DIM#D_WRITE_FIELD_#TYPE_F90_ABVC# )
#endif
h5part_int64_t
h5multi_#DIM#d_write_field_#TYPE_F90_ABV# (
h5part_int64_t *f,
const char *field_name,
const h5part_#TYPE_H5P#_t *data,
const int l_field_name
) {
H5PartFile *filehandle = (H5PartFile*)(size_t)*f;
char *field_name2 = _H5Part_strdupfor2c ( field_name, l_field_name );
h5part_int64_t herr = H5MultiBlock#DIM#dWriteField#TYPE_ABV# (
filehandle, field_name2, data );
free ( field_name2 );
return herr;
}
"""
read_fc = """
#if ! defined(F77_NO_UNDERSCORE)
#define h5multi_#DIM#d_read_field_#TYPE_F90_ABV# F77NAME ( \\
h5multi_#DIM#d_read_field_#TYPE_F90_ABV#_, \\
H5MULTI_#DIM#D_READ_FIELD_#TYPE_F90_ABVC# )
#endif
h5part_int64_t
h5multi_#DIM#d_read_field_#TYPE_F90_ABV# (
h5part_int64_t *f,
const char *field_name,
h5part_#TYPE_H5P#_t **data,
const int l_field_name
) {
H5PartFile *filehandle = (H5PartFile*)(size_t)*f;
char *field_name2 = _H5Part_strdupfor2c ( field_name, l_field_name );
h5part_int64_t herr = H5MultiBlock#DIM#dReadField#TYPE_ABV# (
filehandle, field_name2, (char**) data );
free ( field_name2 );
return herr;
}
"""
dims = [ "3" ]
types = [
["floating points (64-bit)", "Float64", "float64", "H5T_NATIVE_DOUBLE", "REAL*8", "r8", "R8"],
["floating points (32-bit)", "Float32", "float32", "H5T_NATIVE_FLOAT", "REAL*4", "r4", "R4"],
["integers (64-bit)", "Int64", "int64", "H5T_NATIVE_INT64", "INTEGER*8", "i8", "I8"],
["integers (32-bit)", "Int32", "int32", "H5T_NATIVE_INT32", "INTEGER*4", "i4", "I4"]
]
def create_call(template, type, dim):
fcn = template
fcn = fcn.replace('#DIM#',dim)\
.replace('#TYPE_FULL#',type[0])\
.replace('#TYPE_ABV#',type[1])\
.replace('#TYPE_H5P#',type[2])\
.replace('#TYPE_HDF5#',type[3])\
.replace('#TYPE_F90#',type[4])\
.replace('#TYPE_F90_ABV#',type[5])\
.replace('#TYPE_F90_ABVC#',type[6])
return fcn
def write_calls():
cfile = file('H5MultiBlockReadWrite.c','w')
cfile.write(c_head)
hfile = file('H5MultiBlockReadWrite.h','w')
hfile.write(h_head)
# fcfile = file('H5MultiBlockReadWriteF.c','w')
# fcfile.write(fc_head)
# fifile = file('H5MultiBlockReadWriteF90.inc','w')
# fifile.write(fi_head)
for dim in dims:
for type in types:
cfile.write(create_call(write_c,type,dim));
cfile.write(create_call(read_c,type,dim));
hfile.write(create_call(write_h,type,dim));
hfile.write(create_call(read_h,type,dim));
# fcfile.write(create_call(write_fc,type,dim));
# fcfile.write(create_call(read_fc,type,dim));
# fifile.write(create_call(write_fi,type,dim));
# fifile.write(create_call(read_fi,type,dim));
cfile.close()
hfile.write(h_tail)
hfile.close()
# fcfile.close()
# fifile.write(fi_tail)
# fifile.close()
write_calls()