diff --git a/examples/main.c b/examples/main.c index 43b56291c4eb023238c39556d536ab88c3daad0c..6bb16d711cb3d44e8843279e76d4cd24f5ce0cc4 100644 --- a/examples/main.c +++ b/examples/main.c @@ -362,8 +362,8 @@ int main(int argc, char *argv[]) { if (myrank == 0) clocks_gettime(&tic); #if defined(WITH_MPI) #if defined(HAVE_PARALLEL_HDF5) - read_ic_parallel(ICfileName, dim, &parts, &Ngas, &periodic, myrank, nr_nodes, - MPI_COMM_WORLD, MPI_INFO_NULL); + read_ic_parallel(ICfileName, dim, &parts, &gparts, &Ngas, &Ngpart, &periodic, + myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL); #else read_ic_serial(ICfileName, dim, &parts, &gparts, &Ngas, &Ngpart, &periodic, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL); diff --git a/src/common_io.c b/src/common_io.c index 4be334ccd602c7b0c450f5dbe4aedd9155b35ff1..5fb2d9513ec2acc0cd8d389a226b14d427e02539 100644 --- a/src/common_io.c +++ b/src/common_io.c @@ -45,6 +45,9 @@ #include "kernel.h" #include "version.h" +const char* particle_type_names[NUM_PARTICLE_TYPES] = { + "Gas", "DM", "Boundary", "Dummy", "Star", "BH"}; + /** * @brief Converts a C data type to the HDF5 equivalent. * @@ -402,52 +405,68 @@ void createXMFfile() { *snapshot * * @param xmfFile The file to write in. - * @param Nparts The number of particles. * @param hdfFileName The name of the HDF5 file corresponding to this output. * @param time The current simulation time. */ -void writeXMFheader(FILE* xmfFile, long long Nparts, char* hdfFileName, - float time) { +void writeXMFoutputheader(FILE* xmfFile, char* hdfFileName, float time) { /* Write end of file */ + fprintf(xmfFile, "<!-- XMF description for file: %s -->\n", hdfFileName); fprintf(xmfFile, "<Grid GridType=\"Collection\" CollectionType=\"Spatial\">\n"); fprintf(xmfFile, "<Time Type=\"Single\" Value=\"%f\"/>\n", time); - fprintf(xmfFile, "<Grid Name=\"Gas\" GridType=\"Uniform\">\n"); - fprintf(xmfFile, - "<Topology TopologyType=\"Polyvertex\" Dimensions=\"%lld\"/>\n", - Nparts); - fprintf(xmfFile, "<Geometry GeometryType=\"XYZ\">\n"); - fprintf(xmfFile, - "<DataItem Dimensions=\"%lld 3\" NumberType=\"Double\" " - "Precision=\"8\" " - "Format=\"HDF\">%s:/PartType0/Coordinates</DataItem>\n", - Nparts, hdfFileName); - fprintf(xmfFile, "</Geometry>"); } /** * @brief Writes the end of the XMF file (closes all open markups) * * @param xmfFile The file to write in. + * @param output The number of this output. + * @param time The current simulation time. */ -void writeXMFfooter(FILE* xmfFile) { +void writeXMFoutputfooter(FILE* xmfFile, int output, float time) { /* Write end of the section of this time step */ - fprintf(xmfFile, "\n</Grid>\n"); - fprintf(xmfFile, "</Grid>\n"); - fprintf(xmfFile, "\n</Grid>\n"); + fprintf(xmfFile, + "\n</Grid> <!-- End of meta-data for output=%03i, time=%f -->\n", + output, time); + fprintf(xmfFile, "\n</Grid> <!-- timeSeries -->\n"); fprintf(xmfFile, "</Domain>\n"); fprintf(xmfFile, "</Xdmf>\n"); fclose(xmfFile); } +void writeXMFgroupheader(FILE* xmfFile, char* hdfFileName, size_t N, + enum PARTICLE_TYPE ptype) { + fprintf(xmfFile, "\n<Grid Name=\"%s\" GridType=\"Uniform\">\n", + particle_type_names[ptype]); + fprintf(xmfFile, + "<Topology TopologyType=\"Polyvertex\" Dimensions=\"%zi\"/>\n", N); + fprintf(xmfFile, "<Geometry GeometryType=\"XYZ\">\n"); + fprintf(xmfFile, + "<DataItem Dimensions=\"%zi 3\" NumberType=\"Double\" " + "Precision=\"8\" " + "Format=\"HDF\">%s:/PartType%d/Coordinates</DataItem>\n", + N, hdfFileName, ptype); + fprintf(xmfFile, + "</Geometry>\n <!-- Done geometry for %s, start of particle fields " + "list -->\n", + particle_type_names[ptype]); +} + +void writeXMFgroupfooter(FILE* xmfFile, enum PARTICLE_TYPE ptype) { + fprintf(xmfFile, "</Grid> <!-- End of meta-data for parttype=%s -->\n", + particle_type_names[ptype]); +} + /** * @brief Writes the lines corresponding to an array of the HDF5 output * * @param xmfFile The file in which to write * @param fileName The name of the HDF5 file associated to this XMF descriptor. + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param name The name of the array in the HDF5 file. * @param N The number of particles. * @param dim The dimension of the quantity (1 for scalars, 3 for vectors). @@ -455,21 +474,21 @@ void writeXMFfooter(FILE* xmfFile) { * * @todo Treat the types in a better way. */ -void writeXMFline(FILE* xmfFile, char* fileName, char* name, long long N, - int dim, enum DATA_TYPE type) { +void writeXMFline(FILE* xmfFile, char* fileName, char* partTypeGroupName, + char* name, size_t N, int dim, enum DATA_TYPE type) { fprintf(xmfFile, "<Attribute Name=\"%s\" AttributeType=\"%s\" Center=\"Node\">\n", name, dim == 1 ? "Scalar" : "Vector"); if (dim == 1) fprintf(xmfFile, - "<DataItem Dimensions=\"%lld\" NumberType=\"Double\" " - "Precision=\"%d\" Format=\"HDF\">%s:/PartType0/%s</DataItem>\n", - N, type == FLOAT ? 4 : 8, fileName, name); + "<DataItem Dimensions=\"%zi\" NumberType=\"Double\" " + "Precision=\"%d\" Format=\"HDF\">%s:%s/%s</DataItem>\n", + N, type == FLOAT ? 4 : 8, fileName, partTypeGroupName, name); else fprintf(xmfFile, - "<DataItem Dimensions=\"%lld %d\" NumberType=\"Double\" " - "Precision=\"%d\" Format=\"HDF\">%s:/PartType0/%s</DataItem>\n", - N, dim, type == FLOAT ? 4 : 8, fileName, name); + "<DataItem Dimensions=\"%zi %d\" NumberType=\"Double\" " + "Precision=\"%d\" Format=\"HDF\">%s:%s/%s</DataItem>\n", + N, dim, type == FLOAT ? 4 : 8, fileName, partTypeGroupName, name); fprintf(xmfFile, "</Attribute>\n"); } diff --git a/src/common_io.h b/src/common_io.h index 426fa6a01ec87a4413eceaaeb0d0880cbef8a214..4ad0c6fb754c4288a0c731e2b1e2392998719d52 100644 --- a/src/common_io.h +++ b/src/common_io.h @@ -70,6 +70,8 @@ enum PARTICLE_TYPE { NUM_PARTICLE_TYPES }; +extern const char* particle_type_names[]; + #define FILENAME_BUFFER_SIZE 150 #define PARTICLE_GROUP_BUFFER_SIZE 20 @@ -95,10 +97,13 @@ void writeAttribute_s(hid_t grp, char* name, const char* str); void createXMFfile(); FILE* prepareXMFfile(); -void writeXMFfooter(FILE* xmfFile); -void writeXMFheader(FILE* xmfFile, long long N, char* hdfFileName, float time); -void writeXMFline(FILE* xmfFile, char* fileName, char* name, long long N, - int dim, enum DATA_TYPE type); +void writeXMFoutputheader(FILE* xmfFile, char* hdfFileName, float time); +void writeXMFoutputfooter(FILE* xmfFile, int outputCount, float time); +void writeXMFgroupheader(FILE* xmfFile, char* hdfFileName, size_t N, + enum PARTICLE_TYPE ptype); +void writeXMFgroupfooter(FILE* xmfFile, enum PARTICLE_TYPE ptype); +void writeXMFline(FILE* xmfFile, char* fileName, char* partTypeGroupName, + char* name, size_t N, int dim, enum DATA_TYPE type); void writeCodeDescription(hid_t h_file); void writeSPHflavour(hid_t h_file); diff --git a/src/gravity/Default/gravity_io.h b/src/gravity/Default/gravity_io.h index d707d69631e65eed8ad21a7fa9601c07d3c71263..129c4b39828ca73d2d80d79edbdaa8ec4d5a9e01 100644 --- a/src/gravity/Default/gravity_io.h +++ b/src/gravity/Default/gravity_io.h @@ -48,6 +48,8 @@ __attribute__((always_inline)) INLINE static void darkmatter_read_particles( * * @param h_grp The HDF5 group in which to write the arrays. * @param fileName The name of the file (unsued in MPI mode). + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param xmfFile The XMF file to write to (unused in MPI mode). * @param Ndm The number of DM particles on that MPI rank. * @param Ndm_total The total number of g-particles (only used in MPI mode) @@ -59,17 +61,20 @@ __attribute__((always_inline)) INLINE static void darkmatter_read_particles( * */ __attribute__((always_inline)) INLINE static void darkmatter_write_particles( - hid_t h_grp, char* fileName, FILE* xmfFile, int Ndm, long long Ndm_total, - int mpi_rank, long long offset, struct gpart* gparts, - struct UnitSystem* us) { + hid_t h_grp, char* fileName, char* partTypeGroupName, FILE* xmfFile, + int Ndm, long long Ndm_total, int mpi_rank, long long offset, + struct gpart* gparts, struct UnitSystem* us) { /* Write arrays */ - writeArray(h_grp, fileName, xmfFile, "Coordinates", DOUBLE, Ndm, 3, gparts, - Ndm_total, mpi_rank, offset, x, us, UNIT_CONV_LENGTH); - writeArray(h_grp, fileName, xmfFile, "Masses", FLOAT, Ndm, 1, gparts, - Ndm_total, mpi_rank, offset, mass, us, UNIT_CONV_MASS); - writeArray(h_grp, fileName, xmfFile, "Velocities", FLOAT, Ndm, 3, gparts, - Ndm_total, mpi_rank, offset, v_full, us, UNIT_CONV_SPEED); - writeArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, Ndm, 1, gparts, - Ndm_total, mpi_rank, offset, id, us, UNIT_CONV_NO_UNITS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Coordinates", DOUBLE, + Ndm, 3, gparts, Ndm_total, mpi_rank, offset, x, us, + UNIT_CONV_LENGTH); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Masses", FLOAT, Ndm, + 1, gparts, Ndm_total, mpi_rank, offset, mass, us, UNIT_CONV_MASS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Velocities", FLOAT, + Ndm, 3, gparts, Ndm_total, mpi_rank, offset, v_full, us, + UNIT_CONV_SPEED); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "ParticleIDs", + ULONGLONG, Ndm, 1, gparts, Ndm_total, mpi_rank, offset, id, us, + UNIT_CONV_NO_UNITS); } diff --git a/src/hydro/Default/hydro_io.h b/src/hydro/Default/hydro_io.h index 958bf5a1869718b57678246ff3b1985e54145824..0e9ad46ddc1d4e8c8d3ffdbf3e81262ec49a7092 100644 --- a/src/hydro/Default/hydro_io.h +++ b/src/hydro/Default/hydro_io.h @@ -56,6 +56,8 @@ __attribute__((always_inline)) INLINE static void hydro_read_particles( * * @param h_grp The HDF5 group in which to write the arrays. * @param fileName The name of the file (unsued in MPI mode). + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param xmfFile The XMF file to write to (unused in MPI mode). * @param N The number of particles on that MPI rank. * @param N_total The total number of particles (only used in MPI mode) @@ -67,26 +69,31 @@ __attribute__((always_inline)) INLINE static void hydro_read_particles( * */ __attribute__((always_inline)) INLINE static void hydro_write_particles( - hid_t h_grp, char* fileName, FILE* xmfFile, int N, long long N_total, - int mpi_rank, long long offset, struct part* parts, struct UnitSystem* us) { + hid_t h_grp, char* fileName, char* partTypeGroupName, FILE* xmfFile, int N, + long long N_total, int mpi_rank, long long offset, struct part* parts, + struct UnitSystem* us) { /* Write arrays */ - writeArray(h_grp, fileName, xmfFile, "Coordinates", DOUBLE, N, 3, parts, - N_total, mpi_rank, offset, x, us, UNIT_CONV_LENGTH); - writeArray(h_grp, fileName, xmfFile, "Velocities", FLOAT, N, 3, parts, - N_total, mpi_rank, offset, v, us, UNIT_CONV_SPEED); - writeArray(h_grp, fileName, xmfFile, "Masses", FLOAT, N, 1, parts, N_total, - mpi_rank, offset, mass, us, UNIT_CONV_MASS); - writeArray(h_grp, fileName, xmfFile, "SmoothingLength", FLOAT, N, 1, parts, - N_total, mpi_rank, offset, h, us, UNIT_CONV_LENGTH); - writeArray(h_grp, fileName, xmfFile, "InternalEnergy", FLOAT, N, 1, parts, - N_total, mpi_rank, offset, u, us, UNIT_CONV_ENERGY_PER_UNIT_MASS); - writeArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, N, 1, parts, - N_total, mpi_rank, offset, id, us, UNIT_CONV_NO_UNITS); - writeArray(h_grp, fileName, xmfFile, "Acceleration", FLOAT, N, 3, parts, - N_total, mpi_rank, offset, a_hydro, us, UNIT_CONV_ACCELERATION); - writeArray(h_grp, fileName, xmfFile, "Density", FLOAT, N, 1, parts, N_total, - mpi_rank, offset, rho, us, UNIT_CONV_DENSITY); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Coordinates", DOUBLE, + N, 3, parts, N_total, mpi_rank, offset, x, us, UNIT_CONV_LENGTH); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Velocities", FLOAT, + N, 3, parts, N_total, mpi_rank, offset, v, us, UNIT_CONV_SPEED); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Masses", FLOAT, N, 1, + parts, N_total, mpi_rank, offset, mass, us, UNIT_CONV_MASS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "SmoothingLength", + FLOAT, N, 1, parts, N_total, mpi_rank, offset, h, us, + UNIT_CONV_LENGTH); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "InternalEnergy", + FLOAT, N, 1, parts, N_total, mpi_rank, offset, u, us, + UNIT_CONV_ENERGY_PER_UNIT_MASS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "ParticleIDs", + ULONGLONG, N, 1, parts, N_total, mpi_rank, offset, id, us, + UNIT_CONV_NO_UNITS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Acceleration", FLOAT, + N, 3, parts, N_total, mpi_rank, offset, a_hydro, us, + UNIT_CONV_ACCELERATION); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Density", FLOAT, N, + 1, parts, N_total, mpi_rank, offset, rho, us, UNIT_CONV_DENSITY); } /** diff --git a/src/hydro/Gadget2/hydro_io.h b/src/hydro/Gadget2/hydro_io.h index 17c3d3013644c3572f3c26fc3e270b1c1bc465ed..c1c59dfa4980a2843e7e13bee4c964c9b254cae6 100644 --- a/src/hydro/Gadget2/hydro_io.h +++ b/src/hydro/Gadget2/hydro_io.h @@ -56,6 +56,8 @@ __attribute__((always_inline)) INLINE static void hydro_read_particles( * * @param h_grp The HDF5 group in which to write the arrays. * @param fileName The name of the file (unsued in MPI mode). + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param xmfFile The XMF file to write to (unused in MPI mode). * @param N The number of particles on that MPI rank. * @param N_total The total number of particles (only used in MPI mode) @@ -67,27 +69,31 @@ __attribute__((always_inline)) INLINE static void hydro_read_particles( * */ __attribute__((always_inline)) INLINE static void hydro_write_particles( - hid_t h_grp, char* fileName, FILE* xmfFile, int N, long long N_total, - int mpi_rank, long long offset, struct part* parts, struct UnitSystem* us) { + hid_t h_grp, char* fileName, char* partTypeGroupName, FILE* xmfFile, int N, + long long N_total, int mpi_rank, long long offset, struct part* parts, + struct UnitSystem* us) { /* Write arrays */ - writeArray(h_grp, fileName, xmfFile, "Coordinates", DOUBLE, N, 3, parts, - N_total, mpi_rank, offset, x, us, UNIT_CONV_LENGTH); - writeArray(h_grp, fileName, xmfFile, "Velocities", FLOAT, N, 3, parts, - N_total, mpi_rank, offset, v, us, UNIT_CONV_SPEED); - writeArray(h_grp, fileName, xmfFile, "Masses", FLOAT, N, 1, parts, N_total, - mpi_rank, offset, mass, us, UNIT_CONV_MASS); - writeArray(h_grp, fileName, xmfFile, "SmoothingLength", FLOAT, N, 1, parts, - N_total, mpi_rank, offset, h, us, UNIT_CONV_LENGTH); - writeArray(h_grp, fileName, xmfFile, "InternalEnergy", FLOAT, N, 1, parts, - N_total, mpi_rank, offset, entropy, us, + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Coordinates", DOUBLE, + N, 3, parts, N_total, mpi_rank, offset, x, us, UNIT_CONV_LENGTH); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Velocities", FLOAT, + N, 3, parts, N_total, mpi_rank, offset, v, us, UNIT_CONV_SPEED); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Masses", FLOAT, N, 1, + parts, N_total, mpi_rank, offset, mass, us, UNIT_CONV_MASS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "SmoothingLength", + FLOAT, N, 1, parts, N_total, mpi_rank, offset, h, us, + UNIT_CONV_LENGTH); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "InternalEnergy", + FLOAT, N, 1, parts, N_total, mpi_rank, offset, entropy, us, UNIT_CONV_ENTROPY_PER_UNIT_MASS); - writeArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, N, 1, parts, - N_total, mpi_rank, offset, id, us, UNIT_CONV_NO_UNITS); - writeArray(h_grp, fileName, xmfFile, "Acceleration", FLOAT, N, 3, parts, - N_total, mpi_rank, offset, a_hydro, us, UNIT_CONV_ACCELERATION); - writeArray(h_grp, fileName, xmfFile, "Density", FLOAT, N, 1, parts, N_total, - mpi_rank, offset, rho, us, UNIT_CONV_DENSITY); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "ParticleIDs", + ULONGLONG, N, 1, parts, N_total, mpi_rank, offset, id, us, + UNIT_CONV_NO_UNITS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Acceleration", FLOAT, + N, 3, parts, N_total, mpi_rank, offset, a_hydro, us, + UNIT_CONV_ACCELERATION); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Density", FLOAT, N, + 1, parts, N_total, mpi_rank, offset, rho, us, UNIT_CONV_DENSITY); } /** diff --git a/src/hydro/Minimal/hydro_io.h b/src/hydro/Minimal/hydro_io.h index 2c56fb489ab84ca7c30426b54cf95e26e3821084..afe5de83f423e43b4d2480cca1ac3e84d6c549de 100644 --- a/src/hydro/Minimal/hydro_io.h +++ b/src/hydro/Minimal/hydro_io.h @@ -56,6 +56,8 @@ __attribute__((always_inline)) INLINE static void hydro_read_particles( * * @param h_grp The HDF5 group in which to write the arrays. * @param fileName The name of the file (unsued in MPI mode). + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param xmfFile The XMF file to write to (unused in MPI mode). * @param N The number of particles on that MPI rank. * @param N_total The total number of particles (only used in MPI mode) @@ -67,26 +69,31 @@ __attribute__((always_inline)) INLINE static void hydro_read_particles( * */ __attribute__((always_inline)) INLINE static void hydro_write_particles( - hid_t h_grp, char* fileName, FILE* xmfFile, int N, long long N_total, - int mpi_rank, long long offset, struct part* parts, struct UnitSystem* us) { + hid_t h_grp, char* fileName, char* partTypeGroupName, FILE* xmfFile, int N, + long long N_total, int mpi_rank, long long offset, struct part* parts, + struct UnitSystem* us) { /* Write arrays */ - writeArray(h_grp, fileName, xmfFile, "Coordinates", DOUBLE, N, 3, parts, - N_total, mpi_rank, offset, x, us, UNIT_CONV_LENGTH); - writeArray(h_grp, fileName, xmfFile, "Velocities", FLOAT, N, 3, parts, - N_total, mpi_rank, offset, v, us, UNIT_CONV_SPEED); - writeArray(h_grp, fileName, xmfFile, "Masses", FLOAT, N, 1, parts, N_total, - mpi_rank, offset, mass, us, UNIT_CONV_MASS); - writeArray(h_grp, fileName, xmfFile, "SmoothingLength", FLOAT, N, 1, parts, - N_total, mpi_rank, offset, h, us, UNIT_CONV_LENGTH); - writeArray(h_grp, fileName, xmfFile, "InternalEnergy", FLOAT, N, 1, parts, - N_total, mpi_rank, offset, u, us, UNIT_CONV_ENERGY_PER_UNIT_MASS); - writeArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, N, 1, parts, - N_total, mpi_rank, offset, id, us, UNIT_CONV_NO_UNITS); - writeArray(h_grp, fileName, xmfFile, "Acceleration", FLOAT, N, 3, parts, - N_total, mpi_rank, offset, a_hydro, us, UNIT_CONV_ACCELERATION); - writeArray(h_grp, fileName, xmfFile, "Density", FLOAT, N, 1, parts, N_total, - mpi_rank, offset, rho, us, UNIT_CONV_DENSITY); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Coordinates", DOUBLE, + N, 3, parts, N_total, mpi_rank, offset, x, us, UNIT_CONV_LENGTH); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Velocities", FLOAT, + N, 3, parts, N_total, mpi_rank, offset, v, us, UNIT_CONV_SPEED); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Masses", FLOAT, N, 1, + parts, N_total, mpi_rank, offset, mass, us, UNIT_CONV_MASS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "SmoothingLength", + FLOAT, N, 1, parts, N_total, mpi_rank, offset, h, us, + UNIT_CONV_LENGTH); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "InternalEnergy", + FLOAT, N, 1, parts, N_total, mpi_rank, offset, u, us, + UNIT_CONV_ENERGY_PER_UNIT_MASS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "ParticleIDs", + ULONGLONG, N, 1, parts, N_total, mpi_rank, offset, id, us, + UNIT_CONV_NO_UNITS); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Acceleration", FLOAT, + N, 3, parts, N_total, mpi_rank, offset, a_hydro, us, + UNIT_CONV_ACCELERATION); + writeArray(h_grp, fileName, xmfFile, partTypeGroupName, "Density", FLOAT, N, + 1, parts, N_total, mpi_rank, offset, rho, us, UNIT_CONV_DENSITY); } /** diff --git a/src/parallel_io.c b/src/parallel_io.c index cffa99a0fd75566ec3e850076d15e104504eeb40..0076c225e1c5361287280f8a567c8062aefd914e 100644 --- a/src/parallel_io.c +++ b/src/parallel_io.c @@ -178,9 +178,10 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, * * Calls #error() if an error occurs. */ -void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, - enum DATA_TYPE type, int N, int dim, long long N_total, - int mpi_rank, long long offset, char* part_c, +void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, + char* partTypeGroupName, char* name, enum DATA_TYPE type, + int N, int dim, long long N_total, int mpi_rank, + long long offset, char* part_c, size_t partSize, struct UnitSystem* us, enum UnitConversionFactor convFactor) { hid_t h_data = 0, h_err = 0, h_memspace = 0, h_filespace = 0, h_plist_id = 0; @@ -189,7 +190,6 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, int i = 0, rank = 0; const size_t typeSize = sizeOfType(type); const size_t copySize = typeSize * dim; - const size_t partSize = sizeof(struct part); char* temp_c = 0; char buffer[150]; @@ -269,7 +269,9 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, } /* Write XMF description for this data set */ - if (mpi_rank == 0) writeXMFline(xmfFile, fileName, name, N_total, dim, type); + if (mpi_rank == 0) + writeXMFline(xmfFile, fileName, partTypeGroupName, name, N_total, dim, + type); /* Write unit conversion factors for this data set */ conversionString(buffer, us, convFactor); @@ -328,14 +330,16 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, * @param convFactor The UnitConversionFactor for this array * */ -#define writeArray(grp, fileName, xmfFile, name, type, N, dim, part, N_total, \ - mpi_rank, offset, field, us, convFactor) \ - writeArrayBackEnd(grp, fileName, xmfFile, name, type, N, dim, N_total, \ - mpi_rank, offset, (char*)(&(part[0]).field), us, \ - convFactor) +#define writeArray(grp, fileName, xmfFile, pTypeGroupName, name, type, N, dim, \ + part, N_total, mpi_rank, offset, field, us, convFactor) \ + writeArrayBackEnd(grp, fileName, xmfFile, pTypeGroupName, name, type, N, \ + dim, N_total, mpi_rank, offset, (char*)(&(part[0]).field), \ + sizeof(part[0]), us, convFactor) /* Import the right hydro definition */ #include "hydro_io.h" +/* Import the right gravity definition */ +#include "gravity_io.h" /** * @brief Reads an HDF5 initial condition file (GADGET-3 type) in parallel @@ -357,16 +361,17 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, * */ void read_ic_parallel(char* fileName, double dim[3], struct part** parts, - size_t* N, int* periodic, int mpi_rank, int mpi_size, - MPI_Comm comm, MPI_Info info) { + struct gpart** gparts, size_t* Ngas, size_t* Ngparts, + int* periodic, int mpi_rank, int mpi_size, MPI_Comm comm, + MPI_Info info) { hid_t h_file = 0, h_grp = 0; - double boxSize[3] = { - 0.0, -1.0, -1.0}; /* GADGET has only cubic boxes (in cosmological mode) */ - int numParticles[6] = { - 0}; /* GADGET has 6 particle types. We only keep the type 0*/ - int numParticles_highWord[6] = {0}; - long long offset = 0; - long long N_total = 0; + /* GADGET has only cubic boxes (in cosmological mode) */ + double boxSize[3] = {0.0, -1.0, -1.0}; + int numParticles[NUM_PARTICLE_TYPES] = {0}; + int numParticles_highWord[NUM_PARTICLE_TYPES] = {0}; + size_t N[NUM_PARTICLE_TYPES] = {0}; + long long N_total[NUM_PARTICLE_TYPES] = {0}; + long long offset[NUM_PARTICLE_TYPES] = {0}; /* Open file */ /* message("Opening file '%s' as IC.", fileName); */ @@ -398,58 +403,116 @@ void read_ic_parallel(char* fileName, double dim[3], struct part** parts, readAttribute(h_grp, "NumPart_Total", UINT, numParticles); readAttribute(h_grp, "NumPart_Total_HighWord", UINT, numParticles_highWord); - N_total = ((long long)numParticles[0]) + - ((long long)numParticles_highWord[0] << 32); + for (int ptype = 0; ptype < NUM_PARTICLE_TYPES; ++ptype) + N_total[ptype] = ((long long)numParticles[ptype]) + + ((long long)numParticles_highWord[ptype] << 32); + dim[0] = boxSize[0]; dim[1] = (boxSize[1] < 0) ? boxSize[0] : boxSize[1]; dim[2] = (boxSize[2] < 0) ? boxSize[0] : boxSize[2]; - /* message("Found %d particles in a %speriodic box of size [%f %f %f].", */ - /* N_total, (periodic ? "": "non-"), dim[0], dim[1], dim[2]); */ + /* message("Found %d particles in a %speriodic box of size + * [%f %f %f].", */ + /* N_total, (periodic ? "": "non-"), dim[0], + * dim[1], dim[2]); */ /* Divide the particles among the tasks. */ - offset = mpi_rank * N_total / mpi_size; - *N = (mpi_rank + 1) * N_total / mpi_size - offset; + for (int ptype = 0; ptype < NUM_PARTICLE_TYPES; ++ptype) { + offset[ptype] = mpi_rank * N_total[ptype] / mpi_size; + N[ptype] = (mpi_rank + 1) * N_total[ptype] / mpi_size - offset[ptype]; + } /* Close header */ H5Gclose(h_grp); - /* Allocate memory to store particles */ - if (posix_memalign((void*)parts, part_align, *N * sizeof(struct part)) != 0) + /* Allocate memory to store SPH particles */ + *Ngas = N[0]; + if (posix_memalign((void*)parts, part_align, (*Ngas) * sizeof(struct part)) != + 0) error("Error while allocating memory for particles"); - bzero(*parts, *N * sizeof(struct part)); + bzero(*parts, *Ngas * sizeof(struct part)); - /* message("Allocated %8.2f MB for particles.", *N * sizeof(struct part) / + /* Allocate memory to store all particles */ + const size_t Ndm = N[1]; + *Ngparts = N[1] + N[0]; + if (posix_memalign((void*)gparts, gpart_align, + *Ngparts * sizeof(struct gpart)) != 0) + error( + "Error while allocating memory for gravity " + "particles"); + bzero(*gparts, *Ngparts * sizeof(struct gpart)); + + /* message("Allocated %8.2f MB for particles.", *N * + * sizeof(struct part) / * (1024.*1024.)); */ - /* Open SPH particles group */ - /* message("Reading particle arrays..."); */ - h_grp = H5Gopen(h_file, "/PartType0", H5P_DEFAULT); - if (h_grp < 0) error("Error while opening particle group.\n"); + /* message("BoxSize = %lf", dim[0]); */ + /* message("NumPart = [%zd, %zd] Total = %zd", *Ngas, Ndm, + * *Ngparts); */ - /* Read particle fields into the particle structure */ - hydro_read_particles(h_grp, *N, N_total, offset, *parts); + /* Loop over all particle types */ + for (int ptype = 0; ptype < NUM_PARTICLE_TYPES; ptype++) { - /* Close particle group */ - H5Gclose(h_grp); + /* Don't do anything if no particle of this kind */ + if (N_total[ptype] == 0) continue; + + /* Open the particle group in the file */ + char partTypeGroupName[PARTICLE_GROUP_BUFFER_SIZE]; + snprintf(partTypeGroupName, PARTICLE_GROUP_BUFFER_SIZE, "/PartType%d", + ptype); + h_grp = H5Gopen(h_file, partTypeGroupName, H5P_DEFAULT); + if (h_grp < 0) { + error("Error while opening particle group %s.", partTypeGroupName); + } + + /* Read particle fields into the particle structure */ + switch (ptype) { + + case GAS: + hydro_read_particles(h_grp, N[ptype], N_total[ptype], offset[ptype], + *parts); + break; + + case DM: + darkmatter_read_particles(h_grp, N[ptype], N_total[ptype], + offset[ptype], *gparts); + break; + + default: + error("Particle Type %d not yet supported. Aborting", ptype); + } + + /* Close particle group */ + H5Gclose(h_grp); + } + + /* Prepare the DM particles */ + prepare_dm_gparts(*gparts, Ndm); + + /* Now duplicate the hydro particle into gparts */ + duplicate_hydro_gparts(*parts, *gparts, *Ngas, Ndm); + + /* message("Done Reading particles..."); */ /* Close property handler */ H5Pclose(h_plist_id); /* Close file */ H5Fclose(h_file); - - /* message("Done Reading particles..."); */ } /** - * @brief Writes an HDF5 output file (GADGET-3 type) with its XMF descriptor + * @brief Writes an HDF5 output file (GADGET-3 type) with + *its XMF descriptor * * @param e The engine containing all the system. - * @param us The UnitSystem used for the conversion of units in the output + * @param us The UnitSystem used for the conversion of units + *in the output * - * Creates an HDF5 output file and writes the particles contained - * in the engine. If such a file already exists, it is erased and replaced + * Creates an HDF5 output file and writes the particles + *contained + * in the engine. If such a file already exists, it is + *erased and replaced * by the new one. * The companion XMF file is also updated accordingly. * @@ -459,23 +522,27 @@ void read_ic_parallel(char* fileName, double dim[3], struct part** parts, void write_output_parallel(struct engine* e, struct UnitSystem* us, int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info) { - hid_t h_file = 0, h_grp = 0, h_grpsph = 0; - int N = e->s->nr_parts; + const size_t Ngas = e->s->nr_parts; + const size_t Ntot = e->s->nr_gparts; int periodic = e->s->periodic; - unsigned int numParticles[6] = {N, 0}; - unsigned int numParticlesHighWord[6] = {0}; - unsigned int flagEntropy[6] = {0}; - long long N_total = 0, offset = 0; - double offset_d = 0., N_d = 0., N_total_d = 0.; int numFiles = 1; struct part* parts = e->s->parts; - FILE* xmfFile = 0; + struct gpart* gparts = e->s->gparts; + struct gpart* dmparts = NULL; static int outputCount = 0; + FILE* xmfFile = 0; + + /* Number of particles of each type */ + // const size_t Ndm = Ntot - Ngas; + + /* MATTHIEU: Temporary fix to preserve master */ + const size_t Ndm = Ntot > 0 ? Ntot - Ngas : 0; + /* MATTHIEU: End temporary fix */ /* File name */ - char fileName[200]; - sprintf(fileName, "output_%03i.hdf5", outputCount); + char fileName[FILENAME_BUFFER_SIZE]; + snprintf(fileName, FILENAME_BUFFER_SIZE, "output_%03i.hdf5", outputCount); /* First time, we need to create the XMF file */ if (outputCount == 0 && mpi_rank == 0) createXMFfile(); @@ -491,21 +558,26 @@ void write_output_parallel(struct engine* e, struct UnitSystem* us, error("Error while opening file '%s'.", fileName); } - /* Compute offset in the file and total number of particles */ - /* Done using double to allow for up to 2^50=10^15 particles */ - N_d = (double)N; - MPI_Exscan(&N_d, &offset_d, 1, MPI_DOUBLE, MPI_SUM, comm); - N_total_d = offset_d + N_d; - MPI_Bcast(&N_total_d, 1, MPI_DOUBLE, mpi_size - 1, comm); - if (N_total_d > 1.e15) - error( - "Error while computing the offset for parallel output: Simulation has " - "more than 10^15 particles.\n"); - N_total = (long long)N_total_d; - offset = (long long)offset_d; + /* Compute offset in the file and total number of + * particles */ + size_t N[NUM_PARTICLE_TYPES] = {Ngas, Ndm, 0}; + long long N_total[NUM_PARTICLE_TYPES] = {0}; + long long offset[NUM_PARTICLE_TYPES] = {0}; + MPI_Exscan(&N, &offset, NUM_PARTICLE_TYPES, MPI_LONG_LONG, MPI_SUM, comm); + for (int ptype = 0; ptype < NUM_PARTICLE_TYPES; ++ptype) + N_total[ptype] = offset[ptype] + N[ptype]; + + /* The last rank now has the correct N_total. Let's + * broadcast from there */ + MPI_Bcast(&N_total, 6, MPI_LONG_LONG, mpi_size - 1, comm); - /* Write the part of the XMF file corresponding to this specific output */ - if (mpi_rank == 0) writeXMFheader(xmfFile, N_total, fileName, e->time); + /* Now everybody konws its offset and the total number of + * particles of each + * type */ + + /* Write the part of the XMF file corresponding to this + * specific output */ + if (mpi_rank == 0) writeXMFoutputheader(xmfFile, fileName, e->time); /* Open header to write simulation properties */ /* message("Writing runtime parameters..."); */ @@ -526,19 +598,28 @@ void write_output_parallel(struct engine* e, struct UnitSystem* us, /* Print the relevant information and print status */ writeAttribute(h_grp, "BoxSize", DOUBLE, e->s->dim, 3); - writeAttribute(h_grp, "NumPart_ThisFile", UINT, numParticles, 6); double dblTime = e->time; writeAttribute(h_grp, "Time", DOUBLE, &dblTime, 1); /* GADGET-2 legacy values */ - numParticles[0] = (unsigned int)N_total; - writeAttribute(h_grp, "NumPart_Total", UINT, numParticles, 6); - numParticlesHighWord[0] = (unsigned int)(N_total >> 32); + /* Number of particles of each type */ + unsigned int numParticles[NUM_PARTICLE_TYPES] = {0}; + unsigned int numParticlesHighWord[NUM_PARTICLE_TYPES] = {0}; + for (int ptype = 0; ptype < NUM_PARTICLE_TYPES; ++ptype) { + numParticles[ptype] = (unsigned int)N_total[ptype]; + numParticlesHighWord[ptype] = (unsigned int)(N_total[ptype] >> 32); + } + writeAttribute(h_grp, "NumPart_ThisFile", LONGLONG, N_total, + NUM_PARTICLE_TYPES); + writeAttribute(h_grp, "NumPart_Total", UINT, numParticles, + NUM_PARTICLE_TYPES); writeAttribute(h_grp, "NumPart_Total_HighWord", UINT, numParticlesHighWord, - 6); + NUM_PARTICLE_TYPES); double MassTable[6] = {0., 0., 0., 0., 0., 0.}; - writeAttribute(h_grp, "MassTable", DOUBLE, MassTable, 6); - writeAttribute(h_grp, "Flag_Entropy_ICs", UINT, flagEntropy, 6); + writeAttribute(h_grp, "MassTable", DOUBLE, MassTable, NUM_PARTICLE_TYPES); + unsigned int flagEntropy[NUM_PARTICLE_TYPES] = {0}; + writeAttribute(h_grp, "Flag_Entropy_ICs", UINT, flagEntropy, + NUM_PARTICLE_TYPES); writeAttribute(h_grp, "NumFilesPerSnapshot", INT, &numFiles, 1); /* Close header */ @@ -556,21 +637,71 @@ void write_output_parallel(struct engine* e, struct UnitSystem* us, /* Print the system of Units */ writeUnitSystem(h_file, us); - /* Create SPH particles group */ - /* message("Writing particle arrays..."); */ - h_grp = - H5Gcreate(h_file, "/PartType0", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - if (h_grp < 0) error("Error while creating particle group.\n"); + /* Loop over all particle types */ + for (int ptype = 0; ptype < NUM_PARTICLE_TYPES; ptype++) { + + /* Don't do anything if no particle of this kind */ + if (N_total[ptype] == 0) continue; + + /* Add the global information for that particle type to + * the XMF meta-file */ + if (mpi_rank == 0) + writeXMFgroupheader(xmfFile, fileName, N_total[ptype], ptype); + + /* Open the particle group in the file */ + char partTypeGroupName[PARTICLE_GROUP_BUFFER_SIZE]; + snprintf(partTypeGroupName, PARTICLE_GROUP_BUFFER_SIZE, "/PartType%d", + ptype); + h_grp = H5Gcreate(h_file, partTypeGroupName, H5P_DEFAULT, H5P_DEFAULT, + H5P_DEFAULT); + if (h_grp < 0) { + error("Error while opening particle group %s.", partTypeGroupName); + } - /* Write particle fields from the particle structure */ - hydro_write_particles(h_grp, fileName, xmfFile, N, N_total, mpi_rank, offset, - parts, us); + /* Read particle fields into the particle structure */ + switch (ptype) { - /* Close particle group */ - H5Gclose(h_grp); + case GAS: + hydro_write_particles(h_grp, fileName, partTypeGroupName, xmfFile, + N[ptype], N_total[ptype], mpi_rank, offset[ptype], + parts, us); + + break; + + case DM: + /* Allocate temporary array */ + if (posix_memalign((void*)&dmparts, gpart_align, + Ndm * sizeof(struct gpart)) != 0) + error( + "Error while allocating temporart memory for " + "DM particles"); + bzero(dmparts, Ndm * sizeof(struct gpart)); + + /* Collect the DM particles from gpart */ + collect_dm_gparts(gparts, Ntot, dmparts, Ndm); + + /* Write DM particles */ + darkmatter_write_particles(h_grp, fileName, partTypeGroupName, xmfFile, + N[ptype], N_total[ptype], mpi_rank, + offset[ptype], dmparts, us); + + /* Free temporary array */ + free(dmparts); + break; + + default: + error("Particle Type %d not yet supported. Aborting", ptype); + } + + /* Close particle group */ + H5Gclose(h_grp); + + /* Close this particle group in the XMF file as well */ + if (mpi_rank == 0) writeXMFgroupfooter(xmfFile, ptype); + } /* Write LXMF file descriptor */ - if (mpi_rank == 0) writeXMFfooter(xmfFile); + if (mpi_rank == 0) writeXMFoutputfooter(xmfFile, outputCount, e->time); /* message("Done writing particles..."); */ diff --git a/src/parallel_io.h b/src/parallel_io.h index a0589944ec845c712abde1e64e305980748db0e7..663f0aabac44c08682b964512839b925673ea5c5 100644 --- a/src/parallel_io.h +++ b/src/parallel_io.h @@ -32,8 +32,9 @@ #if defined(HAVE_HDF5) && defined(WITH_MPI) && defined(HAVE_PARALLEL_HDF5) void read_ic_parallel(char* fileName, double dim[3], struct part** parts, - size_t* N, int* periodic, int mpi_rank, int mpi_size, - MPI_Comm comm, MPI_Info info); + struct gpart** gparts, size_t* Ngas, size_t* Ngparts, + int* periodic, int mpi_rank, int mpi_size, MPI_Comm comm, + MPI_Info info); void write_output_parallel(struct engine* e, struct UnitSystem* us, int mpi_rank, int mpi_size, MPI_Comm comm, diff --git a/src/serial_io.c b/src/serial_io.c index 3fb1a1d1b743e48be4e8e6d81413c28e8034b870..40bd2b1c8921f4acbfa0950984d6915ebd3d241e 100644 --- a/src/serial_io.c +++ b/src/serial_io.c @@ -57,14 +57,13 @@ * @param dim The dimension of the data (1 for scalar, 3 for vector) * @param part_c A (char*) pointer on the first occurrence of the field of *interest in the parts array + * @param partSize The size in bytes of the particle structure. * @param importance If COMPULSORY, the data must be present in the IC file. If *OPTIONAL, the array will be zeroed when the data is not present. * * @todo A better version using HDF5 hyper-slabs to read the file directly into *the part array * will be written once the structures have been stabilized. - * - * Calls #error() if an error occurs. */ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim, long long N_total, long long offset, @@ -172,9 +171,10 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, * Routines writing an output file *-----------------------------------------------------------------------------*/ -void prepareArray(hid_t grp, char* fileName, FILE* xmfFile, char* name, - enum DATA_TYPE type, long long N_total, int dim, - struct UnitSystem* us, enum UnitConversionFactor convFactor) { +void prepareArray(hid_t grp, char* fileName, FILE* xmfFile, + char* partTypeGroupName, char* name, enum DATA_TYPE type, + long long N_total, int dim, struct UnitSystem* us, + enum UnitConversionFactor convFactor) { hid_t h_data = 0, h_err = 0, h_space = 0, h_prop = 0; int rank = 0; hsize_t shape[2]; @@ -234,7 +234,7 @@ void prepareArray(hid_t grp, char* fileName, FILE* xmfFile, char* name, } /* Write XMF description for this data set */ - writeXMFline(xmfFile, fileName, name, N_total, dim, type); + writeXMFline(xmfFile, fileName, partTypeGroupName, name, N_total, dim, type); /* Write unit conversion factors for this data set */ conversionString(buffer, us, convFactor); @@ -255,22 +255,23 @@ void prepareArray(hid_t grp, char* fileName, FILE* xmfFile, char* name, * @param grp The group in which to write. * @param fileName The name of the file in which the data is written * @param xmfFile The FILE used to write the XMF description + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param name The name of the array to write. * @param type The #DATA_TYPE of the array. * @param N The number of particles to write. * @param dim The dimension of the data (1 for scalar, 3 for vector) * @param part_c A (char*) pointer on the first occurrence of the field of *interest in the parts array + * @param partSize The size in bytes of the particle structure. * @param us The UnitSystem currently in use - * @param convFactor The UnitConversionFactor for this array - * - * - * Calls #error() if an error occurs. + * @param convFactor The UnitConversionFactor for this arrayo */ -void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, - enum DATA_TYPE type, int N, int dim, long long N_total, - int mpi_rank, long long offset, char* part_c, - size_t partSize, struct UnitSystem* us, +void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, + char* partTypeGroupName, char* name, enum DATA_TYPE type, + int N, int dim, long long N_total, int mpi_rank, + long long offset, char* part_c, size_t partSize, + struct UnitSystem* us, enum UnitConversionFactor convFactor) { hid_t h_data = 0, h_err = 0, h_memspace = 0, h_filespace = 0; @@ -285,8 +286,8 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, /* Prepare the arrays in the file */ if (mpi_rank == 0) - prepareArray(grp, fileName, xmfFile, name, type, N_total, dim, us, - convFactor); + prepareArray(grp, fileName, xmfFile, partTypeGroupName, name, type, N_total, + dim, us, convFactor); /* Allocate temporary buffer */ temp = malloc(N * dim * sizeOfType(type)); @@ -370,21 +371,26 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, * @param fileName Unused parameter in non-MPI mode * @param xmfFile Unused parameter in non-MPI mode * @param name The name of the array to write. + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param type The #DATA_TYPE of the array. * @param N The number of particles to write. * @param dim The dimension of the data (1 for scalar, 3 for vector) * @param part A (char*) pointer on the first occurrence of the field of - *interest - *in the parts array + *interest in the parts array + * @param N_total Unused parameter in non-MPI mode + * @param mpi_rank Unused parameter in non-MPI mode + * @param offset Unused parameter in non-MPI mode * @param field The name (code name) of the field to read from. * @param us The UnitSystem currently in use * @param convFactor The UnitConversionFactor for this array * */ -#define writeArray(grp, fileName, xmfFile, name, type, N, dim, part, N_total, \ - mpi_rank, offset, field, us, convFactor) \ - writeArrayBackEnd(grp, fileName, xmfFile, name, type, N, dim, N_total, \ - mpi_rank, offset, (char*)(&(part[0]).field), \ +#define writeArray(grp, fileName, xmfFile, partTypeGroupName, name, type, N, \ + dim, part, N_total, mpi_rank, offset, field, us, \ + convFactor) \ + writeArrayBackEnd(grp, fileName, xmfFile, partTypeGroupName, name, type, N, \ + dim, N_total, mpi_rank, offset, (char*)(&(part[0]).field), \ sizeof(part[0]), us, convFactor) /* Import the right hydro definition */ @@ -609,12 +615,12 @@ void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank, FILE* xmfFile = 0; /* Number of particles of each type */ - //const size_t Ndm = Ntot - Ngas; + // const size_t Ndm = Ntot - Ngas; /* MATTHIEU: Temporary fix to preserve master */ - const size_t Ndm = Ntot > 0 ? Ntot - Ngas: 0; + const size_t Ndm = Ntot > 0 ? Ntot - Ngas : 0; /* MATTHIEU: End temporary fix */ - + /* File name */ char fileName[FILENAME_BUFFER_SIZE]; snprintf(fileName, FILENAME_BUFFER_SIZE, "output_%03i.hdf5", outputCount); @@ -643,7 +649,7 @@ void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank, xmfFile = prepareXMFfile(); /* Write the part corresponding to this specific output */ - // writeXMFheader(xmfFile, N_total, fileName, e->time); + writeXMFoutputheader(xmfFile, fileName, e->time); /* Open file */ /* message("Opening file '%s'.", fileName); */ @@ -750,6 +756,11 @@ void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank, /* Don't do anything if no particle of this kind */ if (N_total[ptype] == 0) continue; + /* Add the global information for that particle type to the XMF + * meta-file */ + if (mpi_rank == 0) + writeXMFgroupheader(xmfFile, fileName, N_total[ptype], ptype); + /* Open the particle group in the file */ char partTypeGroupName[PARTICLE_GROUP_BUFFER_SIZE]; snprintf(partTypeGroupName, PARTICLE_GROUP_BUFFER_SIZE, "/PartType%d", @@ -763,9 +774,9 @@ void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank, switch (ptype) { case GAS: - hydro_write_particles(h_grp, fileName, xmfFile, N[ptype], - N_total[ptype], mpi_rank, offset[ptype], - parts, us); + hydro_write_particles(h_grp, fileName, partTypeGroupName, xmfFile, + N[ptype], N_total[ptype], mpi_rank, + offset[ptype], parts, us); break; @@ -780,9 +791,9 @@ void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank, collect_dm_gparts(gparts, Ntot, dmparts, Ndm); /* Write DM particles */ - darkmatter_write_particles(h_grp, fileName, xmfFile, N[ptype], - N_total[ptype], mpi_rank, offset[ptype], - dmparts, us); + darkmatter_write_particles(h_grp, fileName, partTypeGroupName, + xmfFile, N[ptype], N_total[ptype], + mpi_rank, offset[ptype], dmparts, us); /* Free temporary array */ free(dmparts); @@ -794,6 +805,9 @@ void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank, /* Close particle group */ H5Gclose(h_grp); + + /* Close this particle group in the XMF file as well */ + if (mpi_rank == 0) writeXMFgroupfooter(xmfFile, ptype); } /* Close file */ @@ -805,7 +819,7 @@ void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank, } /* Write footer of LXMF file descriptor */ - if (mpi_rank == 0) writeXMFfooter(xmfFile); + if (mpi_rank == 0) writeXMFoutputfooter(xmfFile, outputCount, e->time); /* message("Done writing particles..."); */ ++outputCount; diff --git a/src/single_io.c b/src/single_io.c index 54ace5c4e369cd6b9a02d44f8a8f03ef6cbadd5f..801428433ef5170082b68dec425e52f845bb41ae 100644 --- a/src/single_io.c +++ b/src/single_io.c @@ -53,14 +53,13 @@ * @param dim The dimension of the data (1 for scalar, 3 for vector) * @param part_c A (char*) pointer on the first occurrence of the field of *interest in the parts array + * @param partSize The size in bytes of the particle structure. * @param importance If COMPULSORY, the data must be present in the IC file. If *OPTIONAL, the array will be zeroed when the data is not present. * * @todo A better version using HDF5 hyper-slabs to read the file directly into *the part array * will be written once the structures have been stabilized. - * - * Calls #error() if an error occurs. */ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim, char* part_c, size_t partSize, @@ -138,24 +137,26 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, * @param grp The group in which to write. * @param fileName The name of the file in which the data is written * @param xmfFile The FILE used to write the XMF description + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param name The name of the array to write. * @param type The #DATA_TYPE of the array. * @param N The number of particles to write. * @param dim The dimension of the data (1 for scalar, 3 for vector) * @param part_c A (char*) pointer on the first occurrence of the field of - *interest in the parts array + *interest in the parts array. + * @param partSize The size in bytes of the particle structure. * @param us The UnitSystem currently in use * @param convFactor The UnitConversionFactor for this array * * @todo A better version using HDF5 hyper-slabs to write the file directly from *the part array * will be written once the structures have been stabilized. - * - * Calls #error() if an error occurs. */ -void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, - enum DATA_TYPE type, int N, int dim, char* part_c, - size_t partSize, struct UnitSystem* us, +void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, + char* partTypeGroupName, char* name, enum DATA_TYPE type, + int N, int dim, char* part_c, size_t partSize, + struct UnitSystem* us, enum UnitConversionFactor convFactor) { hid_t h_data = 0, h_err = 0, h_space = 0, h_prop = 0; void* temp = 0; @@ -237,7 +238,7 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, } /* Write XMF description for this data set */ - writeXMFline(xmfFile, fileName, name, N, dim, type); + writeXMFline(xmfFile, fileName, partTypeGroupName, name, N, dim, type); /* Write unit conversion factors for this data set */ conversionString(buffer, us, convFactor); @@ -281,6 +282,8 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, * @param fileName The name of the file in which the data is written * @param xmfFile The FILE used to write the XMF description * @param name The name of the array to write. + * @param partTypeGroupName The name of the group containing the particles in + *the HDF5 file. * @param type The #DATA_TYPE of the array. * @param N The number of particles to write. * @param dim The dimension of the data (1 for scalar, 3 for vector) @@ -294,10 +297,11 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, * @param convFactor The UnitConversionFactor for this array * */ -#define writeArray(grp, fileName, xmfFile, name, type, N, dim, part, N_total, \ - mpi_rank, offset, field, us, convFactor) \ - writeArrayBackEnd(grp, fileName, xmfFile, name, type, N, dim, \ - (char*)(&(part[0]).field), sizeof(part[0]), us, \ +#define writeArray(grp, fileName, xmfFile, partTypeGroupName, name, type, N, \ + dim, part, N_total, mpi_rank, offset, field, us, \ + convFactor) \ + writeArrayBackEnd(grp, fileName, xmfFile, partTypeGroupName, name, type, N, \ + dim, (char*)(&(part[0]).field), sizeof(part[0]), us, \ convFactor) /* Import the right hydro definition */ @@ -476,10 +480,10 @@ void write_output_single(struct engine* e, struct UnitSystem* us) { static int outputCount = 0; /* Number of particles of each type */ - //const size_t Ndm = Ntot - Ngas; + // const size_t Ndm = Ntot - Ngas; /* MATTHIEU: Temporary fix to preserve master */ - const size_t Ndm = Ntot > 0 ? Ntot - Ngas: 0; + const size_t Ndm = Ntot > 0 ? Ntot - Ngas : 0; /* MATTHIEU: End temporary fix */ long long N_total[NUM_PARTICLE_TYPES] = {Ngas, Ndm, 0}; @@ -496,7 +500,7 @@ void write_output_single(struct engine* e, struct UnitSystem* us) { xmfFile = prepareXMFfile(); /* Write the part corresponding to this specific output */ - writeXMFheader(xmfFile, Ngas, fileName, e->time); + writeXMFoutputheader(xmfFile, fileName, e->time); /* Open file */ /* message("Opening file '%s'.", fileName); */ @@ -569,6 +573,9 @@ void write_output_single(struct engine* e, struct UnitSystem* us) { /* Don't do anything if no particle of this kind */ if (numParticles[ptype] == 0) continue; + /* Add the global information for that particle type to the XMF meta-file */ + writeXMFgroupheader(xmfFile, fileName, numParticles[ptype], ptype); + /* Open the particle group in the file */ char partTypeGroupName[PARTICLE_GROUP_BUFFER_SIZE]; snprintf(partTypeGroupName, PARTICLE_GROUP_BUFFER_SIZE, "/PartType%d", @@ -585,8 +592,8 @@ void write_output_single(struct engine* e, struct UnitSystem* us) { switch (ptype) { case GAS: - hydro_write_particles(h_grp, fileName, xmfFile, Ngas, Ngas, 0, 0, parts, - us); + hydro_write_particles(h_grp, fileName, partTypeGroupName, xmfFile, Ngas, + Ngas, 0, 0, parts, us); break; case DM: @@ -600,8 +607,8 @@ void write_output_single(struct engine* e, struct UnitSystem* us) { collect_dm_gparts(gparts, Ntot, dmparts, Ndm); /* Write DM particles */ - darkmatter_write_particles(h_grp, fileName, xmfFile, Ndm, Ndm, 0, 0, - dmparts, us); + darkmatter_write_particles(h_grp, fileName, partTypeGroupName, xmfFile, + Ndm, Ndm, 0, 0, dmparts, us); /* Free temporary array */ free(dmparts); @@ -613,10 +620,13 @@ void write_output_single(struct engine* e, struct UnitSystem* us) { /* Close particle group */ H5Gclose(h_grp); + + /* Close this particle group in the XMF file as well */ + writeXMFgroupfooter(xmfFile, ptype); } /* Write LXMF file descriptor */ - writeXMFfooter(xmfFile); + writeXMFoutputfooter(xmfFile, outputCount, e->time); /* message("Done writing particles..."); */