From 6d38bf442dd03cb0c043cbbf57b8fb4c1bfc91cc Mon Sep 17 00:00:00 2001 From: Marc Howison Date: Thu, 2 Jul 2009 16:46:07 +0000 Subject: [PATCH] * H5Block: added attribute writing functions to code generator: still need to add reading functions * H5MultiBlock: added halo exchange routine: still needs debugging --- src/H5Block.c | 2 +- src/H5BlockPrivate.h | 10 + src/H5BlockReadWrite.c | 124 ++++++++++++ src/H5BlockReadWrite.h | 36 ++++ src/H5BlockReadWriteF.c | 124 ++++++++++++ src/H5BlockReadWriteF90.inc | 32 +++ src/H5MultiBlock.c | 356 ++++++++++++++++++++++++++++----- src/H5MultiBlock.h | 5 + src/H5MultiBlockErrors.h | 20 ++ src/H5MultiBlockTypes.h | 1 + src/generate-h5bl-readwrite.py | 92 +++++++++ 11 files changed, 752 insertions(+), 50 deletions(-) diff --git a/src/H5Block.c b/src/H5Block.c index e76b036..36525f1 100644 --- a/src/H5Block.c +++ b/src/H5Block.c @@ -1608,7 +1608,7 @@ H5BlockGetFieldInfoByName ( \return \c H5PART_SUCCESS or error code */ -static h5part_int64_t +h5part_int64_t _write_field_attrib ( H5PartFile *f, /*!< IN: file handle */ const char *field_name, /*!< IN: field name */ diff --git a/src/H5BlockPrivate.h b/src/H5BlockPrivate.h index bf370cd..167373b 100644 --- a/src/H5BlockPrivate.h +++ b/src/H5BlockPrivate.h @@ -57,4 +57,14 @@ _H5Block_read_data ( hid_t type ); +h5part_int64_t +_write_field_attrib ( + H5PartFile *f, + const char *field_name, + const char *attrib_name, + const hid_t attrib_type, + const void *attrib_value, + const h5part_int64_t attrib_nelem + ); + #endif diff --git a/src/H5BlockReadWrite.c b/src/H5BlockReadWrite.c index b78bd92..e62196d 100644 --- a/src/H5BlockReadWrite.c +++ b/src/H5BlockReadWrite.c @@ -643,3 +643,127 @@ H5Block3dRead3dVectorFieldInt32 ( return H5PART_SUCCESS; } + +/*! + \ingroup h5block_c_api + + Write \c attrib_value with type floating points (64-bit) as attribute \c attrib_name + to field \c field_name. + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5BlockWriteFieldAttribFloat64 ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_float64_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ) { + + SET_FNAME ( "H5BlockWriteFieldAttribFloat64" ); + BLOCK_INIT ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + + return _write_field_attrib ( + f, + field_name, + attrib_name, + H5T_NATIVE_DOUBLE, + attrib_value, + attrib_nelem ); +} + +/*! + \ingroup h5block_c_api + + Write \c attrib_value with type floating points (32-bit) as attribute \c attrib_name + to field \c field_name. + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5BlockWriteFieldAttribFloat32 ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_float32_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ) { + + SET_FNAME ( "H5BlockWriteFieldAttribFloat32" ); + BLOCK_INIT ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + + return _write_field_attrib ( + f, + field_name, + attrib_name, + H5T_NATIVE_FLOAT, + attrib_value, + attrib_nelem ); +} + +/*! + \ingroup h5block_c_api + + Write \c attrib_value with type integers (64-bit) as attribute \c attrib_name + to field \c field_name. + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5BlockWriteFieldAttribInt64 ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_int64_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ) { + + SET_FNAME ( "H5BlockWriteFieldAttribInt64" ); + BLOCK_INIT ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + + return _write_field_attrib ( + f, + field_name, + attrib_name, + H5T_NATIVE_INT64, + attrib_value, + attrib_nelem ); +} + +/*! + \ingroup h5block_c_api + + Write \c attrib_value with type integers (32-bit) as attribute \c attrib_name + to field \c field_name. + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5BlockWriteFieldAttribInt32 ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_int32_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ) { + + SET_FNAME ( "H5BlockWriteFieldAttribInt32" ); + BLOCK_INIT ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + + return _write_field_attrib ( + f, + field_name, + attrib_name, + H5T_NATIVE_INT32, + attrib_value, + attrib_nelem ); +} diff --git a/src/H5BlockReadWrite.h b/src/H5BlockReadWrite.h index 185f577..8f9d9d8 100644 --- a/src/H5BlockReadWrite.h +++ b/src/H5BlockReadWrite.h @@ -135,6 +135,42 @@ H5Block3dRead3dVectorFieldInt32 ( h5part_int32_t *zval ); +h5part_int64_t +H5BlockWriteFieldAttribFloat64 ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_float64_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ); + +h5part_int64_t +H5BlockWriteFieldAttribFloat32 ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_float32_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ); + +h5part_int64_t +H5BlockWriteFieldAttribInt64 ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_int64_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ); + +h5part_int64_t +H5BlockWriteFieldAttribInt32 ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_int32_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ); + #ifdef __cplusplus } diff --git a/src/H5BlockReadWriteF.c b/src/H5BlockReadWriteF.c index fd6c4e7..a3899ba 100644 --- a/src/H5BlockReadWriteF.c +++ b/src/H5BlockReadWriteF.c @@ -429,3 +429,127 @@ h5bl_3d_read_3dvector_field_i4 ( free ( field_name2 ); return herr; } + +#if ! defined(F77_NO_UNDERSCORE) +#define h5bl_writefieldattrib_r8 F77NAME ( \ + h5bl_writefieldattrib_r8_, \ + H5BL_WRITEFIELDATTRIB_R8 ) +#endif + +h5part_int64_t +h5bl_writefieldattrib_r8 ( + h5part_int64_t *f, + const char *field_name, + const char *attrib_name, + const h5part_float64_t *attrib_value, + const h5part_int64_t *attrib_nelem, + const int l_field_name, + const int l_attrib_name + ) { + + H5PartFile *filehandle = (H5PartFile*)(size_t)*f; + + char *field_name2 = _H5Part_strdupfor2c ( field_name, l_field_name ); + char *attrib_name2 =_H5Part_strdupfor2c ( attrib_name, l_attrib_name ); + + h5part_int64_t herr = H5BlockWriteFieldAttribFloat64 ( + filehandle, field_name2, attrib_name2, + attrib_value, *attrib_nelem ); + + free ( field_name2 ); + free ( attrib_name2 ); + return herr; +} + +#if ! defined(F77_NO_UNDERSCORE) +#define h5bl_writefieldattrib_r4 F77NAME ( \ + h5bl_writefieldattrib_r4_, \ + H5BL_WRITEFIELDATTRIB_R4 ) +#endif + +h5part_int64_t +h5bl_writefieldattrib_r4 ( + h5part_int64_t *f, + const char *field_name, + const char *attrib_name, + const h5part_float32_t *attrib_value, + const h5part_int64_t *attrib_nelem, + const int l_field_name, + const int l_attrib_name + ) { + + H5PartFile *filehandle = (H5PartFile*)(size_t)*f; + + char *field_name2 = _H5Part_strdupfor2c ( field_name, l_field_name ); + char *attrib_name2 =_H5Part_strdupfor2c ( attrib_name, l_attrib_name ); + + h5part_int64_t herr = H5BlockWriteFieldAttribFloat32 ( + filehandle, field_name2, attrib_name2, + attrib_value, *attrib_nelem ); + + free ( field_name2 ); + free ( attrib_name2 ); + return herr; +} + +#if ! defined(F77_NO_UNDERSCORE) +#define h5bl_writefieldattrib_i8 F77NAME ( \ + h5bl_writefieldattrib_i8_, \ + H5BL_WRITEFIELDATTRIB_I8 ) +#endif + +h5part_int64_t +h5bl_writefieldattrib_i8 ( + h5part_int64_t *f, + const char *field_name, + const char *attrib_name, + const h5part_int64_t *attrib_value, + const h5part_int64_t *attrib_nelem, + const int l_field_name, + const int l_attrib_name + ) { + + H5PartFile *filehandle = (H5PartFile*)(size_t)*f; + + char *field_name2 = _H5Part_strdupfor2c ( field_name, l_field_name ); + char *attrib_name2 =_H5Part_strdupfor2c ( attrib_name, l_attrib_name ); + + h5part_int64_t herr = H5BlockWriteFieldAttribInt64 ( + filehandle, field_name2, attrib_name2, + attrib_value, *attrib_nelem ); + + free ( field_name2 ); + free ( attrib_name2 ); + return herr; +} + +#if ! defined(F77_NO_UNDERSCORE) +#define h5bl_writefieldattrib_i4 F77NAME ( \ + h5bl_writefieldattrib_i4_, \ + H5BL_WRITEFIELDATTRIB_I4 ) +#endif + +h5part_int64_t +h5bl_writefieldattrib_i4 ( + h5part_int64_t *f, + const char *field_name, + const char *attrib_name, + const h5part_int32_t *attrib_value, + const h5part_int64_t *attrib_nelem, + const int l_field_name, + const int l_attrib_name + ) { + + H5PartFile *filehandle = (H5PartFile*)(size_t)*f; + + char *field_name2 = _H5Part_strdupfor2c ( field_name, l_field_name ); + char *attrib_name2 =_H5Part_strdupfor2c ( attrib_name, l_attrib_name ); + + h5part_int64_t herr = H5BlockWriteFieldAttribInt32 ( + filehandle, field_name2, attrib_name2, + attrib_value, *attrib_nelem ); + + free ( field_name2 ); + free ( attrib_name2 ); + return herr; +} diff --git a/src/H5BlockReadWriteF90.inc b/src/H5BlockReadWriteF90.inc index 2da7220..457dd17 100644 --- a/src/H5BlockReadWriteF90.inc +++ b/src/H5BlockReadWriteF90.inc @@ -113,4 +113,36 @@ INTEGER*8 FUNCTION h5bl_3d_read_3dvector_field_i4 ( filehandle, name, x, y, z ) INTEGER*4, INTENT(OUT) :: z(*) END FUNCTION +INTEGER*8 FUNCTION h5bl_writefieldattrib_r8 ( filehandle, field_name, attrib_name, attrib_value, attrib_nelem) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: field_name ! The name of the field + CHARACTER(LEN=*), INTENT(IN) :: attrib_name ! The name of the attribute + REAL*8, INTENT(IN) :: attrib_value(*) ! The array of data to write into the attribute + INTEGER*8, INTENT(IN) :: attrib_nelem ! Number of elements in the attrib array +END FUNCTION + +INTEGER*8 FUNCTION h5bl_writefieldattrib_r4 ( filehandle, field_name, attrib_name, attrib_value, attrib_nelem) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: field_name ! The name of the field + CHARACTER(LEN=*), INTENT(IN) :: attrib_name ! The name of the attribute + REAL*4, INTENT(IN) :: attrib_value(*) ! The array of data to write into the attribute + INTEGER*8, INTENT(IN) :: attrib_nelem ! Number of elements in the attrib array +END FUNCTION + +INTEGER*8 FUNCTION h5bl_writefieldattrib_i8 ( filehandle, field_name, attrib_name, attrib_value, attrib_nelem) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: field_name ! The name of the field + CHARACTER(LEN=*), INTENT(IN) :: attrib_name ! The name of the attribute + INTEGER*8, INTENT(IN) :: attrib_value(*) ! The array of data to write into the attribute + INTEGER*8, INTENT(IN) :: attrib_nelem ! Number of elements in the attrib array +END FUNCTION + +INTEGER*8 FUNCTION h5bl_writefieldattrib_i4 ( filehandle, field_name, attrib_name, attrib_value, attrib_nelem) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: field_name ! The name of the field + CHARACTER(LEN=*), INTENT(IN) :: attrib_name ! The name of the attribute + INTEGER*4, INTENT(IN) :: attrib_value(*) ! The array of data to write into the attribute + INTEGER*8, INTENT(IN) :: attrib_nelem ! Number of elements in the attrib array +END FUNCTION + END INTERFACE diff --git a/src/H5MultiBlock.c b/src/H5MultiBlock.c index e165dca..990e5f3 100644 --- a/src/H5MultiBlock.c +++ b/src/H5MultiBlock.c @@ -110,23 +110,30 @@ _get_decomp_and_offsets ( mb->decomp[1] = mb->field_dims[1] / mb->block_dims[1]; mb->decomp[2] = mb->field_dims[2] / mb->block_dims[2]; + if (f->myproc == 0) { + _H5Part_print_info ("Block decomposition: (%ld,%ld,%ld)", + mb->decomp[2], + mb->decomp[1], + mb->decomp[0] ); + } + _H5Part_print_debug ("PROC[%d]: Block decomposition: (%ld,%ld,%ld)", f->myproc, - mb->decomp[0], + mb->decomp[2], mb->decomp[1], - mb->decomp[2] ); + mb->decomp[0] ); - i = f->myproc % mb->decomp[0]; - j = (f->myproc / mb->decomp[0]) % mb->decomp[1]; - k = f->myproc / (mb->decomp[0] * mb->decomp[1]); + k = f->myproc % mb->decomp[2]; + j = (f->myproc / mb->decomp[2]) % mb->decomp[1]; + i = f->myproc / (mb->decomp[2] * 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; + if (i == 0) mb->field_edges |= H5MB_EDGE_Z0; + if (i == mb->decomp[0] - 1) mb->field_edges |= H5MB_EDGE_Z1; + if (j == 0) mb->field_edges |= H5MB_EDGE_Y0; + if (j == mb->decomp[1] - 1) mb->field_edges |= H5MB_EDGE_Y1; + if (k == 0) mb->field_edges |= H5MB_EDGE_X0; + if (k == mb->decomp[2] - 1) mb->field_edges |= H5MB_EDGE_X1; mb->offsets[0] = i * mb->block_dims[0]; mb->offsets[1] = j * mb->block_dims[1]; @@ -134,7 +141,7 @@ _get_decomp_and_offsets ( _H5Part_print_debug ("PROC[%d]: Block offsets: (%ld,%ld,%ld)", f->myproc, - mb->offsets[0], + mb->offsets[2], mb->offsets[1], mb->offsets[0] ); @@ -195,24 +202,19 @@ _alloc_block ( hid_t type /*!< IN: HDF5 datatype of buffer */ ) { - char *buffer; - size_t datasize; - size_t nelems; + size_t typesize; + h5part_int64_t nelems; struct H5MultiBlockStruct *mb = f->multiblock; /* size of datatype */ - datasize = H5Tget_size ( type ); + typesize = 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]; + nelems = mb->halo_dims[0] * mb->halo_dims[1] * mb->halo_dims[2]; - buffer = (char*) malloc ( nelems * datasize ); - if ( ! buffer ) return HANDLE_H5PART_NOMEM_ERR; - - *data = buffer; + *data = (char*) malloc ( nelems * typesize ); + if ( ! *data ) return HANDLE_H5PART_NOMEM_ERR; return H5PART_SUCCESS; } @@ -235,7 +237,7 @@ _pad_block ( hid_t type /*!< IN: HDF5 datatype of buffer */ ) { - size_t datasize; + size_t typesize; h5part_int64_t j, k; h5part_int64_t iDst, iSrc; h5part_int64_t xSize, xySize; @@ -245,20 +247,20 @@ _pad_block ( struct H5MultiBlockStruct *mb = f->multiblock; /* size of datatype */ - datasize = H5Tget_size ( type ); + typesize = H5Tget_size ( type ); /* size of row in original block */ - xSize = mb->block_dims[0] * datasize; + xSize = mb->block_dims[0] * typesize; /* 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]); + hxSize = mb->halo_dims[0] * typesize; + hxySize = hxSize * mb->halo_dims[1]; /* inset of row in halo region */ - hxInset = mb->halo_radii[0] * datasize; + hxInset = mb->halo_radii[0] * typesize; for (k=(mb->block_dims[2]-1);k>=0;k--) { @@ -277,6 +279,119 @@ _pad_block ( return H5PART_SUCCESS; } +static h5part_int64_t +_halo_create_region ( + const h5part_int64_t count, + const h5part_int64_t blocklen, + const h5part_int64_t stride, + MPI_Datatype *halo_region + ) { + + int ret; + int icount, iblocklen, istride; + + icount = (int)count; + if ( (h5part_int64_t)icount != count ) return HANDLE_MPI_INT64_ERR; + + iblocklen = (int)blocklen; + if ( (h5part_int64_t)iblocklen != blocklen ) + return HANDLE_MPI_INT64_ERR; + + istride = (int)stride; + if ( (h5part_int64_t)istride != stride ) return HANDLE_MPI_INT64_ERR; + + ret = MPI_Type_vector ( icount, iblocklen, istride, + MPI_BYTE, halo_region); + if (ret != MPI_SUCCESS) return HANDLE_MPI_CREATE_TYPE_ERR; + + ret = MPI_Type_commit ( halo_region ); + if (ret != MPI_SUCCESS) return HANDLE_MPI_CREATE_TYPE_ERR; + + return H5PART_SUCCESS; +} + +static h5part_int64_t +_halo_exchange_region ( + const H5PartFile *f, /*!< IN: file handle */ + char *data, /*!< IN/OUT: local buffer */ + MPI_Datatype *halo_region, + int send_offset, + int recv_offset, + char send_only_edge, + char recv_only_edge, + int proc_spacing + ) { + + int ret; + + struct H5MultiBlockStruct *mb = f->multiblock; + + MPI_Barrier ( MPI_COMM_WORLD ); + + if ( mb->field_edges & recv_only_edge ) { + ret = MPI_Recv ( + data + recv_offset, + 1, + *halo_region, + f->myproc - proc_spacing, + f->myproc, // use destination proc as tag + f->comm, + MPI_STATUS_IGNORE ); + } else if ( mb->field_edges & send_only_edge ) { + ret = MPI_Send ( + data + send_offset, + 1, + *halo_region, + f->myproc + proc_spacing, + f->myproc + proc_spacing, + f->comm ); + } else { + ret = MPI_Sendrecv ( + data + send_offset, + 1, + *halo_region, + f->myproc + proc_spacing, + f->myproc + proc_spacing, + data + recv_offset, + 1, + *halo_region, + f->myproc - proc_spacing, + f->myproc, + f->comm, + MPI_STATUS_IGNORE ); + } + + if ( ret != MPI_SUCCESS ) return HANDLE_MPI_SENDRECV_ERR; + + return H5PART_SUCCESS; +} + +static void +_pack_halo_region ( + const char *data, /*!< IN: local block */ + size_t typesize, /*!< IN: HDF5 datatype of buffer */ + h5part_int64_t offset, + h5part_int64_t count, + h5part_int64_t block_len, + h5part_int64_t stride, + char *buffer /*!< OUT: packed buffer */ + ) { + + h5part_int64_t i; + h5part_int64_t dst_offset, src_offset; + + src_offset = offset; + + for (i=0; imultiblock; + + typesize = H5Tget_size (type); + + blocksize = mb->halo_dims[0] * mb->halo_dims[1] * mb->halo_dims[2]; + blocksize *= typesize; + + /* xy-slab */ + slabsize = mb->halo_dims[2] * mb->halo_dims[1] * mb->halo_radii[0]; + slabsize *= typesize; + /* jump by an entire xy-slab to get the next z block */ + proc_spacing = mb->decomp[2] * mb->decomp[1]; + /* the best case: the entire x-dimension by y-dimension by z halo + * radius slab can be transferred contiguosly */ + herr = _halo_create_region ( 1, slabsize, 0, &halo_region ); + if (herr != H5PART_SUCCESS) return herr; + + /* forward */ + herr = _halo_exchange_region ( f, data, &halo_region, + blocksize - 2*slabsize, + 0, + H5MB_EDGE_Z0, H5MB_EDGE_Z1, + proc_spacing ); + if (herr != H5PART_SUCCESS) return herr; + + /* backward */ + herr = _halo_exchange_region ( f, data, &halo_region, + slabsize, + blocksize - slabsize, + H5MB_EDGE_Z1, H5MB_EDGE_Z0, + -proc_spacing ); + if (herr != H5PART_SUCCESS) return herr; + + MPI_Type_free ( &halo_region ); + + + /* xz-slab */ + slabsize = mb->halo_dims[2] * mb->halo_radii[1] * mb->halo_dims[0]; + slabsize *= typesize; + /* jump by an entire x-row to get the next y block */ + proc_spacing = mb->decomp[2]; + /* the second best case: a rectangle of x-dimension by y halo radius + * can be transferred contiguously */ + herr = _halo_create_region ( + mb->halo_dims[0], + mb->halo_dims[2] * mb->halo_radii[1] * typesize, + mb->halo_dims[2] * mb->halo_dims[1] * typesize, + &halo_region ); + if (herr != H5PART_SUCCESS) return herr; + + /* forward */ + herr = _halo_exchange_region ( f, data, &halo_region, + blocksize - 2*slabsize, + 0, + H5MB_EDGE_Y0, H5MB_EDGE_Y1, + proc_spacing ); + if (herr != H5PART_SUCCESS) return herr; + + /* backward */ + herr = _halo_exchange_region ( f, data, &halo_region, + slabsize, + blocksize - slabsize, + H5MB_EDGE_Y1, H5MB_EDGE_Y0, + -proc_spacing ); + if (herr != H5PART_SUCCESS) return herr; + + MPI_Type_free ( &halo_region ); + + + /* yz-slab */ + slabsize = mb->halo_radii[2] * mb->halo_dims[1] * mb->halo_dims[0]; + slabsize *= typesize; + /* blocks are contiguous in the x direction */ + proc_spacing = 1; + /* the worst case: only small rows with length = x halo radius */ + herr = _halo_create_region ( + mb->halo_dims[1] * mb->halo_dims[0], + mb->halo_radii[2] * typesize, + mb->halo_dims[2] * typesize, + &halo_region ); + if (herr != H5PART_SUCCESS) return herr; + + /* forward */ + herr = _halo_exchange_region ( f, data, &halo_region, + blocksize - 2*slabsize, + 0, + H5MB_EDGE_X0, H5MB_EDGE_X1, + proc_spacing ); + if (herr != H5PART_SUCCESS) return herr; + + /* backward */ + herr = _halo_exchange_region ( f, data, &halo_region, + slabsize, + blocksize - slabsize, + H5MB_EDGE_X1, H5MB_EDGE_X0, + -proc_spacing ); + if (herr != H5PART_SUCCESS) return herr; + + MPI_Type_free ( &halo_region ); + + return H5PART_SUCCESS; } @@ -327,6 +549,10 @@ _H5MultiBlock_init ( } mb = f->multiblock; + mb->halo_radii[0] = 0; + mb->halo_radii[1] = 0; + mb->halo_radii[2] = 0; + mb->field_edges = 0; mb->halo = 0; mb->read = 0; @@ -404,11 +630,22 @@ _H5MultiBlock_read_data ( mb->block_dims ); if ( herr < 0 ) return herr; + if ( f->myproc == 0 ) { + _H5Part_print_info ("Block dimensions: (%ld,%ld,%ld)", + mb->block_dims[2], + mb->block_dims[1], + mb->block_dims[0] ); + } + _H5Part_print_debug ("PROC[%d]: Block dimensions: (%ld,%ld,%ld)", f->myproc, - mb->block_dims[0], + mb->block_dims[2], mb->block_dims[1], - mb->block_dims[2] ); + mb->block_dims[0] ); + + mb->halo_dims[0] = mb->block_dims[0] + 2*mb->halo_radii[0]; + mb->halo_dims[1] = mb->block_dims[1] + 2*mb->halo_radii[1]; + mb->halo_dims[2] = mb->block_dims[2] + 2*mb->halo_radii[2]; dataspace_id = H5Dget_space ( dataset_id ); if ( dataspace_id < 0 ) return HANDLE_H5D_GET_SPACE_ERR; @@ -428,10 +665,12 @@ _H5MultiBlock_read_data ( mb->have_decomp = 1; + /* shortcut: use the H5Block layout; indices have to be inverted, though, since + * the API exposes Fortran ordering and all internal data uses C ordering */ herr = H5BlockDefine3DFieldLayout ( f, - mb->offsets[0], mb->offsets[0] + mb->block_dims[0] - 1, + mb->offsets[2], mb->offsets[2] + mb->block_dims[2] - 1, mb->offsets[1], mb->offsets[1] + mb->block_dims[1] - 1, - mb->offsets[2], mb->offsets[2] + mb->block_dims[2] - 1); + mb->offsets[0], mb->offsets[0] + mb->block_dims[0] - 1); if ( herr < 0 ) return herr; _H5Part_set_funcname ( fname ); @@ -456,7 +695,8 @@ _H5MultiBlock_read_data ( if ( mb->halo ) { _pad_block ( f, *data, type ); - _halo_exchange ( f, *data, type ); + herr = _halo_exchange ( f, *data, type ); + if ( herr != H5PART_SUCCESS ) return herr; } mb->read = 1; @@ -495,16 +735,18 @@ _H5MultiBlock_write_data ( char * const fname = _H5Part_get_funcname(); + /* shortcut: use the H5Block layout; indices have to be inverted, though, since + * the API exposes Fortran ordering and all internal data uses C ordering */ herr = H5BlockDefine3DFieldLayout ( f, - mb->offsets[0], mb->offsets[0] + mb->block_dims[0] - 1, + mb->offsets[2], mb->offsets[2] + mb->block_dims[2] - 1, mb->offsets[1], mb->offsets[1] + mb->block_dims[1] - 1, - mb->offsets[2], mb->offsets[2] + mb->block_dims[2] - 1); + mb->offsets[0], mb->offsets[0] + mb->block_dims[0] - 1); if ( herr < 0 ) return herr; herr = H5BlockDefine3DChunkDims( f, - mb->block_dims[0], + mb->block_dims[2], mb->block_dims[1], - mb->block_dims[2]); + mb->block_dims[0]); if ( herr < 0 ) return herr; _H5Part_set_funcname ( fname ); @@ -643,13 +885,13 @@ H5MultiBlock3dDefineDims ( struct H5MultiBlockStruct *mb = f->multiblock; - mb->field_dims[0] = field_dims[0]; + mb->field_dims[0] = field_dims[2]; mb->field_dims[1] = field_dims[1]; - mb->field_dims[2] = field_dims[2]; + mb->field_dims[2] = field_dims[0]; - mb->block_dims[0] = block_dims[0]; + mb->block_dims[0] = block_dims[2]; mb->block_dims[1] = block_dims[1]; - mb->block_dims[2] = block_dims[2]; + mb->block_dims[2] = block_dims[0]; h5part_int64_t herr = _get_decomp_and_offsets ( f ); if ( herr < 0 ) return H5PART_ERR_INVAL; @@ -681,9 +923,9 @@ H5MultiBlock3dGetFieldDims( if ( ! mb->read ) return H5PART_ERR_INVAL; - dims[0] = mb->field_dims[0]; + dims[0] = mb->field_dims[2]; dims[1] = mb->field_dims[1]; - dims[2] = mb->field_dims[2]; + dims[2] = mb->field_dims[0]; return H5PART_SUCCESS; } @@ -711,9 +953,9 @@ H5MultiBlock3dGetBlockDims( if ( ! mb->read ) return H5PART_ERR_INVAL; - dims[0] = mb->block_dims[0]; + dims[0] = mb->block_dims[2]; dims[1] = mb->block_dims[1]; - dims[2] = mb->block_dims[2]; + dims[2] = mb->block_dims[0]; return H5PART_SUCCESS; } @@ -741,9 +983,9 @@ H5MultiBlock3dGetOffsetsOfProc ( struct H5MultiBlockStruct *mb = f->multiblock; - offsets[0] = mb->offsets[0]; + offsets[0] = mb->offsets[2]; offsets[1] = mb->offsets[1]; - offsets[2] = mb->offsets[2]; + offsets[2] = mb->offsets[0]; return H5PART_SUCCESS; } @@ -757,7 +999,6 @@ H5MultiBlock3dGetOffsetsOfProc ( \return \c H5PART_SUCCESS on success
\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 */ @@ -775,5 +1016,22 @@ H5MultiBlock3dCalculateDecomp ( return H5PART_SUCCESS; } +/*! + \ingroup h5multiblock_c_api + + Frees a \c block that was allocated during a read. + + \return \c H5PART_SUCCESS +*/ +h5part_int64_t +H5MultiBlockFree ( + void *block /*!< IN: block that was allocated during a read */ + ) { + + free (block); + + return H5PART_SUCCESS; +} + #endif diff --git a/src/H5MultiBlock.h b/src/H5MultiBlock.h index faed341..e0fd0b1 100644 --- a/src/H5MultiBlock.h +++ b/src/H5MultiBlock.h @@ -60,6 +60,11 @@ H5MultiBlock3dCalculateDecomp ( h5part_int64_t *decomp ); +h5part_int64_t +H5MultiBlockFree ( + void *block + ); + #ifdef __cplusplus } #endif diff --git a/src/H5MultiBlockErrors.h b/src/H5MultiBlockErrors.h index a0f7a5b..a9d7658 100644 --- a/src/H5MultiBlockErrors.h +++ b/src/H5MultiBlockErrors.h @@ -16,4 +16,24 @@ H5PART_ERR_DECOMP, \ "Number of blocks does not equal number of procs" ); +#define HANDLE_MPI_CREATE_TYPE_ERR \ + (*_err_handler) ( \ + _H5Part_get_funcname(), \ + H5PART_ERR_MPI, \ + "Cannot created strided vector MPI datatype." ); + +#define HANDLE_MPI_SENDRECV_ERR \ + (*_err_handler) ( \ + _H5Part_get_funcname(), \ + H5PART_ERR_MPI, \ + "Unable to perform point-to-point MPI send/receive." ); + +#define HANDLE_MPI_INT64_ERR \ + (*_err_handler) ( \ + _H5Part_get_funcname(), \ + H5PART_ERR_MPI, \ + "Integer overslow error! An offset/count/stride/etc. value " \ + "passed to an MPI function exceeds the 32-bit limit imposed " \ + "by the MPI standard." ); + #endif diff --git a/src/H5MultiBlockTypes.h b/src/H5MultiBlockTypes.h index 533fcb5..4e28b4f 100644 --- a/src/H5MultiBlockTypes.h +++ b/src/H5MultiBlockTypes.h @@ -4,6 +4,7 @@ struct H5MultiBlockStruct { h5part_int64_t halo_radii[3]; h5part_int64_t block_dims[3]; + h5part_int64_t halo_dims[3]; h5part_int64_t field_dims[3]; h5part_int64_t decomp[3]; h5part_int64_t offsets[3]; diff --git a/src/generate-h5bl-readwrite.py b/src/generate-h5bl-readwrite.py index 8da8a53..8d234df 100755 --- a/src/generate-h5bl-readwrite.py +++ b/src/generate-h5bl-readwrite.py @@ -413,6 +413,93 @@ h5bl_#DIM#d_read_3dvector_field_#TYPE_F90_ABV# ( } """ +write_attr_h = """ +h5part_int64_t +H5BlockWriteFieldAttrib#TYPE_ABV# ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_#TYPE_H5P#_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ); +""" + +write_attr_c = """ +/*! + \\ingroup h5block_c_api + + Write \\c attrib_value with type #TYPE_FULL# as attribute \\c attrib_name + to field \\c field_name. + + \\return \\c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5BlockWriteFieldAttrib#TYPE_ABV# ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const char *attrib_name, /*!< IN: attribute name */ + const h5part_#TYPE_H5P#_t *attrib_value, /*!< IN: attribute value */ + const h5part_int64_t attrib_nelem /*!< IN: number of elements */ + ) { + + SET_FNAME ( "H5BlockWriteFieldAttrib#TYPE_ABV#" ); + BLOCK_INIT ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + + return _write_field_attrib ( + f, + field_name, + attrib_name, + #TYPE_HDF5#, + attrib_value, + attrib_nelem ); +} +""" + +write_attr_fi = """ +INTEGER*8 FUNCTION h5bl_writefieldattrib_#TYPE_F90_ABV# ( filehandle, field_name, attrib_name, attrib_value, attrib_nelem) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: field_name ! The name of the field + CHARACTER(LEN=*), INTENT(IN) :: attrib_name ! The name of the attribute + #TYPE_F90#, INTENT(IN) :: attrib_value(*) ! The array of data to write into the attribute + INTEGER*8, INTENT(IN) :: attrib_nelem ! Number of elements in the attrib array +END FUNCTION +""" + +write_attr_fc = """ +#if ! defined(F77_NO_UNDERSCORE) +#define h5bl_writefieldattrib_#TYPE_F90_ABV# F77NAME ( \\ + h5bl_writefieldattrib_#TYPE_F90_ABV#_, \\ + H5BL_WRITEFIELDATTRIB_#TYPE_F90_ABVC# ) +#endif + +h5part_int64_t +h5bl_writefieldattrib_#TYPE_F90_ABV# ( + h5part_int64_t *f, + const char *field_name, + const char *attrib_name, + const h5part_#TYPE_H5P#_t *attrib_value, + const h5part_int64_t *attrib_nelem, + const int l_field_name, + const int l_attrib_name + ) { + + H5PartFile *filehandle = (H5PartFile*)(size_t)*f; + + char *field_name2 = _H5Part_strdupfor2c ( field_name, l_field_name ); + char *attrib_name2 =_H5Part_strdupfor2c ( attrib_name, l_attrib_name ); + + h5part_int64_t herr = H5BlockWriteFieldAttrib#TYPE_ABV# ( + filehandle, field_name2, attrib_name2, + attrib_value, *attrib_nelem ); + + free ( field_name2 ); + free ( attrib_name2 ); + return herr; +} +""" + dims = ["3"] types = [ @@ -461,6 +548,11 @@ def write_calls(): fcfile.write(create_call(read_vector_fc,type,dim)); fifile.write(create_call(write_vector_fi,type,dim)); fifile.write(create_call(read_vector_fi,type,dim)); + for type in types: + cfile.write(create_call(write_attr_c,type,"")); + hfile.write(create_call(write_attr_h,type,"")); + fifile.write(create_call(write_attr_fi,type,"")); + fcfile.write(create_call(write_attr_fc,type,"")); cfile.close() hfile.write(h_tail) hfile.close()