phigrape/io.cpp

154 lines
6.3 KiB
C++

#include "hdf5.h"
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>
struct double3 {double x,y,z;
};
void ascii_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, int precision=10)
{
int id_width = (int)log10(N-1) + 1;
char string_template[256];
sprintf(string_template, "%%0%dd%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE%%%d.%dE\n", id_width, precision+7, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision, precision+8, precision);
printf("%d\n", step_num);
printf("%d\n", N);
printf("%.16E\n", t);
for (int i=0; i<N; i++) {
printf(string_template, i, m[i], x[i].x, x[i].y, x[i].z, v[i].x, v[i].y, v[i].z);
}
}
void h5_write(const std::string file_name, const int step_num, const int N, const double t, const double *m, const double3 *x, const double3 *v, const double *pot, const double3 *acc, const double3 *jrk, const int write_mode=0, const bool use_double_precision=true)
{
bool write_pot = (write_mode )%2;
bool write_acc = (write_mode>>1)%2;
bool write_jrk = (write_mode>>2)%2;
hid_t file_id, group_id, attribute_id, dataset_id, dataspace_id;
hsize_t dims[2] = {(hsize_t)N, 3};
hid_t h5_float_type;
if (use_double_precision) h5_float_type = H5T_IEEE_F64LE;
else h5_float_type = H5T_IEEE_F32LE;
file_id = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
char group_name[32];
sprintf(group_name, "/Step#%d", step_num);
group_id = H5Gcreate2(file_id, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
dataspace_id = H5Screate(H5S_SCALAR);
attribute_id = H5Acreate2 (group_id, "Time", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
H5Awrite(attribute_id, H5T_NATIVE_DOUBLE, &t);
H5Sclose(dataspace_id);
auto write_dataset = [&](const char dataset_name[], int ndims, double *data) {
hid_t dataspace_id = H5Screate_simple(ndims, dims, NULL);
char dataset_path[32];
sprintf(dataset_path, "%s/%s", group_name, dataset_name);
hid_t dataset_id = H5Dcreate2(file_id, dataset_path, h5_float_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
H5Dclose(dataset_id);
H5Sclose(dataspace_id);
};
write_dataset("MASS", 1, (double*)m);
write_dataset("X", 2, (double*)x);
write_dataset("V", 2, (double*)v);
if (write_pot) write_dataset("POT", 1, (double*)pot);
if (write_acc) write_dataset("ACC", 2, (double*)acc);
if (write_jrk) write_dataset("JRK", 2, (double*)jrk);
H5Gclose(group_id);
H5Fclose(file_id);
}
void h5_read(const std::string file_name, int *step_num, int *N, double *t, double m[], double3 x[], double3 v[])
{
// Open file and root group; count number of top level objects
hid_t file_id = H5Fopen(file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
hid_t group_id = H5Gopen2(file_id, "/", H5P_DEFAULT);
H5G_info_t object_info;
H5Gget_info(group_id, &object_info);
// Iterate over objects and add the number of each "step" group into a vector
std::vector<int> step_num_arr;
for (int i=0; i<object_info.nlinks; i++) {
char name_cstr[256];
H5Gget_objname_by_idx(group_id, i, name_cstr, 256);
std::string name(name_cstr);
if (name.substr(0, 5) == "Step#") step_num_arr.push_back(std::stoi(name.substr(5, std::string::npos)));
}
// Find the highest step in the file
*step_num = *max_element(step_num_arr.begin(), step_num_arr.end());
// Prepare to read the data sets dimensionality data.
char path[256];
hid_t attr_id, dataset_id, dataspace_id;
int ndims;
hsize_t dims[2];
sprintf(path, "/Step#%d", *step_num);
attr_id = H5Aopen_by_name(file_id, path, "Time", H5P_DEFAULT, H5P_DEFAULT);
H5Aread(attr_id, H5T_NATIVE_DOUBLE, t);
sprintf(path, "/Step#%d/MASS", *step_num);
dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT);
dataspace_id = H5Dget_space(dataset_id);
ndims = H5Sget_simple_extent_ndims(dataspace_id);
if (ndims != 1)
throw std::runtime_error("Dataset MASS in Step#" + std::to_string(*step_num) + " of file " + file_name + " is " + std::to_string(ndims) + "-dimensional (expected 1-dimensional)");
H5Sget_simple_extent_dims(dataspace_id, dims, NULL);
H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, m);
*N = dims[0];
sprintf(path, "/Step#%d/X", *step_num);
dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT);
dataspace_id = H5Dget_space(dataset_id);
ndims = H5Sget_simple_extent_ndims(dataspace_id);
if (ndims != 2) throw std::runtime_error("Bad dimensionality");
H5Sget_simple_extent_dims(dataspace_id, dims, NULL);
if ((dims[0] != *N) || (dims[1] != 3)) throw std::runtime_error("Bad dimensionality");
H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (double*)x);
sprintf(path, "/Step#%d/V", *step_num);
dataset_id = H5Dopen2(file_id, path, H5P_DEFAULT);
dataspace_id = H5Dget_space(dataset_id);
ndims = H5Sget_simple_extent_ndims(dataspace_id);
if (ndims != 2) throw std::runtime_error("Bad dimensionality");
H5Sget_simple_extent_dims(dataspace_id, dims, NULL);
if ((dims[0] != *N) || (dims[1] != 3)) throw std::runtime_error("Bad dimensionality");
H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, (double*)v);
}
int main()
{
// double3 aaa;
// double pot;
std::string file_name = "new_file.h5";
int N = 25;
double3 x[N];
for (int i=0; i<N; i++) {
x[i].x=i+0.01;
x[i].y=i+0.02;
x[i].z=i+0.03;
}
double m[N];
double3 v[N];
int step_num;
double t;
h5_write("123.h5", 17, N, 123.987, (double*)x, x, x, (double*)x, x, x, 7, true);
h5_read("123.h5", &step_num, &N, &t, m, x, v);
printf("%d %d %f\n", step_num, N, t);
ascii_write("123.dat", 0, N, t, m, x, v, 10);
// h5_write(file_name, 34, 987.654, N, (double*)x, x, x, (double*)x, x, x, 7);
// h5_read(file_name, &N, (double*)x, x, x);
// printf("aaaa %d %d %d\n", ndims, dims[0], dims[1]);
}