-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
289 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
# h5fortran-MPI API | ||
|
||
This document provides a listing of h5fortran-mpi `public` scoped user-facing procedures and methods with a summary of their parameters. | ||
|
||
All examples assume: | ||
|
||
```fortran | ||
use h5mpi, only: hdf5_file, HSIZE_T, HID_T | ||
type(hdf5_file) :: h | ||
``` | ||
|
||
Query HDF5 library version: | ||
|
||
```fortran | ||
use h5mpi, only : hdf5version | ||
print *, hdf5version() | ||
``` | ||
|
||
## Open / close HDF5 file reference | ||
|
||
More than one HDF5 file can be open in a program, by declaring unique file handle (variable) like: | ||
|
||
```fortran | ||
type(hdf5_file) :: h1, h2, h3 | ||
``` | ||
|
||
```fortran | ||
call h%open(filename, action, mpi, comp_lvl) | ||
!! Opens hdf5 file | ||
character(*), intent(in) :: filename | ||
character(*), intent(in), optional :: action !< 'r', 'w', 'rw', 'r+' | ||
logical, intent(in) :: mpi !< .true.: use HDF5-MPI .false.: use serial HDF5 | ||
integer, intent(in), optional :: comp_lvl !< 0: no compression. 1-9: ZLIB compression, higher is more compressior | ||
``` | ||
|
||
```fortran | ||
call h%close(close_hdf5_interface) | ||
!! This must be called on each HDF5 file to flush buffers to disk | ||
!! data loss can occur if program terminates before this procedure | ||
!! | ||
!! close_hdf5_interface is when you know you have exactly one HDF5 file in your | ||
!! application, if true it closes ALL files, even those invoked directly from HDF5. | ||
logical, intent(in), optional :: close_hdf5_interface | ||
``` | ||
|
||
To avoid memory leaks or corrupted files, always "close()" all hDF5 files before STOPping the Fortran program. | ||
|
||
```fortran | ||
call h%flush() | ||
!! request operating system flush data to disk. | ||
``` | ||
|
||
## Disk variable (dataset) inquiry | ||
|
||
To allocate variables before reading data, inquire about dataset characteristics with these procedures. | ||
|
||
```fortran | ||
rank = h%ndim(dataset_name) | ||
character(*), intent(in) :: dataset_name | ||
``` | ||
|
||
Get disk dataset shape (1D vector) | ||
|
||
```fortran | ||
call h%shape(dataset_name, dims) | ||
character(*), intent(in) :: dataset_name | ||
integer(HSIZE_T), intent(out), allocatable :: dims(:) | ||
``` | ||
|
||
Dataset "dname" data class (i.e. integer, float, string, ...) | ||
|
||
```fortran | ||
integer :: class | ||
!! H5T_INTEGER_F, H5T_FLOAT_F, H5T_STRING_F | ||
class = h%class(dname) | ||
character(*), intent(in) :: dname | ||
``` | ||
|
||
Dataset "dname" datatype | ||
|
||
```fortran | ||
integer(HID_T) :: dtype | ||
!! H5T_NATIVE_REAL, H5T_NATIVE_DOUBLE, H5T_NATIVE_INTEGER, H5T_NATIVE_CHARACTER, H5T_STD_I64LE | ||
dtype = h%dtype(dname) | ||
character(*), intent(in) :: dname | ||
``` | ||
|
||
Does dataset "dname" exist in this HDF5 file? | ||
|
||
```fortran | ||
exists = h%exist(dname) | ||
character(*), intent(in) :: dname | ||
``` | ||
|
||
Is dataset "dname" contiguous on disk? | ||
|
||
```fortran | ||
tf = h%is_contig(dname) | ||
!! is dataset contiguous | ||
character(*), intent(in) :: dname | ||
``` | ||
|
||
Is dataset compact (< 64K) | ||
|
||
```fortran | ||
tf = h%is_compact(dname) | ||
!! is dataset compact layout | ||
character(*), intent(in) :: dname | ||
``` | ||
|
||
Is dataset chunked? | ||
|
||
```fortran | ||
tf = h%is_chunked(dname) | ||
!! is dataset chunked | ||
character(*), intent(in) :: dname | ||
``` | ||
|
||
Is this an HDF5 file? | ||
|
||
```fortran | ||
use h5mpi, only: is_hdf5 | ||
tf = is_hdf5('myfile.txt') !< probably false | ||
tf = is_hdf5('myfile.h5') !< true if a valid HDF5 file | ||
``` | ||
|
||
These are more advanced inquiries into the memory layout of the dataset, for advanced users: | ||
|
||
```fortran | ||
Layout = h%layout(dname) | ||
!! integer :: H5D_CONTIGUOUS_F, H5D_CHUNKED_F, H5D_VIRTUAL_F, H5D_COMPACT_F | ||
character(*), intent(in) :: dname | ||
``` | ||
|
||
```fortran | ||
call h%chunks(dname, chunk_size) | ||
character(*), intent(in) :: dname | ||
integer, intent(out) :: chunk_size(:) | ||
``` | ||
|
||
## create dataset softlink | ||
|
||
HDF5 can create dataset softlinks within an HDF5 file: | ||
|
||
```fortran | ||
call h%softlink(tgt, link) | ||
character(*), intent(in) :: tgt, & !< target path to link dataset | ||
link !< soft link path to create | ||
``` | ||
|
||
## file write operations | ||
|
||
Write data from memory to disk HDF5 dataset: | ||
When file has been opened for MPI collective read via: `%open(..., mpi=.true.)` the data is distributed | ||
via MPI to the workers. | ||
If overall dataset dimensions "dset_dims" is present, data is collectively gathered from the workers as per HDF5-MPI docs. | ||
Otherwise, h5fortran-mpi assumes that root has all the data to be written and ignores the workers. | ||
|
||
```fortran | ||
call h%write(dname, value, dset_dims, istart, iend, chunk_size, compact) | ||
!! write 0d..7d dataset | ||
character(*), intent(in) :: dname | ||
class(*), intent(in) :: value(..) !< array to write | ||
integer, intent(in), dimension(rank(value)), optional :: dset_dims | ||
integer, intent(in), optional, dimension(rank(value)) :: istart, iend !< array slicing for hyperslab | ||
integer, intent(in), optional :: chunk_size(rank(value)) !< override auto-chunking | ||
logical, intent(in), optional :: compact !< faster I/O for sub-64 kB datasets | ||
``` | ||
|
||
Write dataset attribute (e.g. units or instrument): | ||
|
||
```fortran | ||
call h%writeattr(dname, attr, attrval) | ||
character(*), intent(in) :: dname, attr !< dataset name, attribute name | ||
class(*), intent(in) :: attrval(:) !< character, real, integer | ||
``` | ||
|
||
## file read operations | ||
|
||
Read data from disk to memory: | ||
When file has been opened for MPI collective read via: `%open(..., mpi=.true.)` the data is distributed | ||
via MPI to the workers. | ||
For example, if no slicing is specified, the whole dataset is read by root and broadcast to the workers. | ||
If slicing is specified, the data is read and distributed among the workers as per HDF5-MPI docs. | ||
|
||
```fortran | ||
call h%read(dname, value, istart, iend) | ||
character(*), intent(in) :: dname | ||
class(*), intent(inout) :: value(..) !< read array to this ALLOCATED variable of rank 0d..7d | ||
integer, intent(in), optional, dimension(rank(value)) :: istart, iend !< array slicing | ||
``` | ||
|
||
Read dataset attribute into memory: | ||
|
||
```fortran | ||
call h%readattr(dname, attr, attrval) | ||
character(*), intent(in) :: dname, attr !< dataset name, attribute name | ||
class(*), intent(inout) :: attrval(:) !< character scalar; real vector, integer vector | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
cmake_minimum_required(VERSION 3.20...3.22) | ||
project(HDF5_build | ||
LANGUAGES C Fortran | ||
) | ||
|
||
option(hdf5_parallel "build HDF5 parallel MPI" on) | ||
|
||
if(NOT HDF5_VERSION) | ||
set(HDF5_VERSION 1.12.1) # default version to build | ||
endif() | ||
|
||
# --- system checks | ||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | ||
message(FATAL_ERROR "please specify where to install HDF5 under, like | ||
cmake -B build -DCMAKE_INSTALL_PREFIX=~/mylibs") | ||
endif() | ||
|
||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules/) | ||
|
||
|
||
if(NOT MPI_ROOT AND DEFINED ENV{MPI_ROOT}) | ||
set(MPI_ROOT $ENV{MPI_ROOT}) | ||
endif() | ||
|
||
if(CMAKE_SYSTEM_NAME STREQUAL Linux AND MPI_ROOT) | ||
set(ld_path $ENV{LD_LIBRARY_PATH}) | ||
cmake_path(CONVERT "${ld_path}" TO_CMAKE_PATH_LIST ld_path NORMALIZE) | ||
cmake_path(CONVERT "${MPI_ROOT}" TO_CMAKE_PATH_LIST MPI_ROOT NORMALIZE) | ||
|
||
if(NOT "${ld_path}" MATCHES "${MPI_ROOT}/lib") | ||
message(WARNING "${MPI_ROOT}/lib not found in LD_LIBRARY_PATH: $ENV{LD_LIBRARY_PATH} | ||
HDF5 build may fail due to bugs in HDF5 package CMake scripts. | ||
Fix this by adding to ~/.bashrc or similar: | ||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${MPI_ROOT}/lib") | ||
endif() | ||
endif() | ||
|
||
# HDF5 install fails to work (link) if prior HDF5 library is installed there | ||
find_library(_hdf5_libprior NAMES hdf5 PATHS ${CMAKE_INSTALL_PREFIX} PATH_SUFFIXES lib NO_DEFAULT_PATH NO_CACHE) | ||
find_path(_hdf5_incprior NAMES hdf5.h PATHS ${CMAKE_INSTALL_PREFIX} PATH_SUFFIXES include NO_DEFAULT_PATH NO_CACHE) | ||
find_program(_hdf5_binprior NAMES h5cc PATHS ${CMAKE_INSTALL_PREFIX} PATH_SUFFIXES bin NO_DEFAULT_PATH NO_CACHE) | ||
if(_hdf5_binprior) | ||
cmake_path(GET _hdf5_binprior PARENT_PATH _hdf5_binprior) | ||
else() | ||
set(_hdf5_binprior "") | ||
endif() | ||
if(_hdf5_libprior) | ||
cmake_path(GET _hdf5_libprior PARENT_PATH _hdf5_libprior) | ||
endif() | ||
if(_hdf5_libprior OR _hdf5_incprior OR _hdf5_binprior) | ||
message(FATAL_ERROR "HDF5 library already installed: | ||
${_hdf5_libprior} | ||
${_hdf5_incprior} | ||
${_hdf5_binprior} | ||
Please pick a new install location or completely remove the old HDF5 install directory. | ||
Otherwise, HDF5 will fail to link correctly with prior version and this version mixed.") | ||
endif() | ||
|
||
# --- commence HDF5 build/install | ||
include(${PROJECT_SOURCE_DIR}/../cmake/libraries.cmake) | ||
|
||
set_directory_properties(PROPERTIES EP_UPDATE_DISCONNECTED true) | ||
|
||
message(STATUS "Build / install HDF5 ${HDF5_VERSION} to ${CMAKE_INSTALL_PREFIX}") | ||
|
||
if(hdf5_parallel) | ||
find_package(MPI COMPONENTS C REQUIRED) | ||
include(${PROJECT_SOURCE_DIR}/../cmake/check_mpi.cmake) | ||
check_mpi_version() | ||
endif() | ||
|
||
include(${PROJECT_SOURCE_DIR}/../cmake/hdf5.cmake) | ||
|
||
# --- features | ||
include(FeatureSummary) | ||
|
||
add_feature_info(HDF5parallel hdf5_parallel "HDF5 MPI layer") | ||
|
||
feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES) |