Commit 1cfe23ed authored by Matthieu Schaller's avatar Matthieu Schaller
Browse files

Merge branch 'select_io' into 'master'

Select io

Closes #410

See merge request !520
parents d1c7cce9 abaa8d02
......@@ -80,6 +80,7 @@ tests/test_nonsym_force_1_vec.dat
tests/test_nonsym_force_2_vec.dat
tests/potential.dat
tests/testGreetings
tests/testSelectOutput
tests/testReading
tests/testSingle
tests/testTimeIntegration
......@@ -102,6 +103,7 @@ tests/test125cells.sh
tests/test125cellsPerturbed.sh
tests/testParser.sh
tests/testReading.sh
tests/testSelectOutput.sh
tests/testAdiabaticIndex
tests/testRiemannExact
tests/testRiemannTRRS
......
......@@ -1275,6 +1275,7 @@ AC_CONFIG_FILES([tests/testPeriodicBC.sh], [chmod +x tests/testPeriodicBC.sh])
AC_CONFIG_FILES([tests/testPeriodicBCPerturbed.sh], [chmod +x tests/testPeriodicBCPerturbed.sh])
AC_CONFIG_FILES([tests/testInteractions.sh], [chmod +x tests/testInteractions.sh])
AC_CONFIG_FILES([tests/testParser.sh], [chmod +x tests/testParser.sh])
AC_CONFIG_FILES([tests/testSelectOutput.sh], [chmod +x tests/testSelectOutput.sh])
# Save the compilation options
AC_DEFINE_UNQUOTED([SWIFT_CONFIG_FLAGS],["$swift_config_flags"],[Flags passed to configure])
......
......@@ -19,7 +19,7 @@ Snapshots:
time_first: 0. # Time of the first output (in internal units)
delta_time: 1e-2 # Time difference between consecutive outputs (in internal units)
compression: 4
# Parameters governing the conserved quantities statistics
Statistics:
delta_time: 1e-3 # Time between statistics output
......@@ -33,4 +33,4 @@ SPH:
InitialConditions:
file_name: ./sedov.hdf5
smoothing_length_scaling: 3.33
\ No newline at end of file
......@@ -90,6 +90,8 @@ void print_help_message(void) {
printf(" %2s %14s %s\n", "-n", "{int}",
"Execute a fixed number of time steps. When unset use the time_end "
"parameter to stop.");
printf(" %2s %14s %s\n", "-o", "{str}",
"Generate a default output parameter file.");
printf(" %2s %14s %s\n", "-P", "{sec:par:val}",
"Set parameter value and overwrites values read from the parameters "
"file. Can be used more than once.");
......@@ -195,6 +197,7 @@ int main(int argc, char *argv[]) {
int nr_threads = 1;
int with_verbose_timers = 0;
int nparams = 0;
char output_parameters_filename[200] = "";
char *cmdparams[PARSER_MAX_NO_OF_PARAMS];
char paramFileName[200] = "";
char restart_file[200] = "";
......@@ -202,7 +205,7 @@ int main(int argc, char *argv[]) {
/* Parse the parameters */
int c;
while ((c = getopt(argc, argv, "acCdDef:FgGhMn:P:rsSt:Tv:y:Y:")) != -1)
while ((c = getopt(argc, argv, "acCdDef:FgGhMn:o:P:rsSt:Tv:y:Y:")) != -1)
switch (c) {
case 'a':
#if defined(HAVE_SETAFFINITY) && defined(HAVE_LIBNUMA)
......@@ -259,6 +262,15 @@ int main(int argc, char *argv[]) {
return 1;
}
break;
case 'o':
if (sscanf(optarg, "%s", output_parameters_filename) != 1) {
if (myrank == 0) {
printf("Error parsing output fields filename");
print_help_message();
}
return 1;
}
break;
case 'P':
cmdparams[nparams] = optarg;
nparams++;
......@@ -324,6 +336,15 @@ int main(int argc, char *argv[]) {
return 1;
break;
}
/* Write output parameter file */
if (myrank == 0 && strcmp(output_parameters_filename, "") != 0) {
io_write_output_field_parameter(output_parameters_filename);
printf("End of run.\n");
return 0;
}
/* check inputs */
if (optind == argc - 1) {
if (!strcpy(paramFileName, argv[optind++]))
error("Error reading parameter file name.");
......@@ -713,6 +734,9 @@ int main(int argc, char *argv[]) {
"ICs.",
N_total[0], N_total[2], N_total[1]);
/* Verify that the fields to dump actually exist */
if (myrank == 0) io_check_output_fields(params, N_total);
/* Initialize the space with these data. */
if (myrank == 0) clocks_gettime(&tic);
space_init(&s, params, &cosmo, dim, parts, gparts, sparts, Ngas, Ngpart,
......@@ -811,6 +835,7 @@ int main(int argc, char *argv[]) {
&cooling_func, &chemistry, &sourceterms);
engine_config(0, &e, params, nr_nodes, myrank, nr_threads, with_aff,
talking, restart_file);
if (myrank == 0) {
clocks_gettime(&toc);
message("engine_init took %.3f %s.", clocks_diff(&tic, &toc),
......
......@@ -30,7 +30,8 @@
*
* @return Returns the number of fields to read.
*/
int chemistry_read_particles(struct part* parts, struct io_props* list) {
INLINE static int chemistry_read_particles(struct part* parts,
struct io_props* list) {
/* Nothing to read */
return 0;
......@@ -44,7 +45,8 @@ int chemistry_read_particles(struct part* parts, struct io_props* list) {
*
* @return Returns the number of fields to write.
*/
int chemistry_write_particles(const struct part* parts, struct io_props* list) {
INLINE static int chemistry_write_particles(const struct part* parts,
struct io_props* list) {
/* List what we want to write */
list[0] = io_make_output_field("ElementAbundance", FLOAT,
......@@ -101,7 +103,7 @@ int chemistry_write_particles(const struct part* parts, struct io_props* list) {
* @brief Writes the current model of SPH to the file
* @param h_grpsph The HDF5 group in which to write
*/
void chemistry_write_flavour(hid_t h_grp) {
INLINE static void chemistry_write_flavour(hid_t h_grp) {
io_write_attribute_s(h_grp, "Chemistry Model", "EAGLE");
for (int elem = 0; elem < chemistry_element_count; ++elem) {
......
......@@ -48,8 +48,8 @@ chemistry_get_element_name(enum chemistry_element elem) {
*
* @return Returns the number of fields to read.
*/
__attribute__((always_inline)) INLINE static int chemistry_read_particles(
struct part* parts, struct io_props* list) {
INLINE static int chemistry_read_particles(struct part* parts,
struct io_props* list) {
/* List what we want to read */
list[0] = io_make_input_field(
......@@ -69,13 +69,14 @@ __attribute__((always_inline)) INLINE static int chemistry_read_particles(
*
* @return Returns the number of fields to write.
*/
__attribute__((always_inline)) INLINE static int chemistry_write_particles(
const struct part* parts, struct io_props* list) {
INLINE static int chemistry_write_particles(const struct part* parts,
struct io_props* list) {
/* List what we want to write */
list[0] = io_make_output_field(
"SmoothedElementAbundance", FLOAT, chemistry_element_count,
UNIT_CONV_NO_UNITS, parts, chemistry_data.smoothed_metal_mass_fraction);
list[1] = io_make_output_field("Z", FLOAT, 1, UNIT_CONV_NO_UNITS, parts,
chemistry_data.Z);
......@@ -92,8 +93,7 @@ __attribute__((always_inline)) INLINE static int chemistry_write_particles(
* @brief Writes the current model of SPH to the file
* @param h_grp The HDF5 group in which to write
*/
__attribute__((always_inline)) INLINE static void chemistry_write_flavour(
hid_t h_grp) {
INLINE static void chemistry_write_flavour(hid_t h_grp) {
io_write_attribute_s(h_grp, "Chemistry Model", "GEAR");
for (enum chemistry_element i = chemistry_element_O;
......
......@@ -29,7 +29,8 @@
*
* @return Returns the number of fields to write.
*/
int chemistry_read_particles(struct part* parts, struct io_props* list) {
INLINE static int chemistry_read_particles(struct part* parts,
struct io_props* list) {
/* update list according to hydro_io */
......@@ -45,7 +46,8 @@ int chemistry_read_particles(struct part* parts, struct io_props* list) {
*
* @return Returns the number of fields to write.
*/
int chemistry_write_particles(const struct part* parts, struct io_props* list) {
INLINE static int chemistry_write_particles(const struct part* parts,
struct io_props* list) {
/* update list according to hydro_io */
......@@ -59,7 +61,7 @@ int chemistry_write_particles(const struct part* parts, struct io_props* list) {
* @brief Writes the current model of SPH to the file
* @param h_grp The HDF5 group in which to write
*/
void chemistry_write_flavour(hid_t h_grp) {
INLINE static void chemistry_write_flavour(hid_t h_grp) {
io_write_attribute_s(h_grp, "Chemistry Model", "None");
}
......
......@@ -25,12 +25,17 @@
#include "common_io.h"
/* Local includes. */
#include "chemistry_io.h"
#include "engine.h"
#include "error.h"
#include "gravity_io.h"
#include "hydro.h"
#include "hydro_io.h"
#include "io_properties.h"
#include "kernel_hydro.h"
#include "part.h"
#include "part_type.h"
#include "stars_io.h"
#include "threadpool.h"
#include "units.h"
#include "version.h"
......@@ -806,3 +811,157 @@ void io_collect_dm_gparts(const struct gpart* const gparts, size_t Ntot,
error("Collected the wrong number of dm particles (%zu vs. %zu expected)",
count, Ndm);
}
/**
* @brief Verify the io parameter file
*
* @param params The #swift_params
* @param N_total The total number of each particle type.
*/
void io_check_output_fields(const struct swift_params* params,
const long long N_total[3]) {
/* Create some fake particles as arguments for the writing routines */
struct part p;
struct xpart xp;
struct spart sp;
struct gpart gp;
/* Copy N_total to array with length == 6 */
const long long nr_total[swift_type_count] = {
N_total[0], N_total[1], N_total[2], 0, 0, 0};
/* Loop over all particle types to check the fields */
for (int ptype = 0; ptype < swift_type_count; ptype++) {
int num_fields = 0;
struct io_props list[100];
/* Don't do anything if no particle of this kind */
if (nr_total[ptype] == 0) continue;
/* Gather particle fields from the particle structures */
switch (ptype) {
case swift_type_gas:
hydro_write_particles(&p, &xp, list, &num_fields);
num_fields += chemistry_write_particles(&p, list + num_fields);
break;
case swift_type_dark_matter:
darkmatter_write_particles(&gp, list, &num_fields);
break;
case swift_type_star:
star_write_particles(&sp, list, &num_fields);
break;
default:
error("Particle Type %d not yet supported. Aborting", ptype);
}
/* loop over each parameter */
for (int param_id = 0; param_id < params->paramCount; param_id++) {
const char* param_name = params->data[param_id].name;
char section_name[PARSER_MAX_LINE_SIZE];
/* Skip if wrong section */
sprintf(section_name, "SelectOutput:");
if (strstr(param_name, section_name) == NULL) continue;
/* Skip if wrong particle type */
sprintf(section_name, "_%s", part_type_names[ptype]);
if (strstr(param_name, section_name) == NULL) continue;
int found = 0;
/* loop over each possible output field */
for (int field_id = 0; field_id < num_fields; field_id++) {
char field_name[PARSER_MAX_LINE_SIZE];
sprintf(field_name, "SelectOutput:%s_%s", list[field_id].name,
part_type_names[ptype]);
if (strcmp(param_name, field_name) == 0) {
found = 1;
/* check if correct input */
int retParam = 0;
char str[PARSER_MAX_LINE_SIZE];
sscanf(params->data[param_id].value, "%d%s", &retParam, str);
/* Check that we have a 0 or 1 */
if (retParam != 0 && retParam != 1)
message(
"WARNING: Unexpected input for %s. Received %i but expect 0 or "
"1. ",
field_name, retParam);
/* Found it, so move to the next one. */
break;
}
}
if (!found)
message(
"WARNING: Trying to dump particle field '%s' (read from '%s') that "
"does not exist.",
param_name, params->fileName);
}
}
}
/**
* @brief Write the output field parameters file
*
* @param filename The file to write
*/
void io_write_output_field_parameter(const char* filename) {
FILE* file = fopen(filename, "w");
if (file == NULL) error("Error opening file '%s'", filename);
/* Loop over all particle types */
fprintf(file, "SelectOutput:\n");
for (int ptype = 0; ptype < swift_type_count; ptype++) {
int num_fields = 0;
struct io_props list[100];
/* Write particle fields from the particle structure */
switch (ptype) {
case swift_type_gas:
hydro_write_particles(NULL, NULL, list, &num_fields);
num_fields += chemistry_write_particles(NULL, list + num_fields);
break;
case swift_type_dark_matter:
darkmatter_write_particles(NULL, list, &num_fields);
break;
case swift_type_star:
star_write_particles(NULL, list, &num_fields);
break;
default:
break;
}
if (num_fields == 0) continue;
/* Output a header for that particle type */
fprintf(file, " # Particle Type %s\n", part_type_names[ptype]);
/* Write all the fields of this particle type */
for (int i = 0; i < num_fields; ++i)
fprintf(file, " %s_%s: 1\n", list[i].name, part_type_names[ptype]);
fprintf(file, "\n");
}
fclose(file);
printf(
"List of valid ouput fields for the particle in snapshots dumped in "
"'%s'.\n",
filename);
}
......@@ -100,4 +100,9 @@ void io_duplicate_star_gparts(struct threadpool* tp, struct spart* const sparts,
struct gpart* const gparts, size_t Nstars,
size_t Ndm);
void io_check_output_fields(const struct swift_params* params,
const long long N_total[3]);
void io_write_output_field_parameter(const char* filename);
#endif /* SWIFT_COMMON_IO_H */
......@@ -21,8 +21,8 @@
#include "io_properties.h"
void convert_gpart_pos(const struct engine* e, const struct gpart* gp,
double* ret) {
INLINE static void convert_gpart_pos(const struct engine* e,
const struct gpart* gp, double* ret) {
if (e->s->periodic) {
ret[0] = box_wrap(gp->x[0], 0.0, e->s->dim[0]);
......@@ -35,8 +35,8 @@ void convert_gpart_pos(const struct engine* e, const struct gpart* gp,
}
}
void convert_gpart_vel(const struct engine* e, const struct gpart* gp,
float* ret) {
INLINE static void convert_gpart_vel(const struct engine* e,
const struct gpart* gp, float* ret) {
const int with_cosmology = (e->policy & engine_policy_cosmology);
const struct cosmology* cosmo = e->cosmology;
......@@ -74,8 +74,9 @@ void convert_gpart_vel(const struct engine* e, const struct gpart* gp,
* @param list The list of i/o properties to read.
* @param num_fields The number of i/o fields to read.
*/
void darkmatter_read_particles(struct gpart* gparts, struct io_props* list,
int* num_fields) {
INLINE static void darkmatter_read_particles(struct gpart* gparts,
struct io_props* list,
int* num_fields) {
/* Say how much we want to read */
*num_fields = 4;
......@@ -98,8 +99,9 @@ void darkmatter_read_particles(struct gpart* gparts, struct io_props* list,
* @param list The list of i/o properties to write.
* @param num_fields The number of i/o fields to write.
*/
void darkmatter_write_particles(const struct gpart* gparts,
struct io_props* list, int* num_fields) {
INLINE static void darkmatter_write_particles(const struct gpart* gparts,
struct io_props* list,
int* num_fields) {
/* Say how much we want to write */
*num_fields = 5;
......
......@@ -31,8 +31,9 @@
* @param list The list of i/o properties to read.
* @param num_fields The number of i/o fields to read.
*/
void hydro_read_particles(struct part* parts, struct io_props* list,
int* num_fields) {
INLINE static void hydro_read_particles(struct part* parts,
struct io_props* list,
int* num_fields) {
*num_fields = 8;
......@@ -55,8 +56,9 @@ void hydro_read_particles(struct part* parts, struct io_props* list,
UNIT_CONV_DENSITY, parts, rho);
}
void convert_part_pos(const struct engine* e, const struct part* p,
const struct xpart* xp, double* ret) {
INLINE static void convert_part_pos(const struct engine* e,
const struct part* p,
const struct xpart* xp, double* ret) {
if (e->s->periodic) {
ret[0] = box_wrap(p->x[0], 0.0, e->s->dim[0]);
......@@ -69,8 +71,9 @@ void convert_part_pos(const struct engine* e, const struct part* p,
}
}
void convert_part_vel(const struct engine* e, const struct part* p,
const struct xpart* xp, float* ret) {
INLINE static void convert_part_vel(const struct engine* e,
const struct part* p,
const struct xpart* xp, float* ret) {
const int with_cosmology = (e->policy & engine_policy_cosmology);
const struct cosmology* cosmo = e->cosmology;
......@@ -103,8 +106,9 @@ void convert_part_vel(const struct engine* e, const struct part* p,
ret[2] *= cosmo->a2_inv;
}
void convert_part_potential(const struct engine* e, const struct part* p,
const struct xpart* xp, float* ret) {
INLINE static void convert_part_potential(const struct engine* e,
const struct part* p,
const struct xpart* xp, float* ret) {
if (p->gpart != NULL)
ret[0] = gravity_get_comoving_potential(p->gpart);
......@@ -119,8 +123,10 @@ void convert_part_potential(const struct engine* e, const struct part* p,
* @param list The list of i/o properties to write.
* @param num_fields The number of i/o fields to write.
*/
void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
struct io_props* list, int* num_fields) {
INLINE static void hydro_write_particles(const struct part* parts,
const struct xpart* xparts,
struct io_props* list,
int* num_fields) {
*num_fields = 8;
......@@ -149,7 +155,7 @@ void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
* @brief Writes the current model of SPH to the file
* @param h_grpsph The HDF5 group in which to write
*/
void hydro_write_flavour(hid_t h_grpsph) {
INLINE static void hydro_write_flavour(hid_t h_grpsph) {
/* Viscosity and thermal conduction */
io_write_attribute_s(h_grpsph, "Thermal Conductivity Model",
......@@ -178,6 +184,6 @@ void hydro_write_flavour(hid_t h_grpsph) {
*
* @return 1 if entropy is in 'internal energy', 0 otherwise.
*/
int writeEntropyFlag(void) { return 0; }
INLINE static int writeEntropyFlag(void) { return 0; }
#endif /* SWIFT_DEFAULT_HYDRO_IO_H */
......@@ -31,8 +31,9 @@
* @param list The list of i/o properties to read.
* @param num_fields The number of i/o fields to read.
*/
void hydro_read_particles(struct part* parts, struct io_props* list,
int* num_fields) {
INLINE static void hydro_read_particles(struct part* parts,
struct io_props* list,
int* num_fields) {
*num_fields = 8;
......@@ -55,20 +56,21 @@ void hydro_read_particles(struct part* parts, struct io_props* list,
UNIT_CONV_DENSITY, parts, rho);
}
void convert_part_u(const struct engine* e, const struct part* p,
const struct xpart* xp, float* ret) {
INLINE static void convert_part_u(const struct engine* e, const struct part* p,
const struct xpart* xp, float* ret) {
ret[0] = hydro_get_comoving_internal_energy(p);
}
void convert_part_P(const struct engine* e, const struct part* p,
const struct xpart* xp, float* ret) {
INLINE static void convert_part_P(const struct engine* e, const struct part* p,
const struct xpart* xp, float* ret) {
ret[0] = hydro_get_comoving_pressure(p);
}
void convert_part_pos(const struct engine* e, const struct part* p,
const struct xpart* xp, double* ret) {
INLINE static void convert_part_pos(const struct engine* e,
const struct part* p,
const struct xpart* xp, double* ret) {
if (e->s->periodic) {
ret[0] = box_wrap(p->x[0], 0.0, e->s->dim[0]);
......@@ -81,8 +83,9 @@ void convert_part_pos(const struct engine* e, const struct part* p,
}
}
void convert_part_vel(const struct engine* e, const struct part* p,
const struct xpart* xp, float* ret) {
INLINE static void convert_part_vel(const struct engine* e,
const struct part* p,
const struct xpart* xp, float* ret) {
const int with_cosmology = (e->policy & engine_policy_cosmology);
const struct cosmology* cosmo = e->cosmology;
......@@ -115,8 +118,9 @@ void convert_part_vel(const struct engine* e, const struct part* p,
ret[2] *= cosmo->a2_inv;
}
void convert_part_potential(const struct engine* e, const struct part* p,
const struct xpart* xp, float* ret) {
INLINE static void convert_part_potential(const struct engine* e,
const struct part* p,
const struct xpart* xp, float* ret) {
if (p->gpart != NULL)
ret[0] = gravity_get_comoving_potential(p->gpart);
......@@ -131,8 +135,10 @@ void convert_part_potential(const struct engine* e, const struct part* p,
* @param list The list of i/o properties to write.
* @param num_fields The number of i/o fields to write.
*/
void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
struct io_props* list, int* num_fields) {
INLINE static void hydro_write_particles(const struct part* parts,
const struct xpart* xparts,
struct io_props* list,
int* num_fields) {
*num_fields = 10;
......@@ -185,7 +191,7 @@ void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
* @brief Writes the current model of SPH to the file
* @param h_grpsph The HDF5 group in which to write
*/
void hydro_write_flavour(hid_t h_grpsph) {
INLINE static void hydro_write_flavour(hid_t h_grpsph) {
/* Viscosity and thermal conduction */
io_write_attribute_s(h_grpsph, "Thermal Conductivity Model",
......@@ -202,6 +208,6 @@ void hydro_write_flavour(hid_t h_grpsph) {
*
* @return 1 if entropy is in 'internal energy', 0 otherwise.
*/
int writeEntropyFlag(void) { return 0; }
INLINE static int writeEntropyFlag(void) { return 0; }
#endif /* SWIFT_GADGET2_HYDRO_IO_H */
......@@ -40,8 +40,9 @@
* @param list The list of i/o properties to read.
* @param num_fields The number of i/o fields to read.
*/
void hydro_read_particles(struct part* parts, struct io_props* list,
int* num_fields) {
INLINE static void hydro_read_particles(struct part* parts,
struct io_props* list,
int* num_fields) {