diff --git a/.gitignore b/.gitignore index 8c3ede8f3125f5024c1fe01a405024d1cf5a7f19..68e34d1965ff374fa957a17d9ad0240a857cf6c8 100644 --- a/.gitignore +++ b/.gitignore @@ -102,6 +102,7 @@ tests/test125cells.sh tests/test125cellsPerturbed.sh tests/testParser.sh tests/testReading.sh +tests/testSelectOutput.sh tests/testAdiabaticIndex tests/testRiemannExact tests/testRiemannTRRS diff --git a/examples/main.c b/examples/main.c index 8fdac673e29c2409f014cbc03dfdfca5add6c761..cf30a9c2b303f843db04acb73fff2d6a70ac5f62 100644 --- a/examples/main.c +++ b/examples/main.c @@ -338,9 +338,9 @@ int main(int argc, char *argv[]) { } /* Write output parameter file */ - if (strcmp(output_parameters_filename, "") != 0) { + if (myrank == 0 && strcmp(output_parameters_filename, "") != 0) { io_write_output_field_parameter(output_parameters_filename); - printf("Ouput parameter file written in %s\n", output_parameters_filename); + printf("End of run.\n"); return 0; } @@ -734,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, @@ -833,9 +836,6 @@ int main(int argc, char *argv[]) { engine_config(0, &e, params, nr_nodes, myrank, nr_threads, with_aff, talking, restart_file); - /* check output field */ - if (myrank == 0) io_check_output_fields(params, &e, N_total); - if (myrank == 0) { clocks_gettime(&toc); message("engine_init took %.3f %s.", clocks_diff(&tic, &toc), diff --git a/src/chemistry/EAGLE/chemistry_io.h b/src/chemistry/EAGLE/chemistry_io.h index aab8ec240207a47289e35a711af8b245bf2b40fa..f87807579c46fe336f45e934d828318aed0377c7 100644 --- a/src/chemistry/EAGLE/chemistry_io.h +++ b/src/chemistry/EAGLE/chemistry_io.h @@ -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) { diff --git a/src/chemistry/GEAR/chemistry_io.h b/src/chemistry/GEAR/chemistry_io.h index bee29dd3b12afe1b08edeb64248e6ec586a3751f..2a0847bebfb8c1734f21bda2f6ad55b354a7aec9 100644 --- a/src/chemistry/GEAR/chemistry_io.h +++ b/src/chemistry/GEAR/chemistry_io.h @@ -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,8 +69,8 @@ __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( @@ -93,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; diff --git a/src/chemistry/none/chemistry_io.h b/src/chemistry/none/chemistry_io.h index fc460944ec5244ecdeda5b363a2c6c9a964c001a..ef7e0d8d87dfeab5978f0e86bbf6279f7901d10a 100644 --- a/src/chemistry/none/chemistry_io.h +++ b/src/chemistry/none/chemistry_io.h @@ -29,8 +29,8 @@ * * @return Returns the number of fields to write. */ -__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) { /* update list according to hydro_io */ @@ -46,8 +46,8 @@ __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) { /* update list according to hydro_io */ @@ -61,8 +61,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", "None"); } diff --git a/src/common_io.c b/src/common_io.c index 60158b1955b9b65cd8f1d7350bff98cc2dd6f415..bc8e547d6705a709dc75aa9d1f32a6285a647049 100644 --- a/src/common_io.c +++ b/src/common_io.c @@ -815,58 +815,61 @@ void io_collect_dm_gparts(const struct gpart* const gparts, size_t Ntot, * @brief Verify the io parameter file * * @param params The #swift_params - * @param e The #engine + * @param N_total The total number of each particle type. */ void io_check_output_fields(const struct swift_params* params, - const struct engine* e, const long long* N_total) { + const long long N_total[3]) { - /* particles */ - const struct part* parts = e->s->parts; - const struct xpart* xparts = e->s->xparts; - const struct gpart* gparts = e->s->gparts; - const struct spart* sparts = e->s->sparts; + /* 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 */ + /* 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}; - /* get all the possible outputs */ + /* 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; - /* Write particle fields from the particle structure */ + /* Gather particle fields from the particle structures */ switch (ptype) { case swift_type_gas: - hydro_write_particles(parts, xparts, list, &num_fields); - num_fields += chemistry_write_particles(parts, list + num_fields); + 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(gparts, list, &num_fields); + darkmatter_write_particles(&gp, list, &num_fields); break; case swift_type_star: - star_write_particles(sparts, list, &num_fields); + 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 */ + + /* Skip if wrong section */ sprintf(section_name, "SelectOutput:"); if (strstr(param_name, section_name) == NULL) continue; - /* skip if wrong particle type */ + /* Skip if wrong particle type */ sprintf(section_name, "_%s", part_type_names[ptype]); if (strstr(param_name, section_name) == NULL) continue; @@ -885,18 +888,20 @@ void io_check_output_fields(const struct swift_params* params, 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. " - "We will write this field.", - field_name, retParam); - continue; + error("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: Unable to find field corresponding to %s in %s", - param_name, params->fileName); + message( + "WARNING: Trying to dump particle field '%s' (read from '%s') that " + "does not exist.", + param_name, params->fileName); } } } @@ -904,15 +909,17 @@ void io_check_output_fields(const struct swift_params* params, /** * @brief Write the output field parameters file * - * @param e The #engine * @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]; @@ -931,18 +938,27 @@ void io_write_output_field_parameter(const char* filename) { 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 everything */ - for (int i = 0; i < num_fields; ++i) { + + /* 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); } diff --git a/src/common_io.h b/src/common_io.h index 8f8312b192fbe1d77e83eb06ad2cd11a935d70b1..f26a635a66f40424984238e586fcdf5bc752fc99 100644 --- a/src/common_io.h +++ b/src/common_io.h @@ -101,7 +101,7 @@ void io_duplicate_star_gparts(struct threadpool* tp, struct spart* const sparts, size_t Ndm); void io_check_output_fields(const struct swift_params* params, - const struct engine* e, const long long* N_total); + const long long N_total[3]); void io_write_output_field_parameter(const char* filename); diff --git a/src/parallel_io.c b/src/parallel_io.c index 803d2e48d070251659f6f4a5fa242a52e51bfa9b..3c073ce712c4bdcc97dd70ea6e146d92f2f1b64d 100644 --- a/src/parallel_io.c +++ b/src/parallel_io.c @@ -1019,13 +1019,16 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6], error("Particle Type %d not yet supported. Aborting", ptype); } - /* Prepare everything */ + /* Prepare everything that is not cancelled */ for (int i = 0; i < num_fields; ++i) { + + /* Did the user cancel this field? */ char field[PARSER_MAX_LINE_SIZE]; sprintf(field, "SelectOutput:%s_%s", list[i].name, part_type_names[ptype]); int should_write = parser_get_opt_param_int(params, field, 1); - if (should_write != 0) + + if (should_write) prepareArray(e, h_grp, fileName, xmfFile, partTypeGroupName, list[i], N_total[ptype], snapshot_units); } @@ -1270,13 +1273,16 @@ void write_output_parallel(struct engine* e, const char* baseName, error("Particle Type %d not yet supported. Aborting", ptype); } - /* Write everything */ + /* Write everything that is not cancelled */ for (int i = 0; i < num_fields; ++i) { + + /* Did the user cancel this field? */ char field[PARSER_MAX_LINE_SIZE]; sprintf(field, "SelectOutput:%s_%s", list[i].name, part_type_names[ptype]); int should_write = parser_get_opt_param_int(params, field, 1); - if (should_write != 0) + + if (should_write) writeArray(e, h_grp, fileName, partTypeGroupName, list[i], Nparticles, N_total[ptype], mpi_rank, offset[ptype], internal_units, snapshot_units); diff --git a/src/serial_io.c b/src/serial_io.c index 4e47f758ad3f56b57368b87a63a1f7b643e36630..750ec23bfd486e5f4f6226d4790a0af5b306b873 100644 --- a/src/serial_io.c +++ b/src/serial_io.c @@ -1007,13 +1007,16 @@ void write_output_serial(struct engine* e, const char* baseName, error("Particle Type %d not yet supported. Aborting", ptype); } - /* Write everything */ + /* Write everything that is not cancelled */ for (int i = 0; i < num_fields; ++i) { + + /* Did the user cancel this field? */ char field[PARSER_MAX_LINE_SIZE]; sprintf(field, "SelectOutput:%s_%s", list[i].name, part_type_names[ptype]); int should_write = parser_get_opt_param_int(params, field, 1); - if (should_write != 0) + + if (should_write) writeArray(e, h_grp, fileName, xmfFile, partTypeGroupName, list[i], Nparticles, N_total[ptype], mpi_rank, offset[ptype], internal_units, snapshot_units); diff --git a/src/single_io.c b/src/single_io.c index a74a0adb74a1cd2d0439a67c098b8c68f2eb2736..47599eaaa39de21a3df6ad810b7dd71b4807c995 100644 --- a/src/single_io.c +++ b/src/single_io.c @@ -826,13 +826,16 @@ void write_output_single(struct engine* e, const char* baseName, error("Particle Type %d not yet supported. Aborting", ptype); } - /* Write everything */ + /* Write everything that is not cancelled */ for (int i = 0; i < num_fields; ++i) { + + /* Did the user cancel this field? */ char field[PARSER_MAX_LINE_SIZE]; sprintf(field, "SelectOutput:%s_%s", list[i].name, part_type_names[ptype]); int should_write = parser_get_opt_param_int(params, field, 1); - if (should_write != 0) + + if (should_write) writeArray(e, h_grp, fileName, xmfFile, partTypeGroupName, list[i], N, internal_units, snapshot_units); }