diff --git a/src/common_io.c b/src/common_io.c index aba1595df6d59d13f0e1a1e2f879f4ab2248de84..e28496340f424405475e2b13bca19f960411c733 100644 --- a/src/common_io.c +++ b/src/common_io.c @@ -2492,3 +2492,47 @@ void io_make_snapshot_subdir(const char* dirname) { safe_checkdir(dirname, /*create=*/1); } } + +/** + * @brief Construct the file names for a single-file hdf5 snapshots and + * + * @param filename (return) The file name of the hdf5 snapshot. + * @param xmf_filename (return) The file name of the associated XMF file. + * @param use_time_label Are we using time labels for the snapshot indices? + * @param snapshots_invoke_stf Are we calling STF when dumping a snapshot? + * @param time The current simulation time. + * @param stf_count The counter of STF outputs. + * @param snap_count The counter of snapshot outputs. + * @param subdir The sub-directory in which the snapshots are written. + * @param basename The common part of the snapshot names. + */ +void io_get_snapshot_filename(char filename[1024], char xmf_filename[1024], + const int use_time_label, + const int snapshots_invoke_stf, const double time, + const int stf_count, const int snap_count, + const char* subdir, const char* basename) { + + int snap_number = -1; + if (use_time_label) + snap_number = (int)round(time); + else if (snapshots_invoke_stf) + snap_number = stf_count; + else + snap_number = snap_count; + + int number_digits = -1; + if (use_time_label) + number_digits = 6; + else + number_digits = 4; + + /* Are we using a sub-dir? */ + if (strlen(subdir) > 0) { + sprintf(filename, "%s/%s_%0*d.hdf5", subdir, basename, number_digits, + snap_number); + sprintf(xmf_filename, "%s/%s.xmf", subdir, basename); + } else { + sprintf(filename, "%s_%0*d.hdf5", basename, number_digits, snap_number); + sprintf(xmf_filename, "%s.xmf", basename); + } +} diff --git a/src/common_io.h b/src/common_io.h index bb1564cee5b673b0e8526401868de0855a10c194..2a6392dc69fe03f0fba5511ca6936e5d1e0ce8e9 100644 --- a/src/common_io.h +++ b/src/common_io.h @@ -174,4 +174,10 @@ void io_write_output_field_parameter(const char* filename); void io_make_snapshot_subdir(const char* dirname); +void io_get_snapshot_filename(char filename[1024], char xmf_filename[1024], + const int use_time_label, + const int snapshots_invoke_stf, const double time, + const int stf_count, const int snap_count, + const char* subdir, const char* basename); + #endif /* SWIFT_COMMON_IO_H */ diff --git a/src/engine.c b/src/engine.c index a2622f70d280abed2511e35f1d7fb7f15daf6273..ae82c8e03d5d25ee71bfe2b2b1411ee4f7af2cb1 100644 --- a/src/engine.c +++ b/src/engine.c @@ -3587,22 +3587,6 @@ void engine_dump_snapshot(struct engine *e) { engine_collect_stars_counter(e); #endif - /* Determine snapshot location */ - char snapshotBase[FILENAME_BUFFER_SIZE]; - if (strnlen(e->snapshot_subdir, PARSER_MAX_LINE_SIZE) > 0) { - if (snprintf(snapshotBase, FILENAME_BUFFER_SIZE, "%s/%s", - e->snapshot_subdir, - e->snapshot_base_name) >= FILENAME_BUFFER_SIZE) { - error( - "FILENAME_BUFFER_SIZE is too small for snapshot path and file name"); - } - } else { - if (snprintf(snapshotBase, FILENAME_BUFFER_SIZE, "%s", - e->snapshot_base_name) >= FILENAME_BUFFER_SIZE) { - error("FILENAME_BUFFER_SIZE is too small for snapshot file name"); - } - } - /* Dump (depending on the chosen strategy) ... */ #if defined(HAVE_HDF5) #if defined(WITH_MPI) @@ -3614,16 +3598,15 @@ void engine_dump_snapshot(struct engine *e) { } else { #if defined(HAVE_PARALLEL_HDF5) - write_output_parallel(e, snapshotBase, e->internal_units, e->snapshot_units, - e->nodeID, e->nr_nodes, MPI_COMM_WORLD, - MPI_INFO_NULL); + write_output_parallel(e, e->internal_units, e->snapshot_units, e->nodeID, + e->nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL); #else - write_output_serial(e, snapshotBase, e->internal_units, e->snapshot_units, - e->nodeID, e->nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL); + write_output_serial(e, e->internal_units, e->snapshot_units, e->nodeID, + e->nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL); #endif } #else - write_output_single(e, snapshotBase, e->internal_units, e->snapshot_units); + write_output_single(e, e->internal_units, e->snapshot_units); #endif #endif diff --git a/src/parallel_io.c b/src/parallel_io.c index 686b6ab600ffaf8ec14b3a011e263eb62536ea49..5f26423800357ecd8d5a8c81a94dfb047ff43e13 100644 --- a/src/parallel_io.c +++ b/src/parallel_io.c @@ -378,7 +378,7 @@ void read_array_parallel(hid_t grp, struct io_props props, size_t N, * @param N_total The total number of particles to write in this array. * @param snapshot_units The units used for the data in this snapshot. */ -void prepare_array_parallel(struct engine* e, hid_t grp, char* fileName, +void prepare_array_parallel(struct engine* e, hid_t grp, const char* fileName, FILE* xmfFile, char* partTypeGroupName, struct io_props props, long long N_total, const struct unit_system* snapshot_units) { @@ -1041,12 +1041,12 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units, * @brief Prepares a file for a parallel write. * * @param e The #engine. - * @param baseName The base name of the snapshots. * @param N_total The total number of particles of each type to write. * @param internal_units The #unit_system used internally. * @param snapshot_units The #unit_system used in the snapshots. */ -void prepare_file(struct engine* e, const char* baseName, long long N_total[6], +void prepare_file(struct engine* e, const char* fileName, + const char* xmfFileName, long long N_total[6], const struct unit_system* internal_units, const struct unit_system* snapshot_units) { @@ -1071,23 +1071,10 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6], int numFiles = 1; /* First time, we need to create the XMF file */ - if (e->snapshot_output_count == 0) xmf_create_file(baseName); + if (e->snapshot_output_count == 0) xmf_create_file(xmfFileName); /* Prepare the XMF file for the new entry */ - xmfFile = xmf_prepare_file(baseName); - - /* HDF5 File name */ - char fileName[FILENAME_BUFFER_SIZE]; - if (e->snapshot_int_time_label_on) - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%06i.hdf5", baseName, - (int)round(e->time)); - else if (e->snapshot_invoke_stf) { - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName, - e->stf_output_count); - } else { - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName, - e->snapshot_output_count); - } + xmfFile = xmf_prepare_file(xmfFileName); /* Open HDF5 file with the chosen parameters */ hid_t h_file = H5Fcreate(fileName, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); @@ -1301,7 +1288,6 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6], *its XMF descriptor * * @param e The engine containing all the system. - * @param baseName The common part of the snapshot file name. * @param internal_units The #unit_system used internally * @param snapshot_units The #unit_system used in the snapshots * @param mpi_rank The MPI rank of this node. @@ -1317,7 +1303,7 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6], * Calls #error() if an error occurs. * */ -void write_output_parallel(struct engine* e, const char* baseName, +void write_output_parallel(struct engine* e, const struct unit_system* internal_units, const struct unit_system* snapshot_units, int mpi_rank, int mpi_size, MPI_Comm comm, @@ -1389,9 +1375,18 @@ void write_output_parallel(struct engine* e, const char* baseName, ticks tic = getticks(); #endif + /* File names */ + char fileName[FILENAME_BUFFER_SIZE]; + char xmfFileName[FILENAME_BUFFER_SIZE]; + io_get_snapshot_filename(fileName, xmfFileName, e->snapshot_int_time_label_on, + e->snapshot_invoke_stf, e->time, e->stf_output_count, + e->snapshot_output_count, e->snapshot_subdir, + e->snapshot_base_name); + /* Rank 0 prepares the file */ if (mpi_rank == 0) - prepare_file(e, baseName, N_total, internal_units, snapshot_units); + prepare_file(e, fileName, xmfFileName, N_total, internal_units, + snapshot_units); MPI_Barrier(MPI_COMM_WORLD); @@ -1403,19 +1398,6 @@ void write_output_parallel(struct engine* e, const char* baseName, tic = getticks(); #endif - /* HDF5 File name */ - char fileName[FILENAME_BUFFER_SIZE]; - if (e->snapshot_int_time_label_on) - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%06i.hdf5", baseName, - (int)round(e->time)); - else if (e->snapshot_invoke_stf) { - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName, - e->stf_output_count); - } else { - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName, - e->snapshot_output_count); - } - /* Now write the top-level cell structure */ hid_t h_file_cells = 0, h_grp_cells = 0; if (mpi_rank == 0) { diff --git a/src/parallel_io.h b/src/parallel_io.h index 08588ee3d3292e5a765a9941c10f72e6aab82a2a..b816d1d7c6fa74cf1ec83bba2bbf768639811f17 100644 --- a/src/parallel_io.h +++ b/src/parallel_io.h @@ -44,7 +44,7 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units, int mpi_size, MPI_Comm comm, MPI_Info info, int nr_threads, int dry_run); -void write_output_parallel(struct engine* e, const char* baseName, +void write_output_parallel(struct engine* e, const struct unit_system* internal_units, const struct unit_system* snapshot_units, int mpi_rank, int mpi_size, MPI_Comm comm, diff --git a/src/serial_io.c b/src/serial_io.c index 74e936257589b57bf4e68c9f2a9abfe65bdd0246..58b8f284515086866c9dd4da4f0879800d5ee254 100644 --- a/src/serial_io.c +++ b/src/serial_io.c @@ -841,7 +841,6 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units, * @brief Writes an HDF5 output file (GADGET-3 type) with its XMF descriptor * * @param e The engine containing all the system. - * @param baseName The common part of the snapshot file name. * @param internal_units The #unit_system used internally * @param snapshot_units The #unit_system used in the snapshots * @param mpi_rank The MPI rank of this node. @@ -857,7 +856,7 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units, * Calls #error() if an error occurs. * */ -void write_output_serial(struct engine* e, const char* baseName, +void write_output_serial(struct engine* e, const struct unit_system* internal_units, const struct unit_system* snapshot_units, int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info) { @@ -914,16 +913,11 @@ void write_output_serial(struct engine* e, const char* baseName, /* File name */ char fileName[FILENAME_BUFFER_SIZE]; - if (e->snapshot_int_time_label_on) - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%06i.hdf5", baseName, - (int)round(e->time)); - else if (e->snapshot_invoke_stf) { - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName, - e->stf_output_count); - } else { - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName, - e->snapshot_output_count); - } + char xmfFileName[FILENAME_BUFFER_SIZE]; + io_get_snapshot_filename(fileName, xmfFileName, e->snapshot_int_time_label_on, + e->snapshot_invoke_stf, e->time, e->stf_output_count, + e->snapshot_output_count, e->snapshot_subdir, + e->snapshot_base_name); /* Compute offset in the file and total number of particles */ size_t N[swift_type_count] = {Ngas_written, Ndm_written, @@ -945,10 +939,10 @@ void write_output_serial(struct engine* e, const char* baseName, if (mpi_rank == 0) { /* First time, we need to create the XMF file */ - if (e->snapshot_output_count == 0) xmf_create_file(baseName); + if (e->snapshot_output_count == 0) xmf_create_file(xmfFileName); /* Prepare the XMF file for the new entry */ - xmfFile = xmf_prepare_file(baseName); + xmfFile = xmf_prepare_file(xmfFileName); /* Write the part corresponding to this specific output */ xmf_write_outputheader(xmfFile, fileName, e->time); diff --git a/src/serial_io.h b/src/serial_io.h index 1146e5f5fb9767f94c5e76195cabbc893db25e14..764bcf9ca571f06a0e3c9ba389079f072bd61d0f 100644 --- a/src/serial_io.h +++ b/src/serial_io.h @@ -45,7 +45,7 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units, double h, double a, int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info, int n_threads, int dry_run); -void write_output_serial(struct engine* e, const char* baseName, +void write_output_serial(struct engine* e, const struct unit_system* internal_units, const struct unit_system* snapshot_units, int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info); diff --git a/src/single_io.c b/src/single_io.c index bb4a548222f73817774faccdc0082d68bd7a48d0..2cc44cc59ad376b483bae87ebe922989ac1b9c8d 100644 --- a/src/single_io.c +++ b/src/single_io.c @@ -705,7 +705,6 @@ void read_ic_single(const char* fileName, * @brief Writes an HDF5 output file (GADGET-3 type) with its XMF descriptor * * @param e The engine containing all the system. - * @param baseName The common part of the snapshot file name. * @param internal_units The #unit_system used internally * @param snapshot_units The #unit_system used in the snapshots * @@ -717,7 +716,7 @@ void read_ic_single(const char* fileName, * Calls #error() if an error occurs. * */ -void write_output_single(struct engine* e, const char* baseName, +void write_output_single(struct engine* e, const struct unit_system* internal_units, const struct unit_system* snapshot_units) { @@ -777,22 +776,18 @@ void write_output_single(struct engine* e, const char* baseName, /* File name */ char fileName[FILENAME_BUFFER_SIZE]; - if (e->snapshot_int_time_label_on) - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%06i.hdf5", baseName, - (int)round(e->time)); - else if (e->snapshot_invoke_stf) { - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName, - e->stf_output_count); - } else - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName, - e->snapshot_output_count); + char xmfFileName[FILENAME_BUFFER_SIZE]; + io_get_snapshot_filename(fileName, xmfFileName, e->snapshot_int_time_label_on, + e->snapshot_invoke_stf, e->time, e->stf_output_count, + e->snapshot_output_count, e->snapshot_subdir, + e->snapshot_base_name); /* First time, we need to create the XMF file */ - if (e->snapshot_output_count == 0) xmf_create_file(baseName); + if (e->snapshot_output_count == 0) xmf_create_file(xmfFileName); /* Prepare the XMF file for the new entry */ FILE* xmfFile = 0; - xmfFile = xmf_prepare_file(baseName); + xmfFile = xmf_prepare_file(xmfFileName); /* Write the part corresponding to this specific output */ xmf_write_outputheader(xmfFile, fileName, e->time); diff --git a/src/single_io.h b/src/single_io.h index c341fda920e25d9c109e85e6b0967355f09fa6be..24e6bd4e3d0d4181a8e73ae838931256e5687f8d 100644 --- a/src/single_io.h +++ b/src/single_io.h @@ -40,7 +40,7 @@ void read_ic_single(const char* fileName, int with_cosmology, int cleanup_h, int cleanup_sqrt_a, double h, double a, int nr_threads, int dry_run); -void write_output_single(struct engine* e, const char* baseName, +void write_output_single(struct engine* e, const struct unit_system* internal_units, const struct unit_system* snapshot_units); diff --git a/src/xmf.c b/src/xmf.c index d3d88627b8fe0c0e40df53c6eb79960ef82f1519..dcba990005c71f9da885d61575189910953d1af5 100644 --- a/src/xmf.c +++ b/src/xmf.c @@ -51,15 +51,13 @@ static const char* xmf_basename(const char* hdfFileName) { /** * @brief Prepare the XMF file corresponding to a snapshot. * - * @param baseName The common part of the file name. + * @param fileName The name of the file. */ -FILE* xmf_prepare_file(const char* baseName) { +FILE* xmf_prepare_file(const char* fileName) { char buffer[1024]; - char fileName[FILENAME_BUFFER_SIZE]; char tempFileName[FILENAME_BUFFER_SIZE]; - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s.xmf", baseName); - snprintf(tempFileName, FILENAME_BUFFER_SIZE, "%s_temp.xmf", baseName); + snprintf(tempFileName, FILENAME_BUFFER_SIZE, "%s.temp", fileName); FILE* xmfFile = fopen(fileName, "r"); FILE* tempFile = fopen(tempFileName, "w"); @@ -101,11 +99,11 @@ FILE* xmf_prepare_file(const char* baseName) { * * @todo Exploit the XML nature of the XMF format to write a proper XML writer * and simplify all the XMF-related stuff. + * + * @param fileName The name of the file. */ -void xmf_create_file(const char* baseName) { +void xmf_create_file(const char* fileName) { - char fileName[FILENAME_BUFFER_SIZE]; - snprintf(fileName, FILENAME_BUFFER_SIZE, "%s.xmf", baseName); FILE* xmfFile = fopen(fileName, "w"); if (xmfFile == NULL) error("Unable to create XMF file."); @@ -134,7 +132,8 @@ void xmf_create_file(const char* baseName) { * @param hdfFileName The name of the HDF5 file corresponding to this output. * @param time The current simulation time. */ -void xmf_write_outputheader(FILE* xmfFile, char* hdfFileName, float time) { +void xmf_write_outputheader(FILE* xmfFile, const char* hdfFileName, + float time) { /* Write end of file */ fprintf(xmfFile, "<!-- XMF description for file: %s -->\n", hdfFileName); @@ -171,7 +170,7 @@ void xmf_write_outputfooter(FILE* xmfFile, int output, float time) { * @param N The number of particles to write. * @param ptype The particle type we are writing. */ -void xmf_write_groupheader(FILE* xmfFile, char* hdfFileName, size_t N, +void xmf_write_groupheader(FILE* xmfFile, const char* hdfFileName, size_t N, enum part_type ptype) { fprintf(xmfFile, "\n<Grid Name=\"%s\" GridType=\"Uniform\">\n", diff --git a/src/xmf.h b/src/xmf.h index bd2781685f8d1f96daf6e5bfeb45a2bf645fca6e..e742ec8043ef815357ae4a708ed9afdd30ec474e 100644 --- a/src/xmf.h +++ b/src/xmf.h @@ -26,11 +26,11 @@ #include "common_io.h" #include "part_type.h" -void xmf_create_file(const char* baseName); -FILE* xmf_prepare_file(const char* baseName); -void xmf_write_outputheader(FILE* xmfFile, char* hdfFileName, float time); +void xmf_create_file(const char* fileName); +FILE* xmf_prepare_file(const char* fileName); +void xmf_write_outputheader(FILE* xmfFile, const char* hdfFileName, float time); void xmf_write_outputfooter(FILE* xmfFile, int outputCount, float time); -void xmf_write_groupheader(FILE* xmfFile, char* hdfFileName, size_t N, +void xmf_write_groupheader(FILE* xmfFile, const char* hdfFileName, size_t N, enum part_type ptype); void xmf_write_groupfooter(FILE* xmfFile, enum part_type ptype); void xmf_write_line(FILE* xmfFile, const char* fileName,