diff --git a/doc/RTD/source/ParameterFiles/output_selection.rst b/doc/RTD/source/ParameterFiles/output_selection.rst index 78fa55de86c1e2a34ffc732d09f38ade0289fd73..b9f4ceb6e9a31d376e85d35cff6511f62b0e29af 100644 --- a/doc/RTD/source/ParameterFiles/output_selection.rst +++ b/doc/RTD/source/ParameterFiles/output_selection.rst @@ -117,7 +117,6 @@ example, look like: Masses_Gas: off Velocities_Gas: DScale1 Densities_Gas: FMantissa9 - ParticleIDs_Gas: IntegerNBits For convenience, there is also the option to set a default output status for @@ -128,7 +127,7 @@ field for each particle type: .. code:: YAML - BlackHolesOnly: + Default: Standard_Gas: off Standard_DM: off Standard_DMBackground: off @@ -142,7 +141,7 @@ selection: .. code:: YAML - BlackHolesOnly: + Default: basename: bh subdir: snip @@ -187,6 +186,7 @@ cousins. To do this, we will define two top-level sections in our Metal_Mass_Fractions_Gas: off Element_Mass_Fractions_Gas: off Densities_Gas: FMantissa9 + basename: snip ... To then select which outputs are 'snapshots' and which are 'snipshots', you @@ -207,8 +207,8 @@ to your choice in the output list will be written to the snapshot header as ``Header/SelectOutput``. Note that if a the name used in the ``Select Output`` column does not -exist as a section in the output selection YAML file, SWIFT will write -all the available fields. +exist as a section in the output selection YAML file, SWIFT will exit +with an error message. Using non-regular snapshot numbers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -238,5 +238,5 @@ Assuming the snapshot basename (either global or set for the ``Snapshot`` output selection) was set to ``snap``. Note that to specify labels, the ``Select Output`` column needs to be -specified (but can simply default to dumping everything). +specified. diff --git a/src/common_io_fields.c b/src/common_io_fields.c index ccae4d9eddb993b0a8c59ed1edb3b273512f07c9..574cd07b452411c97886c1ebcff3c1ac12c5d5a3 100644 --- a/src/common_io_fields.c +++ b/src/common_io_fields.c @@ -159,10 +159,16 @@ void io_prepare_output_fields(struct output_options* output_options, have_default = 1; /* How many fields should each ptype write by default? */ - int ptype_num_fields_to_write[swift_type_count]; + int ptype_num_fields_to_write[swift_type_count] = {0}; /* What is the default writing status for each ptype (on/off)? */ - int ptype_default_write_status[swift_type_count]; + int ptype_default_write_status[swift_type_count] = {0}; + + /* Default snapshot basename for this output selection */ + char basename[FILENAME_BUFFER_SIZE] = select_output_default_basename; + + /* Default snapshot subdir name for this output selection */ + char subdir_name[FILENAME_BUFFER_SIZE] = select_output_default_subdir_name; /* Initialise section-specific writing counters for each particle type. * If default is 'write', then we start from the total to deduct any fields @@ -203,8 +209,18 @@ void io_prepare_output_fields(struct output_options* output_options, * 'Standard' parameter */ if (strstr(param_name, section_name) == NULL) continue; if (strstr(param_name, ":Standard_") != NULL) continue; - if (strstr(param_name, ":basename") != NULL) continue; - if (strstr(param_name, ":subdir") != NULL) continue; + + /* Deal with a possible non-standard snapshot basename */ + if (strstr(param_name, ":basename") != NULL) { + parser_get_param_string(params, param_name, basename); + continue; + } + + /* Deal with a possible non-standard snapshot subdir name */ + if (strstr(param_name, ":subdir") != NULL) { + parser_get_param_string(params, param_name, subdir_name); + continue; + } /* Get the particle type for current parameter * (raises an error if it could not determine it) */ @@ -282,14 +298,24 @@ void io_prepare_output_fields(struct output_options* output_options, output_options->num_fields_to_write[section_id][ptype] = ptype_num_fields_to_write[ptype]; } + + /* Also copy the output names */ + strcpy(output_options->basenames[section_id], basename); + strcpy(output_options->subdir_names[section_id], subdir_name); + } /* Ends loop over sections, for different output classes */ /* Add field numbers for (possible) implicit `Default` output class */ if (!have_default) { const int default_id = output_options->select_output->sectionCount; - for (int ptype = 0; ptype < swift_type_count; ptype++) + for (int ptype = 0; ptype < swift_type_count; ptype++) { output_options->num_fields_to_write[default_id][ptype] = ptype_num_fields_total[ptype]; + } + sprintf(output_options->basenames[default_id], "%s", + select_output_default_basename); + sprintf(output_options->subdir_names[default_id], "%s", + select_output_default_subdir_name); } } diff --git a/src/engine.h b/src/engine.h index 7256adaa8eb536f6a39b827ac73ad85ac51f6663..e8b88edfc35c491c8e57c8b99ad4f6302923f5ae 100644 --- a/src/engine.h +++ b/src/engine.h @@ -571,7 +571,8 @@ void engine_check_for_index_dump(struct engine *e); void engine_collect_end_of_step(struct engine *e, int apply); void engine_dump_snapshot(struct engine *e); void engine_run_on_dump(struct engine *e); -void engine_init_output_lists(struct engine *e, struct swift_params *params); +void engine_init_output_lists(struct engine *e, struct swift_params *params, + const struct output_options *output_options); void engine_init( struct engine *e, struct space *s, struct swift_params *params, struct output_options *output_options, long long Ngas, long long Ngparts, diff --git a/src/engine_config.c b/src/engine_config.c index f8c8705d31b5e4e2d1eb8a84fe5ac97ad2a4335e..2cdf54f9fac663a89d3d244c0ba5fa51dde7b36f 100644 --- a/src/engine_config.c +++ b/src/engine_config.c @@ -472,7 +472,7 @@ void engine_config(int restart, int fof, struct engine *e, e->time_end - e->time_begin); /* Read (or re-read the list of outputs */ - engine_init_output_lists(e, params); + engine_init_output_lists(e, params, e->output_options); /* Check whether output quantities make sense */ if (e->policy & engine_policy_cosmology) { diff --git a/src/engine_io.c b/src/engine_io.c index 9f544499a7ebe69fc188d405d0332fc619ca0378..d927f9eff835f876a6af37e1f9c126244e6a06b0 100644 --- a/src/engine_io.c +++ b/src/engine_io.c @@ -882,7 +882,8 @@ void engine_compute_next_fof_time(struct engine *e) { * @param e The #engine. * @param params The #swift_params. */ -void engine_init_output_lists(struct engine *e, struct swift_params *params) { +void engine_init_output_lists(struct engine *e, struct swift_params *params, + const struct output_options *output_options) { /* Deal with snapshots */ e->output_list_snapshots = NULL; @@ -890,6 +891,13 @@ void engine_init_output_lists(struct engine *e, struct swift_params *params) { &e->delta_time_snapshot); if (e->output_list_snapshots) { + + /* If we are using a different output selection for the + * various entries, verify that the user did not specify + * invalid selections. */ + if (e->output_list_snapshots->select_output_on) + output_list_check_selection(e->output_list_snapshots, output_options); + engine_compute_next_snapshot_time(e); if (e->policy & engine_policy_cosmology) diff --git a/src/output_list.c b/src/output_list.c index b879afff92db3aee63c13f8e468c161f22801c3b..0c8608c9455031491be201e48f1d2d07f797e8da 100644 --- a/src/output_list.c +++ b/src/output_list.c @@ -168,7 +168,8 @@ void output_list_read_file(struct output_list *output_list, found_select_output = 0; for (int i = 0; i < output_list->select_output_number_of_names; i++) { - if (!strcmp(select_output_buffer, output_list->select_output_names[i])) { + if (strcmp(select_output_buffer, output_list->select_output_names[i]) == + 0) { /* We already have this select output list string in the buffer! */ output_list->select_output_indices[ind] = i; found_select_output = 1; @@ -385,6 +386,29 @@ void output_list_init(struct output_list **list, const struct engine *e, } } +/** + * @brief Verify that a given output list only contains output selections + * that have actually been read in. + * + * @param list the #output_list. + * @param output_options The #output_options we read in earlier. + */ +void output_list_check_selection(const struct output_list *list, + const struct output_options *output_options) { + + for (size_t i = 0; i < list->size; ++i) { + + const int list_id = list->select_output_indices[i]; + + const int selection_id = parser_get_section_id( + output_options->select_output, list->select_output_names[list_id]); + + if (selection_id < 0) + error("Invalid output selection found in output list: '%s'", + list->select_output_names[list_id]); + } +} + /** * @brief Print an #output_list */ diff --git a/src/output_list.h b/src/output_list.h index f68d931cd2ba3c93e79228816ee9c51618df6042..14c7a6a1d07be8af85c7669dc9164e5852586a89 100644 --- a/src/output_list.h +++ b/src/output_list.h @@ -99,7 +99,7 @@ void output_list_print(const struct output_list *output_list); void output_list_clean(struct output_list **output_list); void output_list_struct_dump(struct output_list *list, FILE *stream); void output_list_struct_restore(struct output_list *list, FILE *stream); -int output_list_check_duplicates(const struct output_list *list_a, - const struct output_list *list_b); +void output_list_check_selection(const struct output_list *list, + const struct output_options *output_options); #endif /* SWIFT_OUTPUT_LIST_H */ diff --git a/src/output_options.c b/src/output_options.c index d9f02357e239bfe83eca57d95f6e85fb445c113a..af2796972f4b5ed21d8443432f40be3ecad1472b 100644 --- a/src/output_options.c +++ b/src/output_options.c @@ -300,15 +300,32 @@ void output_options_get_basename(const struct output_options* output_options, char subdir_name[FILENAME_BUFFER_SIZE], char basename[FILENAME_BUFFER_SIZE]) { - /* Full name for the default path */ - char field[PARSER_MAX_LINE_SIZE]; - sprintf(field, "%.*s:basename", FIELD_BUFFER_SIZE, selection_name); + /* Get the ID of the output selection in the structure */ + int selection_id = + parser_get_section_id(output_options->select_output, selection_name); - parser_get_opt_param_string(output_options->select_output, field, basename, - default_basename); + /* Special treatment for absent `Default` section */ + if (selection_id < 0) { + selection_id = output_options->select_output->sectionCount; + } - sprintf(field, "%.*s:subdir", FIELD_BUFFER_SIZE, selection_name); + /* If the default keyword is found, we use the name provided + * in the param file (not the select output!), aka. the argument + * of the function. */ + if (strcmp(output_options->basenames[selection_id], + select_output_default_basename) == 0) { + sprintf(basename, "%s", default_basename); + } else { + sprintf(basename, "%s", output_options->basenames[selection_id]); + } - parser_get_opt_param_string(output_options->select_output, field, subdir_name, - default_subdirname); + /* If the default keyword is found, we use the subdir name provided + * in the param file (not the select output!), aka. the argument + * of the function. */ + if (strcmp(output_options->subdir_names[selection_id], + select_output_default_subdir_name) == 0) { + sprintf(subdir_name, "%s", default_subdirname); + } else { + sprintf(subdir_name, "%s", output_options->subdir_names[selection_id]); + } } diff --git a/src/output_options.h b/src/output_options.h index 9fac755a7fee85db7ccdfa67825ff2e4b6f5f8bf..d4ab0627d92b7b789d7398a0a3717614a4c86654 100644 --- a/src/output_options.h +++ b/src/output_options.h @@ -30,6 +30,8 @@ /*! Default name for the SelectOutput header */ #define select_output_header_default_name "Default" +#define select_output_default_basename "Standard" +#define select_output_default_subdir_name "Standard" /** * @brief Output selection properties, including the parsed files. @@ -44,6 +46,18 @@ struct output_options { * output style is used but not specified. */ int num_fields_to_write[OUTPUT_LIST_MAX_NUM_OF_SELECT_OUTPUT_STYLES + 1] [swift_type_count]; + + /*! Basenames to use for the snapshots of the given selection + * If set to the default, the code will use the name set in the + * snapshot section of the param file. */ + char basenames[OUTPUT_LIST_MAX_NUM_OF_SELECT_OUTPUT_STYLES + 1] + [FILENAME_BUFFER_SIZE]; + + /*! Subdir names to use for the snapshots of the given selection + * If set to the default, the code will use the name set in the + * snapshot section of the param file. */ + char subdir_names[OUTPUT_LIST_MAX_NUM_OF_SELECT_OUTPUT_STYLES + 1] + [FILENAME_BUFFER_SIZE]; }; /* Create and destroy */