Skip to Content

Работа с HDF5 в Фортране

HDF5 — удобный формат для хранения и использования данных вычислительных экспериментов. Он может использоваться с языками C/C++, Fortran-90 и свежее, Python; доступен для использования в среде Matlab; отображать данные, хранящиеся в данном формате может MathGL.

В этой заметке я хочу постепенно описать работу с HDF5 в Fortran. Основная информация почёрпнута с сайта The HDF group.

Общая информация

Как следует из названия (Hierarchical Data Format), формат предусматривает размещение данных в иерархическом виде по принципу файловой системы. Файл данных инкапсулирует такие объекты, как группы (groups — аналог каталогов) и данные (dataset). Каждый объект может быть помечен произвольными атрибутами, описывающими его. Допускаются вложенные группы. Вся структура начинается с корневой группы, которая присутствует по умолчанию в hdf-файле и её не требуется создавать.

Библиотека и программы

Рабочая среда HDF5 с точки зрения Fortran состоит из ряда модулей, основным из которых является hdf5 и некоторых вспомогательных утилит. Начинать следует с использования hdfview (http://www.hdfgroup.org/hdf-java-html/hdfview/index.html), написанной на Java программы для просмотра hdf5-файлов. На этапе освоения и отладки программ она позволит контролировать правильность создаваемых файлов.

Сама библиотека может быть взята с официального сайта и собрана, либо, в случае Linux, есть большая вероятность, что она присутствует в дистрибутиве. У меня на ALT Linux последовательная библиотека (существует также и параллельный вариант) ставится командой

apt-get install libhdf5-6-seq libhdf5-devel

Для компиляции программы, содержащей hdf5-инструкции, если соответствующие пути не прописаны, необходимо указывать пути к модулям (-I инструкция), библиотеке (-L) и саму библиотеку (-l). Таким образом типичная команда компиляции будет иметь вид

gfortran myhdf5.f90 -I /usr/lib/hdf5-seq/include/ -L /usr/lib/hdf5-seq/lib/ -l hdf5_fortran

Подключение HDF5

Как уже было сказано, процедуры и константы, обеспечивающие работу с HDF5-файлами, описываются в соответствующих модулях. Однако подключать достаточно один модуль hdf5, на остальные он ссылается сам. Сама работа с hdf начинается с инициализации hdf-режима и заканчивается выходом из указанного режима. Данные действия осуществляются процедурами h5open_f и h5close_f:

program testHDF5

  use hdf5

  implicit none

  integer :: ierr

! Начинаем работу с HDF5
call h5open_f(ierr)

! Действия с HDF5

! Завершаем работу с HDF5
call h5close_f(ierr)

end

Замечание. Все записанные в этом примере операторы обязательно присутствуют в любой программе, поэтому в примерах ниже я часто буду их пропускать и записывать только описания необходимых переменных и код для раздела «Действия с HDF5».

Открытие HDF5 файла

Открытие файла на чтение или запись осуществляется процедурами h5fcreate_f или h5fopen_f; закрытие — h5fclose_f.

Следует отметить, что именование процедур для работы с HDF5 следует жёстким правилам. Так, префикс h5 (HDF5) и суффикс _f (Fortran) присутствуют в обязательном порядке в именах всех процедур. Второй префикс определяет объект, с которым работает данная процедура: f означает файл. В предыдущем разделе описаны функции, относящиеся ко всей работе с HDF5 без выделения конкретного объекта, потому в их именах второй префикс отсутствует.

Рассмотрим подробнее функции работы с файлами.

h5fcreate_f(filename, mode, file_id, ierr)

Здесь filename — символьная переменная или константа, задающая имя файла;
mode — предопределённая константа, определяющая режим создания и открытия файла;
file_id — файловый дескриптор, который используется остальными процедурами, который представляет собой целую переменную разновидности hid_t (Hdf IDentifier Type);
ierr — целая переменная для возвращения кода ошибки, присутствует во всех процедурах.
Эта процедура создаёт и открывает файл.
В ней предусмотрены два режима создания файла: h5f_acc_trunc (_acc — третий суффикс (access)) говорит о том, что если файл с таким именем уже существует, он будет удалён и на его месте создан новый (truncate); h5f_acc_excl остановит работу и вернёт ошибку, если файл уже существует (exclusive).

Работу с уже существующими файлами, данные из которых требуется читать или куда будем дописывать данные следует начинать с процедуры

h5fopen_f(filename, mode, file_id, ierr)

Параметры процедуры те же, что и для предыдущей, но режимы открытия файла могут принимать иные значения:
h5f_acc_rdonly (ReaD only) — файл открывается только на чтение или h5f_acc_rdwr (Read and WRite) — файл открывается для чтения и записи.

По завершении работы с файлом его следует закрыть:

h5fclose_f(file_id, ierr)

Таким образом, типичная работа с новым файлом может выглядеть как

  integer (hid_t) :: file_id
  character (15) :: fname="my_hdf5_file.h5"

call h5fcreate_f(fname, h5f_acc_trunc, file_id, ierr)

! Действия с HDF5 данными

call h5fclose_f(file_id, ierr)

Работа с группами

Группы в HDF5 выполняют ту же роль, что и каталоги в файловой системе. Это означает, что объекты данных располагаются внутри групп, сами группы могут быть вложенными, по умолчанию присутствует никак не называемая корневая группа.

Рассмотрим следующие функции работы с группами: h5gcreate_f, h5gopen_f, h5gclose_f, h5gget_info_f, h5gget_info_by_idx_f, h5gget_info_by_name_f.

Работа с данными. Выделение места

Сложность внутренней структуры HDF5 файла приводит к необходимости двухэтапной работы по размещению данных в нём. Вначале выделяется место под данные (dataspace) указанного типа, после чего данные могут быть размещены.

Выделение места (или пространства — Space) под данные производится рядом процедур, из которых рассмотрим h5screate_f, h5scopy_f, h5screate_simple_f, h5sclose_f.

h5screate_f отвечает в первую очередь за выделение и открытие для записи пространства под скаляр:

h5screate_f(classtype, space_id, ierr)

где classtype — константа, определяющая класс выделяемого пространства, принимает значение h5s_scalar_f для скаляра; space_id — возвращаемый дескриптор пространства данных, он имеет целый тип класс hid_t.

h5screate_simple_f выделяет и открывает для записи пространство под массив простого типа.

h5screate_simple_f(rank, dims, space_id, ierr)

параметры: rank — константа, переменная и или арифметическое выражение целого типа, задающие ранг массива, под который выделяется место; dims — одномерный массив целого типа класса hsize_t, описывающий конфигурацию массива, для которого выделяется пространство.

h5scopy_f выделяет новое пространство того же размера, что уже задано и возвращает новый дескриптор:

h5scopy_f(space_id, new_space_id, ierr)

Здесь space_id — дескриптор существующего пространства; new_space_id — возвращаемый дескриптор вновь выделенного пространства. Дескрипторы сохраняются в переменные целого типа класса hid_t.

По окончании работы с вновь созданным пространством, его следует закрыть:

h5sclose_f(space_id, ierr)

Работа с данными. Запись и чтение

h5dcreate_f, h5dopen_f, h5dclose_f, h5dread_f, h5dwrite_f.

h5dcreate_f(file_id, name, classtype, space_id, data_id, ierr)
h5dopen_f(file_id, name, data_id, ierr)
h5dclose_f(data_id, ierr)
h5dwrite_f(data_id, mem_type_id, buf, dims, ierr)
h5dread_f(data_id, mem_type_id, buf, dims, ierr)

Атрибуты