Commit f53617b2 authored by Peter W. Draper's avatar Peter W. Draper
Browse files

Merge branch 'io_unit_conversion' into 'master'

Io unit conversion

This implements two changes:

 - Unit conversion from ICs to internal units and from internal units to snapshots when doing i/o.
 - A much simpler interface to add/remove fields to be written/read during i/o.

Could you let me know whether your usual tests still run with this ? 

See merge request !194
parents 489556aa 75c9e143
......@@ -89,6 +89,14 @@ grp.attrs["Flag_Entropy_ICs"] = [0, 0, 0, 0, 0, 0]
grp = file.create_group("/RuntimePars")
grp.attrs["PeriodicBoundariesOn"] = periodic
#Units
grp = file.create_group("/Units")
grp.attrs["Unit length in cgs (U_L)"] = 3.0856776e21
grp.attrs["Unit mass in cgs (U_M)"] = 1.9885e33
grp.attrs["Unit time in cgs (U_t)"] = 3.0856776e16
grp.attrs["Unit current in cgs (U_I)"] = 1.
grp.attrs["Unit temperature in cgs (U_T)"] = 1.
#Particle group
#grp0 = file.create_group("/PartType0")
grp1 = file.create_group("/PartType1")
......
......@@ -38,3 +38,11 @@ SPH:
# Parameters related to the initial conditions
InitialConditions:
file_name: ./uniformBox.hdf5 # The file to read
# External potential parameters
PointMass:
position_x: 50. # location of external point mass in internal units
position_y: 50.
position_z: 50.
mass: 1e10 # mass of external point mass in internal units
......@@ -291,7 +291,7 @@ int main(int argc, char *argv[]) {
struct swift_params *params = malloc(sizeof(struct swift_params));
if (params == NULL) error("Error allocating memory for the parameter file.");
if (myrank == 0) {
message("Reading parameters from file '%s'", paramFileName);
message("Reading runtime parameters from file '%s'", paramFileName);
parser_read_file(paramFileName, params);
// parser_print_params(&params);
parser_write_params_to_file(params, "used_parameters.yml");
......@@ -324,11 +324,11 @@ int main(int argc, char *argv[]) {
units_init(&us, params, "InternalUnitSystem");
phys_const_init(&us, &prog_const);
if (myrank == 0 && verbose > 0) {
message("Unit system: U_M = %e g.", us.UnitMass_in_cgs);
message("Unit system: U_L = %e cm.", us.UnitLength_in_cgs);
message("Unit system: U_t = %e s.", us.UnitTime_in_cgs);
message("Unit system: U_I = %e A.", us.UnitCurrent_in_cgs);
message("Unit system: U_T = %e K.", us.UnitTemperature_in_cgs);
message("Internal unit system: U_M = %e g.", us.UnitMass_in_cgs);
message("Internal unit system: U_L = %e cm.", us.UnitLength_in_cgs);
message("Internal unit system: U_t = %e s.", us.UnitTime_in_cgs);
message("Internal unit system: U_I = %e A.", us.UnitCurrent_in_cgs);
message("Internal unit system: U_T = %e K.", us.UnitTemperature_in_cgs);
phys_const_print(&prog_const);
}
......@@ -354,17 +354,17 @@ 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, &gparts, &Ngas, &Ngpart, &periodic,
&flag_entropy_ICs, myrank, nr_nodes, MPI_COMM_WORLD,
MPI_INFO_NULL, dry_run);
read_ic_parallel(ICfileName, &us, dim, &parts, &gparts, &Ngas, &Ngpart,
&periodic, &flag_entropy_ICs, myrank, nr_nodes,
MPI_COMM_WORLD, MPI_INFO_NULL, dry_run);
#else
read_ic_serial(ICfileName, dim, &parts, &gparts, &Ngas, &Ngpart, &periodic,
read_ic_serial(ICfileName, &us, dim, &parts, &gparts, &Ngas, &Ngpart, &periodic,
&flag_entropy_ICs, myrank, nr_nodes, MPI_COMM_WORLD,
MPI_INFO_NULL, dry_run);
#endif
#else
read_ic_single(ICfileName, dim, &parts, &gparts, &Ngas, &Ngpart, &periodic,
&flag_entropy_ICs, dry_run);
read_ic_single(ICfileName, &us, dim, &parts, &gparts, &Ngas, &Ngpart,
&periodic, &flag_entropy_ICs, dry_run);
#endif
if (myrank == 0) {
clocks_gettime(&toc);
......@@ -452,7 +452,7 @@ int main(int argc, char *argv[]) {
if (myrank == 0) clocks_gettime(&tic);
struct engine e;
engine_init(&e, &s, params, nr_nodes, myrank, nr_threads, with_aff,
engine_policies, talking, &prog_const, &hydro_properties,
engine_policies, talking, &us, &prog_const, &hydro_properties,
&potential);
if (myrank == 0) {
clocks_gettime(&toc);
......
......@@ -54,7 +54,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \
# Include files for distribution, not installation.
nobase_noinst_HEADERS = approx_math.h atomic.h cycle.h error.h inline.h kernel_hydro.h kernel_gravity.h \
vector.h runner_doiact.h runner_doiact_grav.h units.h intrinsics.h minmax.h kick.h \
timestep.h drift.h adiabatic_index.h \
timestep.h drift.h adiabatic_index.h io_properties.h \
gravity.h gravity_io.h \
gravity/Default/gravity.h gravity/Default/gravity_iact.h gravity/Default/gravity_io.h \
gravity/Default/gravity_debug.h gravity/Default/gravity_part.h \
......
......@@ -58,6 +58,7 @@ const char* particle_type_names[NUM_PARTICLE_TYPES] = {
*way.
*/
hid_t hdf5Type(enum DATA_TYPE type) {
switch (type) {
case INT:
return H5T_NATIVE_INT;
......@@ -87,6 +88,7 @@ hid_t hdf5Type(enum DATA_TYPE type) {
* @brief Returns the memory size of the data type
*/
size_t sizeOfType(enum DATA_TYPE type) {
switch (type) {
case INT:
return sizeof(int);
......@@ -112,6 +114,24 @@ size_t sizeOfType(enum DATA_TYPE type) {
}
}
/**
* @brief Return 1 if the type has double precision
*
* Returns an error if the type is not FLOAT or DOUBLE
*/
int isDoublePrecision(enum DATA_TYPE type) {
switch (type) {
case FLOAT:
return 0;
case DOUBLE:
return 1;
default:
error("Invalid type");
return 0;
}
}
/**
* @brief Reads an attribute from a given HDF5 group.
*
......@@ -273,15 +293,55 @@ void writeAttribute_s(hid_t grp, const char* name, const char* str) {
writeStringAttribute(grp, name, str, strlen(str));
}
/**
* @brief Reads the Unit System from an IC file.
* @param h_file The (opened) HDF5 file from which to read.
* @param us The UnitSystem to fill.
*
* If the 'Units' group does not exist in the ICs, cgs units will be assumed
*/
void readUnitSystem(hid_t h_file, struct UnitSystem* us) {
hid_t h_grp = H5Gopen(h_file, "/Units", H5P_DEFAULT);
if (h_grp < 0) {
message("'Units' group not found in ICs. Assuming CGS unit system.");
/* Default to CGS */
us->UnitMass_in_cgs = 1.;
us->UnitLength_in_cgs = 1.;
us->UnitTime_in_cgs = 1.;
us->UnitCurrent_in_cgs = 1.;
us->UnitTemperature_in_cgs = 1.;
return;
}
/* Ok, Read the damn thing */
readAttribute(h_grp, "Unit length in cgs (U_L)", DOUBLE,
&us->UnitLength_in_cgs);
readAttribute(h_grp, "Unit mass in cgs (U_M)", DOUBLE, &us->UnitMass_in_cgs);
readAttribute(h_grp, "Unit time in cgs (U_t)", DOUBLE, &us->UnitTime_in_cgs);
readAttribute(h_grp, "Unit current in cgs (U_I)", DOUBLE,
&us->UnitCurrent_in_cgs);
readAttribute(h_grp, "Unit temperature in cgs (U_T)", DOUBLE,
&us->UnitTemperature_in_cgs);
/* Clean up */
H5Gclose(h_grp);
}
/**
* @brief Writes the current Unit System
* @param h_file The (opened) HDF5 file in which to write
* @param us The UnitSystem used in the run
* @param us The UnitSystem to dump
* @param groupName The name of the HDF5 group to write to
*/
void writeUnitSystem(hid_t h_file, struct UnitSystem* us) {
hid_t h_grpunit = 0;
void writeUnitSystem(hid_t h_file, const struct UnitSystem* us,
const char* groupName) {
h_grpunit = H5Gcreate1(h_file, "/Units", 0);
hid_t h_grpunit = 0;
h_grpunit = H5Gcreate1(h_file, groupName, 0);
if (h_grpunit < 0) error("Error while creating Unit System group");
writeAttribute_d(h_grpunit, "Unit mass in cgs (U_M)",
......@@ -484,8 +544,9 @@ void writeXMFgroupfooter(FILE* xmfFile, enum PARTICLE_TYPE ptype) {
*
* @todo Treat the types in a better way.
*/
void writeXMFline(FILE* xmfFile, char* fileName, char* partTypeGroupName,
char* name, size_t N, int dim, enum DATA_TYPE type) {
void writeXMFline(FILE* xmfFile, const char* fileName,
const char* partTypeGroupName, const 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");
......
......@@ -45,13 +45,6 @@ enum DATA_TYPE {
CHAR
};
/**
* @brief The two sorts of data present in the GADGET IC files: compulsory to
*start a run or optional.
*
*/
enum DATA_IMPORTANCE { COMPULSORY = 1, OPTIONAL = 0 };
/**
* @brief The different particle types present in a GADGET IC file
*
......@@ -69,10 +62,12 @@ enum PARTICLE_TYPE {
extern const char* particle_type_names[];
#define FILENAME_BUFFER_SIZE 150
#define PARTICLE_GROUP_BUFFER_SIZE 20
#define FIELD_BUFFER_SIZE 200
#define PARTICLE_GROUP_BUFFER_SIZE 50
hid_t hdf5Type(enum DATA_TYPE type);
size_t sizeOfType(enum DATA_TYPE type);
int isDoublePrecision(enum DATA_TYPE type);
void collect_dm_gparts(const struct gpart* const gparts, size_t Ntot,
struct gpart* const dmparts, size_t Ndm);
......@@ -99,11 +94,15 @@ 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 writeXMFline(FILE* xmfFile, const char* fileName,
const char* partTypeGroupName, const char* name, size_t N,
int dim, enum DATA_TYPE type);
void writeCodeDescription(hid_t h_file);
void writeUnitSystem(hid_t h_file, struct UnitSystem* us);
void readUnitSystem(hid_t h_file, struct UnitSystem* us);
void writeUnitSystem(hid_t h_grp, const struct UnitSystem* us,
const char* groupName);
#endif /* defined HDF5 */
......
......@@ -2677,14 +2677,17 @@ void engine_dump_snapshot(struct engine *e) {
/* Dump... */
#if defined(WITH_MPI)
#if defined(HAVE_PARALLEL_HDF5)
write_output_parallel(e, e->snapshotBaseName, e->snapshotUnits, e->nodeID,
e->nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
write_output_parallel(e, e->snapshotBaseName, e->internalUnits,
e->snapshotUnits, e->nodeID, e->nr_nodes,
MPI_COMM_WORLD, MPI_INFO_NULL);
#else
write_output_serial(e, e->snapshotBaseName, e->snapshotUnits, e->nodeID,
e->nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
write_output_serial(e, e->snapshotBaseName, e->internalUnits,
e->snapshotUnits, e->nodeID, e->nr_nodes, MPI_COMM_WORLD,
MPI_INFO_NULL);
#endif
#else
write_output_single(e, e->snapshotBaseName, e->snapshotUnits);
write_output_single(e, e->snapshotBaseName, e->internalUnits,
e->snapshotUnits);
#endif
clocks_gettime(&time2);
......@@ -2759,6 +2762,7 @@ void engine_unpin() {
* @param with_aff use processor affinity, if supported.
* @param policy The queuing policy to use.
* @param verbose Is this #engine talkative ?
* @param internal_units The system of units used internally.
* @param physical_constants The #phys_const used for this run.
* @param hydro The #hydro_props used for this run.
* @param potential The properties of the external potential.
......@@ -2766,6 +2770,7 @@ void engine_unpin() {
void engine_init(struct engine *e, struct space *s,
const struct swift_params *params, int nr_nodes, int nodeID,
int nr_threads, int with_aff, int policy, int verbose,
const struct UnitSystem *internal_units,
const struct phys_const *physical_constants,
const struct hydro_props *hydro,
const struct external_potential *potential) {
......@@ -2795,6 +2800,7 @@ void engine_init(struct engine *e, struct space *s,
e->timeStep = 0.;
e->timeBase = 0.;
e->timeBase_inv = 0.;
e->internalUnits = internal_units;
e->timeFirstSnapshot =
parser_get_param_double(params, "Snapshots:time_first");
e->deltaTimeSnapshot =
......
......@@ -139,6 +139,9 @@ struct engine {
/* Number of particles updated */
size_t updates, g_updates;
/* The internal system of units */
const struct UnitSystem *internalUnits;
/* Snapshot information */
double timeFirstSnapshot;
double deltaTimeSnapshot;
......@@ -212,6 +215,7 @@ void engine_dump_snapshot(struct engine *e);
void engine_init(struct engine *e, struct space *s,
const struct swift_params *params, int nr_nodes, int nodeID,
int nr_threads, int with_aff, int policy, int verbose,
const struct UnitSystem *internal_units,
const struct phys_const *physical_constants,
const struct hydro_props *hydro,
const struct external_potential *potential);
......
......@@ -17,64 +17,54 @@
*
******************************************************************************/
#include "io_properties.h"
/**
* @brief Read dark matter particles from HDF5.
*
* @param h_grp The HDF5 group in which to read the arrays.
* @param N The number of particles on that MPI rank.
* @param N_total The total number of particles (only used in MPI mode)
* @param offset The offset of the particles for this MPI rank (only used in MPI
*mode)
* @param gparts The particle array
* @brief Specifies which g-particle fields to read from a dataset
*
* @param gparts The g-particle array.
* @param list The list of i/o properties to read.
* @param num_fields The number of i/o fields to read.
*/
__attribute__((always_inline)) INLINE static void darkmatter_read_particles(
hid_t h_grp, int N, long long N_total, long long offset,
struct gpart* gparts) {
void darkmatter_read_particles(struct gpart* gparts, struct io_props* list,
int* num_fields) {
/* Say how much we want to read */
*num_fields = 4;
/* Read arrays */
readArray(h_grp, "Coordinates", DOUBLE, N, 3, gparts, N_total, offset, x,
COMPULSORY);
readArray(h_grp, "Masses", FLOAT, N, 1, gparts, N_total, offset, mass,
COMPULSORY);
readArray(h_grp, "Velocities", FLOAT, N, 3, gparts, N_total, offset, v_full,
COMPULSORY);
readArray(h_grp, "ParticleIDs", ULONGLONG, N, 1, gparts, N_total, offset,
id_or_neg_offset, COMPULSORY);
/* List what we want to read */
list[0] = io_make_input_field("Coordinates", DOUBLE, 3, COMPULSORY,
UNIT_CONV_LENGTH, gparts, x);
list[1] = io_make_input_field("Velocities", FLOAT, 3, COMPULSORY,
UNIT_CONV_SPEED, gparts, v_full);
list[2] = io_make_input_field("Masses", FLOAT, 1, COMPULSORY, UNIT_CONV_MASS,
gparts, mass);
list[3] = io_make_input_field("ParticleIDs", ULONGLONG, 1, COMPULSORY,
UNIT_CONV_NO_UNITS, gparts, id_or_neg_offset);
}
/**
* @brief Writes the different particles to the HDF5 file
*
* @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)
* @param mpi_rank The MPI rank of this node (only used in MPI mode)
* @param offset The offset of the particles for this MPI rank (only used in MPI
*mode)
* @param gparts The #gpart array
* @param us The unit system to use
* @brief Specifies which g-particle fields to write to a dataset
*
* @param gparts The g-particle array.
* @param list The list of i/o properties to write.
* @param num_fields The number of i/o fields to write.
*/
__attribute__((always_inline)) INLINE static void darkmatter_write_particles(
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) {
void darkmatter_write_particles(struct gpart* gparts, struct io_props* list,
int* num_fields) {
/* Say how much we want to read */
*num_fields = 5;
/* Write arrays */
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_or_neg_offset, us, UNIT_CONV_NO_UNITS);
/* List what we want to read */
list[0] = io_make_output_field("Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH,
gparts, x);
list[1] = io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED,
gparts, v_full);
list[2] =
io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, gparts, mass);
list[3] = io_make_output_field("ParticleIDs", ULONGLONG, 1,
UNIT_CONV_NO_UNITS, gparts, id_or_neg_offset);
list[4] = io_make_output_field("Acceleration", FLOAT, 3,
UNIT_CONV_ACCELERATION, gparts, a_grav);
}
......@@ -17,83 +17,69 @@
*
******************************************************************************/
#include "io_properties.h"
#include "kernel_hydro.h"
/**
* @brief Reads the different particles to the HDF5 file
*
* @param h_grp The HDF5 group in which to read the arrays.
* @param N The number of particles on that MPI rank.
* @param N_total The total number of particles (only used in MPI mode)
* @param offset The offset of the particles for this MPI rank (only used in MPI
*mode)
* @param parts The particle array
* @brief Specifies which particle fields to read from a dataset
*
* @param parts The particle array.
* @param list The list of i/o properties to read.
* @param num_fields The number of i/o fields to read.
*/
__attribute__((always_inline)) INLINE static void hydro_read_particles(
hid_t h_grp, int N, long long N_total, long long offset,
struct part* parts) {
void hydro_read_particles(struct part* parts, struct io_props* list,
int* num_fields) {
*num_fields = 8;
/* Read arrays */
readArray(h_grp, "Coordinates", DOUBLE, N, 3, parts, N_total, offset, x,
COMPULSORY);
readArray(h_grp, "Velocities", FLOAT, N, 3, parts, N_total, offset, v,
COMPULSORY);
readArray(h_grp, "Masses", FLOAT, N, 1, parts, N_total, offset, mass,
COMPULSORY);
readArray(h_grp, "SmoothingLength", FLOAT, N, 1, parts, N_total, offset, h,
COMPULSORY);
readArray(h_grp, "InternalEnergy", FLOAT, N, 1, parts, N_total, offset, u,
COMPULSORY);
readArray(h_grp, "ParticleIDs", ULONGLONG, N, 1, parts, N_total, offset, id,
COMPULSORY);
readArray(h_grp, "Acceleration", FLOAT, N, 3, parts, N_total, offset, a_hydro,
OPTIONAL);
readArray(h_grp, "Density", FLOAT, N, 1, parts, N_total, offset, rho,
OPTIONAL);
/* List what we want to read */
list[0] = io_make_input_field("Coordinates", DOUBLE, 3, COMPULSORY,
UNIT_CONV_LENGTH, parts, x);
list[1] = io_make_input_field("Velocities", FLOAT, 3, COMPULSORY,
UNIT_CONV_SPEED, parts, v);
list[2] = io_make_input_field("Masses", FLOAT, 1, COMPULSORY, UNIT_CONV_MASS,
parts, mass);
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);
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,
UNIT_CONV_ACCELERATION, parts, a_hydro);
list[7] = io_make_input_field("Density", FLOAT, 1, OPTIONAL,
UNIT_CONV_DENSITY, parts, rho);
}
/**
* @brief Writes the different particles to the HDF5 file
*
* @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)
* @param mpi_rank The MPI rank of this node (only used in MPI mode)
* @param offset The offset of the particles for this MPI rank (only used in MPI
*mode)
* @param parts The particle array
* @param us The unit system to use
* @brief Specifies which particle fields to write to a dataset
*
* @param parts The particle array.
* @param list The list of i/o properties to write.
* @param num_fields The number of i/o fields to write.
*/
__attribute__((always_inline)) INLINE static void hydro_write_particles(
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) {
void hydro_write_particles(struct part* parts, struct io_props* list,
int* num_fields) {
*num_fields = 8;
/* Write arrays */
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);
/* List what we want to write */
list[0] = io_make_output_field("Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH,
parts, x);
list[1] =
io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, v);
list[2] =
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,
UNIT_CONV_ENERGY_PER_UNIT_MASS, parts, u);
list[5] = io_make_output_field("ParticleIDs", ULONGLONG, 1,
UNIT_CONV_NO_UNITS, parts, id);
list[6] = io_make_output_field("Acceleration", FLOAT, 3,
UNIT_CONV_ACCELERATION, parts, a_hydro);
list[7] =
io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho);
}
/**
......
......@@ -17,83 +17,69 @@
*
******************************************************************************/
#include "io_properties.h"
#include "kernel_hydro.h"
/**
* @brief Reads the different particles to the HDF5 file
*
* @param h_grp The HDF5 group in which to read the arrays.
* @param N The number of particles on that MPI rank.
* @param N_total The total number of particles (only used in MPI mode)
* @param offset The offset of the particles for this MPI rank (only used in MPI
*mode)
* @param parts The particle array
* @brief Specifies which particle fields to read from a dataset
*
* @param parts The particle array.
* @param list The list of i/o properties to read.
* @param num_fields The number of i/o fields to read.
*/
__attribute__((always_inline)) INLINE static void hydro_read_particles(
hid_t h_grp, int N, long long N_total, long long offset,