#ifdef HAS_HDF5 #include "hdf5.h" #endif #include "double3.h" #include #include #include #include #include #include #include bool is_hdf5(std::string file_name) { std::ifstream file(file_name, std::ifstream::binary); const char hdf5_magic[] = "\x89HDF\x0d\x0a\x1a\x0a"; char buffer[8]; file.read(buffer, 8); if (!file) throw std::runtime_error("Unable to read file " + file_name); bool result = (memcmp(buffer, hdf5_magic, 8)==0); file.close(); return result; } void ascii_read(const std::string file_name, int& step_num, int& N, double& t, double **m, double3 **x, double3 **v) { char rest[512]; int result; std::ifstream file(file_name); if (!file.good()) throw std::runtime_error("File " + file_name + " not found."); std::string str; std::getline(file, str); result = sscanf(str.c_str(), "%d%s", &step_num, rest); if (result!=1) throw std::runtime_error("Error parsing line 1: expected one integer"); std::getline(file, str); result = sscanf(str.c_str(), "%d%s", &N, rest); if (result!=1) throw std::runtime_error("Error parsing line 2: expected one integer"); std::getline(file, str); result = sscanf(str.c_str(), "%lf%s", &t, rest); if (result!=1) throw std::runtime_error("Error parsing line 3: expected one real number"); *m = new double[N]; *x = new double3[N]; *v = new double3[N]; int i = -1; while (std::getline(file, str)) { if (++i > N) throw std::runtime_error("Error parsing line " + std::to_string(i+4) + ": particle out of range"); result = sscanf(str.c_str(), "%*s %lf %lf %lf %lf %lf %lf %lf%s", &(*m)[i], &(*x)[i][0], &(*x)[i][1], &(*x)[i][2], &(*v)[i][0], &(*v)[i][1], &(*v)[i][2], rest); } file.close(); } 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) { auto file = std::ofstream(file_name); if (!file.is_open()) throw std::runtime_error("Cannot open file for output"); int id_width = (int)log10(N-1) + 1; char string_template[256], output_string[256]; file << step_num << '\n'; file << N << '\n'; file.precision(16); file << std::scientific << t << '\n'; 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); for (int i=0; i step_num_arr; for (unsigned int i=0; i& pot, const double3 *acc, const double3 *jrk, const int extra_mode=0, const bool use_double_precision=true) { #ifdef HAS_HDF5 hid_t file_id, group_id, attribute_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); bool write_pot = (extra_mode ) & 1; bool write_acc = (extra_mode >> 1) & 1; bool write_jrk = (extra_mode >> 2) & 1; if (write_pot) write_dataset("POT", 1, (double*)pot.data()); if (write_acc) write_dataset("ACC", 2, (double*)acc); if (write_jrk) write_dataset("JRK", 2, (double*)jrk); H5Gclose(group_id); H5Fclose(file_id); H5close(); // If we don't do that (HDF5 1.10.5) then the file isn't really closed... #else throw std::runtime_error("h5_write was called but compiled without HDF5 support"); #endif }