diff --git a/.gitattributes b/.gitattributes index 28bc524..8af69ca 100644 --- a/.gitattributes +++ b/.gitattributes @@ -77,6 +77,7 @@ test/H5test.cc -text test/H5testF.f -text test/H5testFpar.F90 -text test/Makefile.am -text +test/coords.F90 -text test/params.h -text test/read.c -text test/test.c -text diff --git a/src/H5Block.c b/src/H5Block.c index adb5362..1495955 100644 --- a/src/H5Block.c +++ b/src/H5Block.c @@ -2009,6 +2009,250 @@ H5Block3dSetFieldSpacing ( 3 ); } +/*! + \ingroup h5block_attrib + + Get the explicit list of X coordinates for field \c field_name in the current + time step. The coordinates are read into the 1D array \c coords which has + length \c coords_len. + + By convention, the \c coords array should have the same length as the X + dimension of the field, and a warning will be printed if they differ. + + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5Block3dGetFieldXCoords( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + h5part_float64_t *coords, /*!< OUT: X coordinates */ + const h5part_int64_t coords_len /*!< IN: length of coordinates */ + ) { + + SET_FNAME ( "H5BlockGetFieldXCoords" ); + BLOCK_INIT ( f ); + CHECK_TIMEGROUP( f ); + CHECK_LAYOUT( f ); + + struct H5BlockStruct *b = f->block; + + if (coords_len != b->i_max + 1) + _H5Part_print_warn( "Coordinate array length (%lld) does not match X dimension (%lld)", + (long long)coords_len, (long long)b->i_max + 1); + + return _read_field_attrib ( + f, + field_name, + H5BLOCK_FIELD_XCOORD_NAME, + coords ); +} + +/*! + \ingroup h5block_attrib + + Set an explicit list of X coordinates for field \c field_name in the current + time step. The coordinates are a 1D array of floating point values with + dimension \c coords_len. + + By convention, the \c coords array should have the same length as the X + dimension of the field, and a warning will be printed if not. + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5Block3dSetFieldXCoords ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const h5part_float64_t *coords, /*!< IN: X coordinates */ + const h5part_int64_t coords_len /*!< IN: number of coordinates */ + ) { + + SET_FNAME ( "H5BlockSetFieldXCoords" ); + BLOCK_INIT ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + CHECK_LAYOUT( f ); + + struct H5BlockStruct *b = f->block; + + if (coords_len != b->i_max + 1) + _H5Part_print_warn( "Coordinate array length (%lld) does not match X dimension (%lld)", + (long long)coords_len, (long long)b->i_max + 1); + + return _write_field_attrib ( + f, + field_name, + H5BLOCK_FIELD_XCOORD_NAME, + (const hid_t)H5PART_FLOAT64, + coords, + coords_len + ); +} + +/*! + \ingroup h5block_attrib + + Get the explicit list of Y coordinates for field \c field_name in the current + time step. The coordinates are read into the 1D array \c coords which has + length \c coords_len. + + By convention, the \c coords array should have the same length as the Y + dimension of the field, and a warning will be printed if they differ. + + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5Block3dGetFieldYCoords( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + h5part_float64_t *coords, /*!< OUT: Y coordinates */ + const h5part_int64_t coords_len /*!< IN: length of coordinates */ + ) { + + SET_FNAME ( "H5BlockGetFieldYCoords" ); + BLOCK_INIT ( f ); + CHECK_TIMEGROUP( f ); + CHECK_LAYOUT( f ); + + struct H5BlockStruct *b = f->block; + + if (coords_len != b->j_max + 1) + _H5Part_print_warn( "Coordinate array length (%lld) does not match Y dimension (%lld)", + (long long)coords_len, (long long)b->j_max + 1); + + return _read_field_attrib ( + f, + field_name, + H5BLOCK_FIELD_YCOORD_NAME, + coords ); +} + + +/*! + \ingroup h5block_attrib + + Set an explicit list of Y coordinates for field \c field_name in the current + time step. The coordinates are a 1D array of floating point values with + dimension \c coords_len. + + By convention, the \c coords array should have the same length as the Y + dimension of the field, and a warning will be printed if not. + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5Block3dSetFieldYCoords ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const h5part_float64_t *coords, /*!< IN: Y coordinates */ + const h5part_int64_t coords_len /*!< IN: number of coordinates */ + ) { + + SET_FNAME ( "H5BlockSetFieldYCoords" ); + BLOCK_INIT ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + CHECK_LAYOUT( f ); + + struct H5BlockStruct *b = f->block; + + if (coords_len != b->j_max + 1) + _H5Part_print_warn( "Coordinate array length (%lld) does not match X dimension (%lld)", + (long long)coords_len, (long long)b->j_max + 1); + + return _write_field_attrib ( + f, + field_name, + H5BLOCK_FIELD_YCOORD_NAME, + (const hid_t)H5PART_FLOAT64, + coords, + coords_len + ); +} + +/*! + \ingroup h5block_attrib + + Get the explicit list of Z coordinates for field \c field_name in the current + time step. The coordinates are read into the 1D array \c coords which has + length \c coords_len. + + By convention, the \c coords array should have the same length as the Z + dimension of the field, and a warning will be printed if they differ. + + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5Block3dGetFieldZCoords( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + h5part_float64_t *coords, /*!< OUT: Z coordinates */ + const h5part_int64_t coords_len /*!< IN: length of coordinates */ + ) { + + SET_FNAME ( "H5BlockGetFieldZCoords" ); + BLOCK_INIT ( f ); + CHECK_TIMEGROUP( f ); + CHECK_LAYOUT( f ); + + struct H5BlockStruct *b = f->block; + + if (coords_len != b->k_max + 1) + _H5Part_print_warn( "Coordinate array length (%lld) does not match Z dimension (%lld)", + (long long)coords_len, (long long)b->k_max + 1); + + return _read_field_attrib ( + f, + field_name, + H5BLOCK_FIELD_ZCOORD_NAME, + coords ); +} + +/*! + \ingroup h5block_attrib + + Set an explicit list of Z coordinates for field \c field_name in the current + time step. The coordinates are a 1D array of floating point values with + dimension \c coords_len. + + By convention, the \c coords array should have the same length as the Z + dimension of the field, and a warning will be printed if not. + + \return \c H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5Block3dSetFieldZCoords ( + H5PartFile *f, /*!< IN: file handle */ + const char *field_name, /*!< IN: field name */ + const h5part_float64_t *coords, /*!< IN: Z coordinates */ + const h5part_int64_t coords_len /*!< IN: number of coordinates */ + ) { + + SET_FNAME ( "H5BlockSetFieldZCoords" ); + BLOCK_INIT ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + CHECK_LAYOUT( f ); + + struct H5BlockStruct *b = f->block; + + if (coords_len != b->k_max + 1) + _H5Part_print_warn( "Coordinate array length (%lld) does not match X dimension (%lld)", + (long long)coords_len, (long long)b->k_max + 1); + + return _write_field_attrib ( + f, + field_name, + H5BLOCK_FIELD_ZCOORD_NAME, + (const hid_t)H5PART_FLOAT64, + coords, + coords_len + ); +} + /*! \ingroup h5block_model diff --git a/src/H5Block.f90 b/src/H5Block.f90 index ffb0558..9244d7f 100644 --- a/src/H5Block.f90 +++ b/src/H5Block.f90 @@ -232,4 +232,69 @@ INTEGER*8 FUNCTION h5bl_3d_set_field_origin ( filehandle, name, x, y, z ) REAL*8, INTENT(IN) :: z END FUNCTION +!> \ingroup h5blockf_attrib +!! See \ref H5Block3dGetFieldXCoords +!! \return 0 on success or error code +!< +INTEGER*8 FUNCTION h5bl_3d_get_field_xcoords ( filehandle, name, coords ) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: name + REAL*8, INTENT(OUT) :: coords(*) + INTEGER*8, INTENT(IN) :: coords_len +END FUNCTION +!> \ingroup h5blockf_attrib +!! See \ref H5Block3dSetFieldXCoords +!! \return 0 on success or error code +!< +INTEGER*8 FUNCTION h5bl_3d_set_field_xcoords ( filehandle, name, coords ) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: name + REAL*8, INTENT(IN) :: coords(*) + INTEGER*8, INTENT(IN) :: coords_len +END FUNCTION + +!> \ingroup h5blockf_attrib +!! See \ref H5Block3dGetFieldYCoords +!! \return 0 on success or error code +!< +INTEGER*8 FUNCTION h5bl_3d_get_field_ycoords ( filehandle, name, coords ) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: name + REAL*8, INTENT(OUT) :: coords(*) + INTEGER*8, INTENT(IN) :: coords_len +END FUNCTION + +!> \ingroup h5blockf_attrib +!! See \ref H5Block3dSetFieldYCoords +!! \return 0 on success or error code +!< +INTEGER*8 FUNCTION h5bl_3d_set_field_ycoords ( filehandle, name, coords ) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: name + REAL*8, INTENT(IN) :: coords(*) + INTEGER*8, INTENT(IN) :: coords_len +END FUNCTION + +!> \ingroup h5blockf_attrib +!! See \ref H5Block3dGetFieldZCoords +!! \return 0 on success or error code +!< +INTEGER*8 FUNCTION h5bl_3d_get_field_zcoords ( filehandle, name, coords ) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: name + REAL*8, INTENT(OUT) :: coords(*) + INTEGER*8, INTENT(IN) :: coords_len +END FUNCTION + +!> \ingroup h5blockf_attrib +!! See \ref H5Block3dSetFieldZCoords +!! \return 0 on success or error code +!< +INTEGER*8 FUNCTION h5bl_3d_set_field_zcoords ( filehandle, name, coords ) + INTEGER*8, INTENT(IN) :: filehandle + CHARACTER(LEN=*), INTENT(IN) :: name + REAL*8, INTENT(IN) :: coords(*) + INTEGER*8, INTENT(IN) :: coords_len +END FUNCTION + diff --git a/src/H5Block.h b/src/H5Block.h index aba3c29..aad7287 100644 --- a/src/H5Block.h +++ b/src/H5Block.h @@ -13,6 +13,9 @@ extern "C" { #define H5BLOCK_FIELD_ORIGIN_NAME "__Origin__" #define H5BLOCK_FIELD_SPACING_NAME "__Spacing__" +#define H5BLOCK_FIELD_XCOORD_NAME "__X_Coordinates__" +#define H5BLOCK_FIELD_YCOORD_NAME "__Y_Coordinates__" +#define H5BLOCK_FIELD_ZCOORD_NAME "__Z_Coordinates__" /*! Interface for block structured field data. @@ -138,6 +141,54 @@ H5Block3dSetFieldSpacing ( const h5part_float64_t z_spacing ); +h5part_int64_t +H5Block3dGetFieldXCoords ( + H5PartFile *f, + const char *field_name, + h5part_float64_t *coords, + const h5part_int64_t coords_len + ); + +h5part_int64_t +H5Block3dSetFieldXCoords ( + H5PartFile *f, + const char *field_name, + const h5part_float64_t *coords, + const h5part_int64_t coords_len + ); + +h5part_int64_t +H5Block3dGetFieldYCoords ( + H5PartFile *f, + const char *field_name, + h5part_float64_t *coords, + const h5part_int64_t coords_len + ); + +h5part_int64_t +H5Block3dSetFieldYCoords ( + H5PartFile *f, + const char *field_name, + const h5part_float64_t *coords, + const h5part_int64_t coords_len + ); + +h5part_int64_t +H5Block3dGetFieldZCoords ( + H5PartFile *f, + const char *field_name, + h5part_float64_t *coords, + const h5part_int64_t coords_len + ); + +h5part_int64_t +H5Block3dSetZCoords ( + H5PartFile *f, + const char *field_name, + const h5part_float64_t *coords, + const h5part_int64_t coords_len + ); + h5part_int64_t H5BlockWriteFieldAttrib ( H5PartFile *f, diff --git a/src/H5BlockF.c b/src/H5BlockF.c index 33ee255..d0c62cb 100755 --- a/src/H5BlockF.c +++ b/src/H5BlockF.c @@ -68,6 +68,24 @@ #define h5bl_3d_get_field_origin F77NAME ( \ h5bl_3d_get_field_origin_, \ H5BL_3D_GET_FIELD_origin ) +#define h5bl_3d_get_field_xcoords F77NAME ( \ + h5bl_3d_get_field_xcoords_, \ + H5BL_3D_GET_FIELD_XCOORDS ) +#define h5bl_3d_set_field_xcoords F77NAME ( \ + h5bl_3d_set_field_xcoords_, \ + H5BL_3D_SET_FIELD_XCOORDS ) +#define h5bl_3d_get_field_ycoords F77NAME ( \ + h5bl_3d_get_field_ycoords_, \ + H5BL_3D_GET_FIELD_YCOORDS ) +#define h5bl_3d_set_field_ycoords F77NAME ( \ + h5bl_3d_set_field_ycoords_, \ + H5BL_3D_SET_FIELD_YCOORDS ) +#define h5bl_3d_get_field_zcoords F77NAME ( \ + h5bl_3d_get_field_zcoords_, \ + H5BL_3D_GET_FIELD_ZCOORDS ) +#define h5bl_3d_set_field_zcoords F77NAME ( \ + h5bl_3d_set_field_zcoords_, \ + H5BL_3D_SET_FIELD_ZCOORDS ) #endif h5part_int64_t @@ -447,3 +465,123 @@ h5bl_3d_set_field_origin ( free ( field_name2 ); return herr; } + +h5part_int64_t +h5bl_3d_set_field_xcoords ( + h5part_int64_t *f, + const char *field_name, + const h5part_float64_t *coords, + const h5part_int64_t *coords_len, + 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 = H5Block3dSetFieldXCoords ( + filehandle, field_name2, coords, *coords_len ); + + free ( field_name2 ); + return herr; +} + +h5part_int64_t +h5bl_3d_get_field_xcoords ( + h5part_int64_t *f, + const char *field_name, + h5part_float64_t *coords, + const h5part_int64_t *coords_len, + 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 = H5Block3dGetFieldXCoords ( + filehandle, field_name2, coords, *coords_len ); + + free ( field_name2 ); + return herr; +} + +h5part_int64_t +h5bl_3d_set_field_ycoords ( + h5part_int64_t *f, + const char *field_name, + const h5part_float64_t *coords, + const h5part_int64_t *coords_len, + 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 = H5Block3dSetFieldYCoords ( + filehandle, field_name2, coords, *coords_len ); + + free ( field_name2 ); + return herr; +} + +h5part_int64_t +h5bl_3d_get_field_ycoords ( + h5part_int64_t *f, + const char *field_name, + h5part_float64_t *coords, + const h5part_int64_t *coords_len, + 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 = H5Block3dGetFieldYCoords ( + filehandle, field_name2, coords, *coords_len ); + + free ( field_name2 ); + return herr; +} + +h5part_int64_t +h5bl_3d_set_field_zcoords ( + h5part_int64_t *f, + const char *field_name, + const h5part_float64_t *coords, + const h5part_int64_t *coords_len, + 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 = H5Block3dSetFieldZCoords ( + filehandle, field_name2, coords, *coords_len ); + + free ( field_name2 ); + return herr; +} + +h5part_int64_t +h5bl_3d_get_field_zcoords ( + h5part_int64_t *f, + const char *field_name, + h5part_float64_t *coords, + const h5part_int64_t *coords_len, + 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 = H5Block3dGetFieldZCoords ( + filehandle, field_name2, coords, *coords_len ); + + free ( field_name2 ); + return herr; +} diff --git a/src/H5Part.c b/src/H5Part.c index 433a574..361b236 100644 --- a/src/H5Part.c +++ b/src/H5Part.c @@ -1347,7 +1347,6 @@ _H5Part_read_attrib ( herr_t herr; hid_t attrib_id; - hid_t space_id; hid_t type_id; #ifdef H5PART_HAVE_HDF5_18 @@ -1363,15 +1362,9 @@ _H5Part_read_attrib ( type_id = H5Aget_type ( attrib_id ); if ( type_id < 0 ) return HANDLE_H5A_GET_TYPE_ERR; - space_id = H5Aget_space ( attrib_id ); - if ( space_id < 0 ) return HANDLE_H5A_GET_SPACE_ERR; - herr = H5Aread ( attrib_id, type_id, attrib_value ); if ( herr < 0 ) return HANDLE_H5A_READ_ERR; - herr = H5Sclose ( space_id ); - if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; - herr = H5Tclose ( type_id ); if ( herr < 0 ) return HANDLE_H5T_CLOSE_ERR; diff --git a/test/coords.F90 b/test/coords.F90 new file mode 100644 index 0000000..60c4d3a --- /dev/null +++ b/test/coords.F90 @@ -0,0 +1,97 @@ +program H5BlockCoordsTest + implicit none + +#ifdef PARALLEL_IO + include 'mpif.h' +#endif + include 'H5PartF.h' + +#ifdef PARALLEL_IO + integer :: ierr, comm +#endif + integer*8 :: file_id, status, i + real*8, allocatable :: r8buf(:,:,:), r8buf3(:,:,:,:), coords(:) + real*8 :: x, y, z + +#ifdef PARALLEL_IO + call MPI_INIT(ierr) + comm = MPI_COMM_WORLD +#endif + + ! this enables level 4 ("debug") messages to be + ! printed by the H5Part library + ! (4_8 is the literal for an integer*8 with value 4) + status = h5pt_set_verbosity_level (4_8) + + ! open the a file called 'test.h5' in parallel for writing +#ifdef PARALLEL_IO + file_id = h5pt_openw_par_align ('test.h5', comm, 1048576_8, "vfd_mpiposix") +#else + file_id = h5pt_openw_align ('test.h5', 1048576_8, "vfd_mpiposix") +#endif + + status = h5bl_define3dlayout(file_id, 1_8, 30_8, 1_8, 30_8, 1_8, 30_8) + + ! in the Fortran API, steps start at 1 + status = h5pt_setstep (file_id, 1_8) + + ! create fake data + allocate(r8buf(30,30,30)) + allocate(r8buf3(30,30,30,3)) + allocate(coords(30)) + x = 1.0 + y = 2.0 + z = 3.0 + + ! write the data + status = h5bl_3d_write_scalar_field_r8(file_id, "x", r8buf(1,1,1)) + status = h5bl_3d_set_field_origin(file_id, "x", x, y, z) + status = h5bl_3d_set_field_spacing(file_id, "x", x, y, z) + + status = h5bl_3d_write_3dvector_field_r8(file_id, "v", r8buf3(1,1,1,1), r8buf3(1,1,1,2), r8buf3(1,1,1,3)) + status = h5bl_3d_set_field_origin(file_id, "v", x, y, z) + status = h5bl_3d_set_field_spacing(file_id, "v", x, y, z) + + ! create fake coordinates + do i = 1, 30 + coords(i) = 3*i + enddo + status = h5bl_3d_set_field_xcoords(file_id, "v", coords, 30_8) + do i = 1, 30 + coords(i) = 3*i + 1 + enddo + status = h5bl_3d_set_field_ycoords(file_id, "v", coords, 30_8) + do i = 1, 30 + coords(i) = 3*i + 2 + enddo + status = h5bl_3d_set_field_zcoords(file_id, "v", coords, 30_8) + + ! read fake coordinates + do i = 1, 30 + coords(i) = -1 + enddo + status = h5bl_3d_get_field_xcoords(file_id, "v", coords, 30_8) + write(*, *) coords + !write(*, "I3") ( coords(i), i=1, 30 ) + do i = 1, 30 + coords(i) = -1 + enddo + status = h5bl_3d_get_field_ycoords(file_id, "v", coords, 30_8) + write(*, *) coords + !write(*, "I3") ( coords(i), i=1, 30 ) + do i = 1, 30 + coords(i) = -1 + enddo + status = h5bl_3d_get_field_zcoords(file_id, "v", coords, 30_8) + write(*, *) coords + !write(*, "I3") ( coords(i), i=1, 30 ) + + ! close the file + status = h5pt_close (file_id) + +#ifdef PARALLEL_IO + call MPI_FINALIZE(ierr) +#endif + +end program H5BlockCoordsTest +