diff --git a/src/hydro/Default/hydro_io.h b/src/hydro/Default/hydro_io.h index a122fc24961644073470f9638bad967a52ef4926..1c3e70753d417eb59d0fda5a7acfd1c24ab93045 100644 --- a/src/hydro/Default/hydro_io.h +++ b/src/hydro/Default/hydro_io.h @@ -42,7 +42,7 @@ void hydro_read_particles(struct part* parts, struct io_props* list, list[3] = io_make_input_field("SmoothingLength", FLOAT, 1, COMPULSORY, UNIT_CONV_LENGTH, parts, h); list[4] = io_make_input_field("InternalEnergy", FLOAT, 1, COMPULSORY, - UNIT_CONV_ENERGY, parts, u); + UNIT_CONV_ENERGY_PER_UNIT_MASS, parts, u); list[5] = io_make_input_field("ParticleIDs", ULONGLONG, 1, COMPULSORY, UNIT_CONV_NO_UNITS, parts, id); list[6] = io_make_input_field("Accelerations", FLOAT, 3, OPTIONAL, @@ -72,7 +72,7 @@ void hydro_write_particles(struct part* parts, struct io_props* list, io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, parts, mass); list[3] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH, parts, h); - list[4] = io_make_output_field("Entropy", FLOAT, 1, + list[4] = io_make_output_field("InternalEnergy", FLOAT, 1, UNIT_CONV_ENERGY_PER_UNIT_MASS, parts, u); list[5] = io_make_output_field("ParticleIDs", ULONGLONG, 1, UNIT_CONV_NO_UNITS, parts, id); diff --git a/src/hydro/Gadget2/hydro_io.h b/src/hydro/Gadget2/hydro_io.h index c8db0b3b64cb03e4e013c6dd8daeb16a138b6709..1614a483ac3007d37770e04d40833f78d19a8cd2 100644 --- a/src/hydro/Gadget2/hydro_io.h +++ b/src/hydro/Gadget2/hydro_io.h @@ -17,6 +17,7 @@ * ******************************************************************************/ +#include "adiabatic_index.h" #include "io_properties.h" #include "kernel_hydro.h" @@ -42,7 +43,7 @@ void hydro_read_particles(struct part* parts, struct io_props* list, list[3] = io_make_input_field("SmoothingLength", FLOAT, 1, COMPULSORY, UNIT_CONV_LENGTH, parts, h); list[4] = io_make_input_field("InternalEnergy", FLOAT, 1, COMPULSORY, - UNIT_CONV_ENERGY, parts, entropy); + UNIT_CONV_ENERGY_PER_UNIT_MASS, parts, entropy); list[5] = io_make_input_field("ParticleIDs", ULONGLONG, 1, COMPULSORY, UNIT_CONV_NO_UNITS, parts, id); list[6] = io_make_input_field("Accelerations", FLOAT, 3, OPTIONAL, @@ -51,6 +52,12 @@ void hydro_read_particles(struct part* parts, struct io_props* list, UNIT_CONV_DENSITY, parts, rho); } +float convert_u(struct engine* e, struct part* p) { + + return p->entropy * pow_gamma_minus_one(p->rho) * + hydro_one_over_gamma_minus_one; +} + /** * @brief Specifies which particle fields to write to a dataset * @@ -61,7 +68,7 @@ void hydro_read_particles(struct part* parts, struct io_props* list, void hydro_write_particles(struct part* parts, struct io_props* list, int* num_fields) { - *num_fields = 8; + *num_fields = 9; /* List what we want to write */ list[0] = io_make_output_field("Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, @@ -80,6 +87,9 @@ void hydro_write_particles(struct part* parts, struct io_props* list, UNIT_CONV_ACCELERATION, parts, a_hydro); list[7] = io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho); + list[8] = io_make_output_field_convert_part("InternalEnergy", FLOAT, 1, + UNIT_CONV_ENERGY_PER_UNIT_MASS, + parts, rho, convert_u); } /** @@ -102,4 +112,4 @@ void writeSPHflavour(hid_t h_grpsph) { * * @return 1 if entropy is in 'internal energy', 0 otherwise. */ -int writeEntropyFlag() { return 1; } +int writeEntropyFlag() { return 0; } diff --git a/src/hydro/Minimal/hydro_io.h b/src/hydro/Minimal/hydro_io.h index 6b52481e9e77ffb7d3c35edd0b2da834ff035a87..1a5b2938354fb8ee3ef936f86ff442c731e0d4c7 100644 --- a/src/hydro/Minimal/hydro_io.h +++ b/src/hydro/Minimal/hydro_io.h @@ -42,7 +42,7 @@ void hydro_read_particles(struct part* parts, struct io_props* list, list[3] = io_make_input_field("SmoothingLength", FLOAT, 1, COMPULSORY, UNIT_CONV_LENGTH, parts, h); list[4] = io_make_input_field("InternalEnergy", FLOAT, 1, COMPULSORY, - UNIT_CONV_ENERGY, parts, u); + UNIT_CONV_ENERGY_PER_UNIT_MASS, parts, u); list[5] = io_make_input_field("ParticleIDs", ULONGLONG, 1, COMPULSORY, UNIT_CONV_NO_UNITS, parts, id); list[6] = io_make_input_field("Accelerations", FLOAT, 3, OPTIONAL, @@ -72,7 +72,7 @@ void hydro_write_particles(struct part* parts, struct io_props* list, io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, parts, mass); list[3] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH, parts, h); - list[4] = io_make_output_field("Entropy", FLOAT, 1, + list[4] = io_make_output_field("InternalEnergy", FLOAT, 1, UNIT_CONV_ENERGY_PER_UNIT_MASS, parts, u); list[5] = io_make_output_field("ParticleIDs", ULONGLONG, 1, UNIT_CONV_NO_UNITS, parts, id); diff --git a/src/io_properties.h b/src/io_properties.h index 5e19420d006ee8043ac418045b6889d885fbd66a..2d4a65163f1ef2bcbaceadee73596d8c0345171a 100644 --- a/src/io_properties.h +++ b/src/io_properties.h @@ -54,6 +54,16 @@ struct io_props { /* The size of the particles */ size_t partSize; + + /* The particle arrays */ + struct part* parts; + struct gpart* gparts; + + /* Conversion function for part */ + float (*convert_part)(struct engine*, struct part*); + + /* Conversion function for gpart */ + float (*convert_gpart)(struct engine*, struct gpart*); }; /** @@ -68,7 +78,7 @@ struct io_props { * * @param name Name of the field to read * @param type The type of the data - * @param dimension Dataset dimension (!D, 3D, ...) + * @param dimension Dataset dimension (1D, 3D, ...) * @param importance Is this dataset compulsory ? * @param units The units of the dataset * @param field Pointer to the field of the first particle @@ -89,6 +99,10 @@ struct io_props io_make_input_field_(char name[FIELD_BUFFER_SIZE], r.units = units; r.field = field; r.partSize = partSize; + r.parts = NULL; + r.gparts = NULL; + r.convert_part = NULL; + r.convert_gpart = NULL; return r; } @@ -105,7 +119,7 @@ struct io_props io_make_input_field_(char name[FIELD_BUFFER_SIZE], * * @param name Name of the field to read * @param type The type of the data - * @param dimension Dataset dimension (!D, 3D, ...) + * @param dimension Dataset dimension (1D, 3D, ...) * @param units The units of the dataset * @param field Pointer to the field of the first particle * @param partSize The size in byte of the particle @@ -124,6 +138,98 @@ struct io_props io_make_output_field_(char name[FIELD_BUFFER_SIZE], r.units = units; r.field = field; r.partSize = partSize; + r.parts = NULL; + r.gparts = NULL; + r.convert_part = NULL; + r.convert_gpart = NULL; + + return r; +} + +/** + * @brief Constructs an #io_props (with conversion) from its parameters + */ +#define io_make_output_field_convert_part(name, type, dim, units, part, field, \ + convert) \ + io_make_output_field_convert_part_(name, type, dim, units, \ + (char*)(&(part[0]).field), \ + sizeof(part[0]), part, convert) + +/** + * @brief Construct an #io_props from its parameters + * + * @param name Name of the field to read + * @param type The type of the data + * @param dimension Dataset dimension (1D, 3D, ...) + * @param units The units of the dataset + * @param field Pointer to the field of the first particle + * @param partSize The size in byte of the particle + * @param parts The particle array + * @param functionPtr The function used to convert a particle to a float + * + * Do not call this function directly. Use the macro defined above. + */ +struct io_props io_make_output_field_convert_part_( + char name[FIELD_BUFFER_SIZE], enum DATA_TYPE type, int dimension, + enum UnitConversionFactor units, char* field, size_t partSize, + struct part* parts, float (*functionPtr)(struct engine*, struct part*)) { + + struct io_props r; + strcpy(r.name, name); + r.type = type; + r.dimension = dimension; + r.importance = 0; + r.units = units; + r.field = field; + r.partSize = partSize; + r.parts = parts; + r.gparts = NULL; + r.convert_part = functionPtr; + r.convert_gpart = NULL; + + return r; +} + +/** + * @brief Constructs an #io_props (with conversion) from its parameters + */ +#define io_make_output_field_convert_gpart(name, type, dim, units, part, \ + field, convert) \ + io_make_output_field_convert_gpart_(name, type, dim, units, \ + (char*)(&(part[0]).field), \ + sizeof(part[0]), gpart, convert) + +/** + * @brief Construct an #io_props from its parameters + * + * @param name Name of the field to read + * @param type The type of the data + * @param dimension Dataset dimension (1D, 3D, ...) + * @param units The units of the dataset + * @param field Pointer to the field of the first particle + * @param partSize The size in byte of the particle + * @param gparts The particle array + * @param functionPtr The function used to convert a g-particle to a float + * + * Do not call this function directly. Use the macro defined above. + */ +struct io_props io_make_output_field_convert_gpart_( + char name[FIELD_BUFFER_SIZE], enum DATA_TYPE type, int dimension, + enum UnitConversionFactor units, char* field, size_t partSize, + struct gpart* gparts, float (*functionPtr)(struct engine*, struct gpart*)) { + + struct io_props r; + strcpy(r.name, name); + r.type = type; + r.dimension = dimension; + r.importance = 0; + r.units = units; + r.field = field; + r.partSize = partSize; + r.parts = NULL; + r.gparts = gparts; + r.convert_part = NULL; + r.convert_gpart = functionPtr; return r; } diff --git a/src/parallel_io.c b/src/parallel_io.c index 5e358c34f70065255e1eab61295b21487f07f77d..c6bbcdfd3982ee5663ff54246feb58bebdbb0dad 100644 --- a/src/parallel_io.c +++ b/src/parallel_io.c @@ -181,6 +181,7 @@ void readArray(hid_t grp, const struct io_props prop, size_t N, /** * @brief Writes a data array in given HDF5 group. * + * @param e The #engine we are writing from. * @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 @@ -194,7 +195,7 @@ void readArray(hid_t grp, const struct io_props prop, size_t N, * the part array will be written once the structures have been stabilized. * */ -void writeArray(hid_t grp, char* fileName, FILE* xmfFile, +void writeArray(struct engine* e, hid_t grp, char* fileName, FILE* xmfFile, char* partTypeGroupName, const struct io_props props, size_t N, long long N_total, int mpi_rank, long long offset, const struct UnitSystem* internal_units, @@ -211,9 +212,25 @@ void writeArray(hid_t grp, char* fileName, FILE* xmfFile, if (temp == NULL) error("Unable to allocate memory for temporary buffer"); /* Copy particle data to temporary buffer */ - char* temp_c = temp; - for (size_t i = 0; i < N; ++i) - memcpy(&temp_c[i * copySize], props.field + i * props.partSize, copySize); + if (props.convert_part == NULL && + props.convert_gpart == NULL) { /* No conversion */ + + char* temp_c = temp; + for (size_t i = 0; i < N; ++i) + memcpy(&temp_c[i * copySize], props.field + i * props.partSize, copySize); + + } else if (props.convert_part != NULL) { /* conversion (for parts)*/ + + float* temp_f = temp; + for (size_t i = 0; i < N; ++i) + temp_f[i] = props.convert_part(e, &props.parts[i]); + + } else if (props.convert_gpart != NULL) { /* conversion (for gparts)*/ + + float* temp_f = temp; + for (size_t i = 0; i < N; ++i) + temp_f[i] = props.convert_gpart(e, &props.gparts[i]); + } /* Unit conversion if necessary */ const double factor = @@ -798,7 +815,7 @@ void write_output_parallel(struct engine* e, const char* baseName, /* Write everything */ for (int i = 0; i < num_fields; ++i) - writeArray(h_grp, fileName, xmfFile, partTypeGroupName, list[i], N, + writeArray(e, h_grp, fileName, xmfFile, partTypeGroupName, list[i], N, N_total[ptype], mpi_rank, offset[ptype], internal_units, snapshot_units); diff --git a/src/serial_io.c b/src/serial_io.c index 0134fa3e52cd0df7341cbc88f11f4182b1c02949..91231e70c603fc882f38e73f3d545828613629fc 100644 --- a/src/serial_io.c +++ b/src/serial_io.c @@ -261,6 +261,7 @@ void prepareArray(hid_t grp, char* fileName, FILE* xmfFile, /** * @brief Writes a data array in given HDF5 group. * + * @param e The #engine we are writing from. * @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 @@ -276,7 +277,7 @@ void prepareArray(hid_t grp, char* fileName, FILE* xmfFile, * @param us The UnitSystem currently in use * @param convFactor The UnitConversionFactor for this arrayo */ -void writeArray(hid_t grp, char* fileName, FILE* xmfFile, +void writeArray(struct engine* e, hid_t grp, char* fileName, FILE* xmfFile, char* partTypeGroupName, const struct io_props props, size_t N, long long N_total, int mpi_rank, long long offset, const struct UnitSystem* internal_units, @@ -298,9 +299,25 @@ void writeArray(hid_t grp, char* fileName, FILE* xmfFile, if (temp == NULL) error("Unable to allocate memory for temporary buffer"); /* Copy particle data to temporary buffer */ - char* temp_c = temp; - for (size_t i = 0; i < N; ++i) - memcpy(&temp_c[i * copySize], props.field + i * props.partSize, copySize); + if (props.convert_part == NULL && + props.convert_gpart == NULL) { /* No conversion */ + + char* temp_c = temp; + for (size_t i = 0; i < N; ++i) + memcpy(&temp_c[i * copySize], props.field + i * props.partSize, copySize); + + } else if (props.convert_part != NULL) { /* conversion (for parts)*/ + + float* temp_f = temp; + for (size_t i = 0; i < N; ++i) + temp_f[i] = props.convert_part(e, &props.parts[i]); + + } else if (props.convert_gpart != NULL) { /* conversion (for gparts)*/ + + float* temp_f = temp; + for (size_t i = 0; i < N; ++i) + temp_f[i] = props.convert_gpart(e, &props.gparts[i]); + } /* Unit conversion if necessary */ const double factor = @@ -885,7 +902,7 @@ void write_output_serial(struct engine* e, const char* baseName, /* Write everything */ for (int i = 0; i < num_fields; ++i) - writeArray(h_grp, fileName, xmfFile, partTypeGroupName, list[i], N, + writeArray(e, h_grp, fileName, xmfFile, partTypeGroupName, list[i], N, N_total[ptype], mpi_rank, offset[ptype], internal_units, snapshot_units); diff --git a/src/single_io.c b/src/single_io.c index 3f634737194bf8bfdc780e662262b228ebc5c737..f88f3da5c352fc30f1a34de453e9b9abfacd3ad7 100644 --- a/src/single_io.c +++ b/src/single_io.c @@ -152,6 +152,7 @@ void readArray(hid_t h_grp, const struct io_props prop, size_t N, /** * @brief Writes a data array in given HDF5 group. * + * @param e The #engine we are writing from. * @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 @@ -165,7 +166,7 @@ void readArray(hid_t h_grp, const struct io_props prop, size_t N, * @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. */ -void writeArray(hid_t grp, char* fileName, FILE* xmfFile, +void writeArray(struct engine* e, hid_t grp, char* fileName, FILE* xmfFile, char* partTypeGroupName, const struct io_props props, size_t N, const struct UnitSystem* internal_units, const struct UnitSystem* snapshot_units) { @@ -181,9 +182,25 @@ void writeArray(hid_t grp, char* fileName, FILE* xmfFile, if (temp == NULL) error("Unable to allocate memory for temporary buffer"); /* Copy particle data to temporary buffer */ - char* temp_c = temp; - for (size_t i = 0; i < N; ++i) - memcpy(&temp_c[i * copySize], props.field + i * props.partSize, copySize); + if (props.convert_part == NULL && + props.convert_gpart == NULL) { /* No conversion */ + + char* temp_c = temp; + for (size_t i = 0; i < N; ++i) + memcpy(&temp_c[i * copySize], props.field + i * props.partSize, copySize); + + } else if (props.convert_part != NULL) { /* conversion (for parts)*/ + + float* temp_f = temp; + for (size_t i = 0; i < N; ++i) + temp_f[i] = props.convert_part(e, &props.parts[i]); + + } else if (props.convert_gpart != NULL) { /* conversion (for gparts)*/ + + float* temp_f = temp; + for (size_t i = 0; i < N; ++i) + temp_f[i] = props.convert_gpart(e, &props.gparts[i]); + } /* Unit conversion if necessary */ const double factor = @@ -695,7 +712,7 @@ void write_output_single(struct engine* e, const char* baseName, /* Write everything */ for (int i = 0; i < num_fields; ++i) - writeArray(h_grp, fileName, xmfFile, partTypeGroupName, list[i], N, + writeArray(e, h_grp, fileName, xmfFile, partTypeGroupName, list[i], N, internal_units, snapshot_units); /* Free temporary array */