b8a7e0686d
- iterators revisited
594 lines
18 KiB
C
594 lines
18 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h> /* va_arg - System dependent ?! */
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <hdf5.h>
|
|
|
|
#ifndef WIN32
|
|
#include <unistd.h>
|
|
#else /* WIN32 */
|
|
#include <io.h>
|
|
#define open _open
|
|
#define close _close
|
|
#endif /* WIN32 */
|
|
|
|
#include "h5core/h5_core.h"
|
|
#include "H5Part.h"
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
Set the number of particles for the current time-step.
|
|
After you call this subroutine, all subsequent
|
|
operations will assume this number of particles will be written.
|
|
|
|
For the parallel library, the \c nparticles value is the number of
|
|
particles that the \e individual task will write. You can use
|
|
a different value on different tasks.
|
|
This function uses an \c MPI_Allgather
|
|
call to aggregate each tasks number of particles and determine
|
|
the appropiate offsets. Because of the use of this MPI collective,
|
|
it is advisable to call this function as
|
|
few times as possible when running at large concurrency.
|
|
|
|
This function assumes that your particles' data fields are in stored in
|
|
contiguous 1D arrays.
|
|
For instance, the fields \e x and \e y for your particles are stored
|
|
in separate arrays \c x[] and \c y[].
|
|
|
|
If instead you store your particles as tuples, so that the values
|
|
are arranged \f$ x_1,y_1,x_2,y_2\f$... than you need to setup striding
|
|
(in this case with value 2) using \ref H5PartSetNumParticlesStrided.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartSetNumParticles (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
h5_size_t nparticles /*!< [in] Number of particles */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_size_t stride = 1;
|
|
h5_err_t h5err = h5u_set_num_particles( f, nparticles, stride );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
Set the number of particles for the current time-step.
|
|
After you call this subroutine, all subsequent
|
|
operations will assume this number of particles will be written.
|
|
|
|
For the parallel library, the \c nparticles value is the number of
|
|
particles that the \e individual task will write. You can use
|
|
a different value on different tasks.
|
|
This function uses an \c MPI_Allgather
|
|
call to aggregate each tasks number of particles and determine
|
|
the appropiate offsets. Because of the use of this MPI collective,
|
|
it is advisable to call this function as
|
|
few times as possible when running at large concurrency.
|
|
|
|
This function assumes that your particles' data fields are
|
|
stored tuples. For instance, the fields \e x and \e y of your
|
|
particles are arranged \f$x_1,y_1,x_2,y_2\f$... in a single data
|
|
array. In this example, the stride value would be 2.
|
|
|
|
If you instead have a separate array for each fields,
|
|
such as \c x[] and \c y[],
|
|
use \ref H5PartSetNumParticles.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartSetNumParticlesStrided (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
h5_size_t nparticles, /*!< [in] Number of particles */
|
|
h5_size_t stride /*!< [in] Stride value (e.g. number of fields in the particle array) */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_set_num_particles( f, nparticles, stride );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
Define the chunk \c size and enables chunking in the underlying
|
|
HDF5 layer.
|
|
|
|
Note that this policy wastes disk space, but can improve write
|
|
bandwidth on parallel filesystems that are sensitive to write alignment
|
|
(e.g. lustre). It is only recommended when using the MPI-POSIX or MPI-IO
|
|
independent VFDs (see \ref H5OpenFile).
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartSetChunk (
|
|
h5_file_t *f,
|
|
h5_size_t size
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_set_chunk( f, size );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_data
|
|
|
|
Write array of 64 bit floating point data to file.
|
|
|
|
After setting the number of particles with \c H5PartSetNumParticles() and
|
|
the current timestep using \c H5SetStep(), you can start writing datasets
|
|
into the file. Each dataset has a name associated with it (chosen by the
|
|
user) in order to facilitate later retrieval. The name of the dataset is
|
|
specified in the parameter \c name, which must be a null-terminated string.
|
|
|
|
There are no restrictions on naming of datasets, but it is useful to arrive
|
|
at some common naming convention when sharing data with other groups.
|
|
|
|
The writing routines also implicitly store the datatype of the array so that
|
|
the array can be reconstructed properly on other systems with incompatible
|
|
type representations.
|
|
|
|
All data that is written after setting the timestep is associated with that
|
|
timestep. While the number of particles can change for each timestep, you
|
|
cannot change the number of particles in the middle of a given timestep.
|
|
|
|
The data is committed to disk before the routine returns.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartWriteDataFloat64 (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const char *name, /*!< [in] Name to associate array with */
|
|
const h5_float64_t *data /*!< [in] Array to commit to disk */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_write_data( f, name, (void*)data, H5T_NATIVE_DOUBLE );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_data
|
|
|
|
Write array of 32 bit floating point data to file.
|
|
|
|
After setting the number of particles with \c H5PartSetNumParticles() and
|
|
the current timestep using \c H5SetStep(), you can start writing datasets
|
|
into the file. Each dataset has a name associated with it (chosen by the
|
|
user) in order to facilitate later retrieval. The name of the dataset is
|
|
specified in the parameter \c name, which must be a null-terminated string.
|
|
|
|
There are no restrictions on naming of datasets, but it is useful to arrive
|
|
at some common naming convention when sharing data with other groups.
|
|
|
|
The writing routines also implicitly store the datatype of the array so that
|
|
the array can be reconstructed properly on other systems with incompatible
|
|
type representations.
|
|
|
|
All data that is written after setting the timestep is associated with that
|
|
timestep. While the number of particles can change for each timestep, you
|
|
cannot change the number of particles in the middle of a given timestep.
|
|
|
|
The data is committed to disk before the routine returns.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartWriteDataFloat32 (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const char *name, /*!< [in] Name to associate array with */
|
|
const h5_float32_t *data /*!< [in] Array to commit to disk */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_write_data( f, name, (void*)data, H5T_NATIVE_FLOAT );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_data
|
|
|
|
Write array of 64 bit integer data to file.
|
|
|
|
After setting the number of particles with \c H5PartSetNumParticles() and
|
|
the current timestep using \c H5SetStep(), you can start writing datasets
|
|
into the file. Each dataset has a name associated with it (chosen by the
|
|
user) in order to facilitate later retrieval. The name of the dataset is
|
|
specified in the parameter \c name, which must be a null-terminated string.
|
|
|
|
There are no restrictions on naming of datasets, but it is useful to arrive
|
|
at some common naming convention when sharing data with other groups.
|
|
|
|
The writing routines also implicitly store the datatype of the array so that
|
|
the array can be reconstructed properly on other systems with incompatible
|
|
type representations.
|
|
|
|
All data that is written after setting the timestep is associated with that
|
|
timestep. While the number of particles can change for each timestep, you
|
|
cannot change the number of particles in the middle of a given timestep.
|
|
|
|
The data is committed to disk before the routine returns.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartWriteDataInt64 (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const char *name, /*!< [in] Name to associate array with */
|
|
const h5_int64_t *data /*!< [in] Array to commit to disk */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_write_data ( f, name, (void*)data, H5T_NATIVE_INT64 );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_data
|
|
|
|
Write array of 32 bit integer data to file.
|
|
|
|
After setting the number of particles with \c H5PartSetNumParticles() and
|
|
the current timestep using \c H5SetStep(), you can start writing datasets
|
|
into the file. Each dataset has a name associated with it (chosen by the
|
|
user) in order to facilitate later retrieval. The name of the dataset is
|
|
specified in the parameter \c name, which must be a null-terminated string.
|
|
|
|
There are no restrictions on naming of datasets, but it is useful to arrive
|
|
at some common naming convention when sharing data with other groups.
|
|
|
|
The writing routines also implicitly store the datatype of the array so that
|
|
the array can be reconstructed properly on other systems with incompatible
|
|
type representations.
|
|
|
|
All data that is written after setting the timestep is associated with that
|
|
timestep. While the number of particles can change for each timestep, you
|
|
cannot change the number of particles in the middle of a given timestep.
|
|
|
|
The data is committed to disk before the routine returns.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartWriteDataInt32 (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const char *name, /*!< [in] Name to associate array with */
|
|
const h5_int32_t *data /*!< [in] Array to commit to disk */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_write_data ( f, name, (void*)data, H5T_NATIVE_INT32 );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_data
|
|
|
|
Read array of 64 bit floating point data from file.
|
|
|
|
When retrieving datasets from disk, you ask for them
|
|
by name. There are no restrictions on naming of arrays,
|
|
but it is useful to arrive at some common naming
|
|
convention when sharing data with other groups.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartReadDataFloat64 (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const char *name, /*!< [in] Name to associate dataset with */
|
|
h5_float64_t *data /*!< [out] Array of data */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_read_data ( f, name, data, H5T_NATIVE_DOUBLE );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_data
|
|
|
|
Read array of 32 bit floating point data from file.
|
|
|
|
When retrieving datasets from disk, you ask for them
|
|
by name. There are no restrictions on naming of arrays,
|
|
but it is useful to arrive at some common naming
|
|
convention when sharing data with other groups.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartReadDataFloat32 (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const char *name, /*!< [in] Name to associate dataset with */
|
|
h5_float32_t *data /*!< [out] Array of data */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_read_data ( f, name, data, H5T_NATIVE_FLOAT );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_data
|
|
|
|
Read array of 64 bit integer data from file.
|
|
|
|
When retrieving datasets from disk, you ask for them
|
|
by name. There are no restrictions on naming of arrays,
|
|
but it is useful to arrive at some common naming
|
|
convention when sharing data with other groups.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartReadDataInt64 (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const char *name, /*!< [in] Name to associate dataset with */
|
|
h5_int64_t *data /*!< [out] Array of data */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_read_data ( f, name, data, H5T_NATIVE_INT64 );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_data
|
|
|
|
Read array of 32 bit integer data from file.
|
|
|
|
When retrieving datasets from disk, you ask for them
|
|
by name. There are no restrictions on naming of arrays,
|
|
but it is useful to arrive at some common naming
|
|
convention when sharing data with other groups.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartReadDataInt32 (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const char *name, /*!< [in] Name to associate dataset with */
|
|
h5_int32_t *data /*!< [out] Array of data */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_read_data ( f, name, data, H5T_NATIVE_INT32 );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
Get the number of datasets that are stored at the current time-step.
|
|
|
|
\return number of datasets in current timestep or error code
|
|
*/
|
|
|
|
h5_ssize_t
|
|
H5PartGetNumDatasets (
|
|
h5_file_t *f /*!< [in] Handle to open file */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_get_num_datasets(f);
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
This reads the name of a dataset specified by it's index in the current
|
|
time-step.
|
|
|
|
If the number of datasets is \c n, the range of \c _index is \c 0 to \c n-1.
|
|
|
|
\result \c H5_SUCCESS
|
|
*/
|
|
h5_err_t
|
|
H5PartGetDatasetName (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const h5_id_t idx, /*!< [in] Index of the dataset */
|
|
char *name, /*!< [out] Name of dataset */
|
|
const h5_size_t len /*!< [in] Size of buffer \c name */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_get_dataset_info(f, idx, name, len, NULL, NULL);
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
Gets the name, type and number of elements of a dataset based on its
|
|
index in the current timestep.
|
|
|
|
Type is one of the following values:
|
|
|
|
- \c H5_FLOAT64_T (for \c h5_float64_t)
|
|
- \c H5_FLOAT32_T (for \c h5_float32_t)
|
|
- \c H5_INT64_T (for \c h5_int64_t)
|
|
- \c H5_INT32_T (for \c h5_int32_t)
|
|
|
|
\return \c H5_SUCCESS
|
|
*/
|
|
h5_err_t
|
|
H5PartGetDatasetInfo (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const h5_id_t idx, /*!< [in] Index of the dataset */
|
|
char *dataset_name, /*!< [out] Name of dataset */
|
|
const h5_size_t len_dataset_name,
|
|
/*!< [in] Size of buffer \c dataset_name */
|
|
h5_int64_t *type, /*!< [out] Type of data in dataset */
|
|
h5_size_t *nelem /*!< [out] Number of elements. */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_get_dataset_info(f, idx, dataset_name, len_dataset_name, type, nelem);
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
This function returns the number of particles in this processor's view,
|
|
if a view has been set.
|
|
|
|
If not, it returns the total number of particles across all processors
|
|
from the last \ref H5PartSetNumParticles call.
|
|
|
|
If you have neither set the number of particles
|
|
nor set a view, then this returns the total number of
|
|
particles in the first data set of the current time step.
|
|
Note that H5Part assumes that all data sets within a given time step
|
|
have the same number of particles (although the number particles can
|
|
vary across time steps).
|
|
|
|
If none of these conditions are met, an error is thrown.
|
|
|
|
\return number of particles in current timestep or an error
|
|
code.
|
|
*/
|
|
h5_ssize_t
|
|
H5PartGetNumParticles (
|
|
h5_file_t *f /*!< [in] Handle to open file */
|
|
) {
|
|
H5_API_ENTER;
|
|
CHECK_FILEHANDLE( f );
|
|
h5_ssize_t nparticels = h5u_get_num_particles( f );
|
|
H5_API_RETURN (nparticels);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
Reset the view.
|
|
|
|
\return \c H5_SUCCESS
|
|
*/
|
|
h5_err_t
|
|
H5PartResetView (
|
|
h5_file_t *f /*!< [in] Handle to open file */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_reset_view ( f );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
Check whether a view has been set, either automatically with
|
|
\ref H5PartSetNumParticles or manually with \ref H5PartSetView
|
|
or \ref H5PartSetViewIndices.
|
|
|
|
\return 0 for false or 1 for true
|
|
*/
|
|
h5_err_t
|
|
H5PartHasView (
|
|
h5_file_t *f /*!< [in] Handle to open file */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_has_view ( f );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
For parallel I/O or for subsetting operations on the datafile,
|
|
this function allows you to define a subset of the total
|
|
particle dataset to operate on.
|
|
The concept of "view" works for both serial
|
|
and for parallel I/O. The "view" will remain in effect until a new view
|
|
is set, or the number of particles in a dataset changes, or the view is
|
|
"unset" by calling \c H5PartSetView(file,-1,-1);
|
|
|
|
Before you set a view, \ref H5PartGetNumParticles will return the
|
|
total number of particles in the current time-step (even for the parallel
|
|
reads). However, after you set a view, it will return the number of
|
|
particles contained in the view.
|
|
|
|
The range is \e inclusive: the end value is the last index of the
|
|
data.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartSetView (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
h5_int64_t start, /*!< [in] Start particle */
|
|
h5_int64_t end /*!< [in] End particle */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_set_view ( f, start, end );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
For parallel I/O or for subsetting operations on the datafile,
|
|
this function allows you to define a subset of the total
|
|
dataset to operate on by specifying a list of indices.
|
|
The concept of "view" works for both serial
|
|
and for parallel I/O. The "view" will remain in effect until a new view
|
|
is set, or the number of particles in a dataset changes, or the view is
|
|
"unset" by calling \c H5PartSetViewIndices(NULL,0);
|
|
|
|
Before you set a view, the \c H5PartGetNumParticles() will return the
|
|
total number of particles in the current time-step (even for the parallel
|
|
reads). However, after you set a view, it will return the number of
|
|
particles contained in the view.
|
|
|
|
\return \c H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartSetViewIndices (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
const h5_id_t *indices, /*!< [in] List of indices */
|
|
h5_size_t nelems /*!< [in] Size of list */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_set_view_indices ( f, indices, nelems );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
Allows you to query the current view. Start and End
|
|
will be \c -1 if there is no current view established.
|
|
Use \c H5PartHasView() to see if the view is smaller than the
|
|
total dataset.
|
|
|
|
\return number of elements in the view or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartGetView (
|
|
h5_file_t *f, /*!< [in] Handle to open file */
|
|
h5_int64_t *start, /*!< [out] Start particle */
|
|
h5_int64_t *end /*!< [out] End particle */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_get_view( f, start, end );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|
|
/*!
|
|
\ingroup h5part_model
|
|
|
|
If it is too tedious to manually set the start and end coordinates
|
|
for a view, the \c H5SetCanonicalView() will automatically select an
|
|
appropriate domain decomposition of the data arrays for the degree
|
|
of parallelism and set the "view" accordingly.
|
|
|
|
\return H5_SUCCESS or error code
|
|
*/
|
|
h5_err_t
|
|
H5PartSetCanonicalView (
|
|
h5_file_t *f /*!< [in] Handle to open file */
|
|
) {
|
|
H5_API_ENTER;
|
|
h5_err_t h5err = h5u_set_canonical_view( f );
|
|
H5_API_RETURN (h5err);
|
|
}
|
|
|