Skip to content

Commit 433e744

Browse files
committed
Allow snapshots to be reused as ICs explicitly
1 parent 229bd4b commit 433e744

9 files changed

Lines changed: 132 additions & 32 deletions

File tree

examples/parameter_example.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ Statistics:
226226
InitialConditions:
227227
file_name: SedovBlast/sedov.hdf5 # The file to read
228228
periodic: 1 # Are we running with periodic ICs?
229+
accept_snapshot: 0 # (Optional) Accept SWIFT snapshot field names when reading ICs.
229230
generate_gas_in_ics: 0 # (Optional) Generate gas particles from the DM-only ICs (e.g. from panphasia).
230231
cleanup_h_factors: 0 # (Optional) Clean up the h-factors used in the ICs (e.g. in Gadget files).
231232
cleanup_velocity_factors: 0 # (Optional) Clean up the scale-factors used in the definition of the velocity variable in the ICs (e.g. in Gadget files).

src/io_properties.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,22 @@ INLINE static void safe_strcpy(char *restrict dst, const char *restrict src,
209209
dst[dst_len - 1] = '\0';
210210
}
211211

212+
/**
213+
* @brief Return a snapshot-output alias for legacy/singular IC field names.
214+
*
215+
* SWIFT follows GADGET-style singular names in ICs but writes plural field
216+
* names in snapshots. Accepting these aliases lets a snapshot be reused as an
217+
* IC without an external conversion step.
218+
*/
219+
INLINE static const char *io_get_input_field_alias(const char *name) {
220+
221+
if (strcmp(name, "SmoothingLength") == 0) return "SmoothingLengths";
222+
if (strcmp(name, "InternalEnergy") == 0) return "InternalEnergies";
223+
if (strcmp(name, "Density") == 0) return "Densities";
224+
225+
return NULL;
226+
}
227+
212228
/**
213229
* @brief Constructs an #io_props from its parameters
214230
*

src/parallel_io.c

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -251,16 +251,40 @@ void read_array_parallel(hid_t grp, struct io_props props, size_t N,
251251
long long N_total, int mpi_rank, long long offset,
252252
const struct unit_system *internal_units,
253253
const struct unit_system *ic_units, int cleanup_h,
254-
int cleanup_sqrt_a, double h, double a) {
254+
int cleanup_sqrt_a, double h, double a,
255+
const int accept_snapshot) {
255256

256257
const size_t typeSize = io_sizeof_type(props.type);
257258
const size_t copySize = typeSize * props.dimension;
258259

260+
const char *dataset_name = props.name;
261+
259262
/* Check whether the dataspace exists or not */
260-
const htri_t exist = H5Lexists(grp, props.name, 0);
263+
htri_t exist = H5Lexists(grp, dataset_name, 0);
261264
if (exist < 0) {
262-
error("Error while checking the existence of data set '%s'.", props.name);
263-
} else if (exist == 0) {
265+
error("Error while checking the existence of data set '%s'.", dataset_name);
266+
}
267+
268+
if (exist == 0) {
269+
const char *alias = io_get_input_field_alias(props.name);
270+
if (alias != NULL) {
271+
const htri_t alias_exist = H5Lexists(grp, alias, 0);
272+
if (alias_exist < 0) {
273+
error("Error while checking the existence of data set '%s'.", alias);
274+
} else if (alias_exist > 0 && accept_snapshot) {
275+
dataset_name = alias;
276+
exist = alias_exist;
277+
} else if (alias_exist > 0 && props.importance == COMPULSORY) {
278+
error(
279+
"Compulsory data set '%s' not present in the file. Found snapshot "
280+
"field '%s' instead. Set InitialConditions:accept_snapshot to 1 "
281+
"to accept snapshot field names.",
282+
props.name, alias);
283+
}
284+
}
285+
}
286+
287+
if (exist == 0) {
264288
if (props.importance == COMPULSORY) {
265289
error("Compulsory data set '%s' not present in the file.", props.name);
266290
} else {
@@ -279,8 +303,8 @@ void read_array_parallel(hid_t grp, struct io_props props, size_t N,
279303
}
280304

281305
/* Open data space in file */
282-
const hid_t h_data = H5Dopen2(grp, props.name, H5P_DEFAULT);
283-
if (h_data < 0) error("Error while opening data space '%s'.", props.name);
306+
const hid_t h_data = H5Dopen2(grp, dataset_name, H5P_DEFAULT);
307+
if (h_data < 0) error("Error while opening data space '%s'.", dataset_name);
284308

285309
/* Parallel-HDF5 1.10.2 incorrectly reads data that was compressed */
286310
/* We detect this here and crash with an error message instead of */
@@ -796,7 +820,8 @@ void read_ic_parallel(char *fileName, const struct unit_system *internal_units,
796820
const int cleanup_sqrt_a, const double h, const double a,
797821
const int mpi_rank, const int mpi_size, MPI_Comm comm,
798822
MPI_Info info, const int n_threads, const int dry_run,
799-
const int remap_ids, struct ic_info *ics_metadata) {
823+
const int remap_ids, const int accept_snapshot,
824+
struct ic_info *ics_metadata) {
800825

801826
hid_t h_file = 0, h_grp = 0;
802827
/* GADGET has only cubic boxes (in cosmological mode) */
@@ -1100,7 +1125,8 @@ void read_ic_parallel(char *fileName, const struct unit_system *internal_units,
11001125
/* Read array. */
11011126
read_array_parallel(h_grp, list[i], Nparticles, N_total[ptype],
11021127
mpi_rank, offset[ptype], internal_units, ic_units,
1103-
cleanup_h, cleanup_sqrt_a, h, a);
1128+
cleanup_h, cleanup_sqrt_a, h, a,
1129+
accept_snapshot);
11041130
}
11051131

11061132
/* Close particle group */

src/parallel_io.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ void read_ic_parallel(char *fileName, const struct unit_system *internal_units,
4747
const int cleanup_sqrt_a, const double h, const double a,
4848
const int mpi_rank, const int mpi_size, MPI_Comm comm,
4949
MPI_Info info, const int nr_threads, const int dry_run,
50-
const int remap_ids, struct ic_info *ics_metadata);
50+
const int remap_ids, const int accept_snapshot,
51+
struct ic_info *ics_metadata);
5152

5253
void write_output_parallel(struct engine *e,
5354
const struct unit_system *internal_units,

src/serial_io.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,41 @@ void read_array_serial(hid_t grp, const struct io_props props, size_t N,
8989
long long N_total, long long offset,
9090
const struct unit_system *internal_units,
9191
const struct unit_system *ic_units, int cleanup_h,
92-
int cleanup_sqrt_a, double h, double a) {
92+
int cleanup_sqrt_a, double h, double a,
93+
const int accept_snapshot) {
9394

9495
const size_t typeSize = io_sizeof_type(props.type);
9596
const size_t copySize = typeSize * props.dimension;
9697
const size_t num_elements = N * props.dimension;
9798

99+
const char *dataset_name = props.name;
100+
98101
/* Check whether the dataspace exists or not */
99-
const htri_t exist = H5Lexists(grp, props.name, 0);
102+
htri_t exist = H5Lexists(grp, dataset_name, 0);
100103
if (exist < 0) {
101-
error("Error while checking the existence of data set '%s'.", props.name);
102-
} else if (exist == 0) {
104+
error("Error while checking the existence of data set '%s'.", dataset_name);
105+
}
106+
107+
if (exist == 0) {
108+
const char *alias = io_get_input_field_alias(props.name);
109+
if (alias != NULL) {
110+
const htri_t alias_exist = H5Lexists(grp, alias, 0);
111+
if (alias_exist < 0) {
112+
error("Error while checking the existence of data set '%s'.", alias);
113+
} else if (alias_exist > 0 && accept_snapshot) {
114+
dataset_name = alias;
115+
exist = alias_exist;
116+
} else if (alias_exist > 0 && props.importance == COMPULSORY) {
117+
error(
118+
"Compulsory data set '%s' not present in the file. Found snapshot "
119+
"field '%s' instead. Set InitialConditions:accept_snapshot to 1 "
120+
"to accept snapshot field names.",
121+
props.name, alias);
122+
}
123+
}
124+
}
125+
126+
if (exist == 0) {
103127
if (props.importance == COMPULSORY) {
104128
error("Compulsory data set '%s' not present in the file.", props.name);
105129
} else {
@@ -122,8 +146,8 @@ void read_array_serial(hid_t grp, const struct io_props props, size_t N,
122146
/* fflush(stdout); */
123147

124148
/* Open data space */
125-
const hid_t h_data = H5Dopen(grp, props.name, H5P_DEFAULT);
126-
if (h_data < 0) error("Error while opening data space '%s'.", props.name);
149+
const hid_t h_data = H5Dopen(grp, dataset_name, H5P_DEFAULT);
150+
if (h_data < 0) error("Error while opening data space '%s'.", dataset_name);
127151

128152
/* Allocate temporary buffer */
129153
void *temp = malloc(num_elements * typeSize);
@@ -158,7 +182,7 @@ void read_array_serial(hid_t grp, const struct io_props props, size_t N,
158182
/* Using HDF5 dataspaces would be better */
159183
const hid_t h_err = H5Dread(h_data, io_hdf5_type(props.type), h_memspace,
160184
h_filespace, H5P_DEFAULT, temp);
161-
if (h_err < 0) error("Error while reading data array '%s'.", props.name);
185+
if (h_err < 0) error("Error while reading data array '%s'.", dataset_name);
162186

163187
/* Unit conversion if necessary */
164188
const double factor =
@@ -569,7 +593,8 @@ void read_ic_serial(char *fileName, const struct unit_system *internal_units,
569593
const int cleanup_sqrt_a, double h, double a,
570594
const int mpi_rank, int mpi_size, MPI_Comm comm,
571595
MPI_Info info, const int n_threads, const int dry_run,
572-
const int remap_ids, struct ic_info *ics_metadata) {
596+
const int remap_ids, const int accept_snapshot,
597+
struct ic_info *ics_metadata) {
573598

574599
hid_t h_file = 0, h_grp = 0;
575600
/* GADGET has only cubic boxes (in cosmological mode) */
@@ -905,7 +930,8 @@ void read_ic_serial(char *fileName, const struct unit_system *internal_units,
905930
/* Read array. */
906931
read_array_serial(h_grp, list[i], Nparticles, N_total[ptype],
907932
offset[ptype], internal_units, ic_units,
908-
cleanup_h, cleanup_sqrt_a, h, a);
933+
cleanup_h, cleanup_sqrt_a, h, a,
934+
accept_snapshot);
909935
}
910936

911937
/* Close particle group */

src/serial_io.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ void read_ic_serial(char *fileName, const struct unit_system *internal_units,
4949
const int cleanup_sqrt_a, const double h, const double a,
5050
const int mpi_rank, int mpi_size, MPI_Comm comm,
5151
MPI_Info info, const int n_threads, const int dry_run,
52-
const int remap_ids, struct ic_info *ics_metadata);
52+
const int remap_ids, const int accept_snapshot,
53+
struct ic_info *ics_metadata);
5354

5455
void write_output_serial(struct engine *e,
5556
const struct unit_system *internal_units,

src/single_io.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,41 @@ static const int io_max_size_output_list = 100;
8686
void read_array_single(hid_t h_grp, const struct io_props props, size_t N,
8787
const struct unit_system *internal_units,
8888
const struct unit_system *ic_units, int cleanup_h,
89-
int cleanup_sqrt_a, double h, double a) {
89+
int cleanup_sqrt_a, double h, double a,
90+
const int accept_snapshot) {
9091

9192
const size_t typeSize = io_sizeof_type(props.type);
9293
const size_t copySize = typeSize * props.dimension;
9394
const size_t num_elements = N * props.dimension;
9495

96+
const char *dataset_name = props.name;
97+
9598
/* Check whether the dataspace exists or not */
96-
const htri_t exist = H5Lexists(h_grp, props.name, 0);
99+
htri_t exist = H5Lexists(h_grp, dataset_name, 0);
97100
if (exist < 0) {
98-
error("Error while checking the existence of data set '%s'.", props.name);
99-
} else if (exist == 0) {
101+
error("Error while checking the existence of data set '%s'.", dataset_name);
102+
}
103+
104+
if (exist == 0) {
105+
const char *alias = io_get_input_field_alias(props.name);
106+
if (alias != NULL) {
107+
const htri_t alias_exist = H5Lexists(h_grp, alias, 0);
108+
if (alias_exist < 0) {
109+
error("Error while checking the existence of data set '%s'.", alias);
110+
} else if (alias_exist > 0 && accept_snapshot) {
111+
dataset_name = alias;
112+
exist = alias_exist;
113+
} else if (alias_exist > 0 && props.importance == COMPULSORY) {
114+
error(
115+
"Compulsory data set '%s' not present in the file. Found snapshot "
116+
"field '%s' instead. Set InitialConditions:accept_snapshot to 1 "
117+
"to accept snapshot field names.",
118+
props.name, alias);
119+
}
120+
}
121+
}
122+
123+
if (exist == 0) {
100124
if (props.importance == COMPULSORY) {
101125
error("Compulsory data set '%s' not present in the file.", props.name);
102126
} else {
@@ -119,8 +143,8 @@ void read_array_single(hid_t h_grp, const struct io_props props, size_t N,
119143
/* props.name); */
120144

121145
/* Open data space */
122-
const hid_t h_data = H5Dopen(h_grp, props.name, H5P_DEFAULT);
123-
if (h_data < 0) error("Error while opening data space '%s'.", props.name);
146+
const hid_t h_data = H5Dopen(h_grp, dataset_name, H5P_DEFAULT);
147+
if (h_data < 0) error("Error while opening data space '%s'.", dataset_name);
124148

125149
/* Allocate temporary buffer */
126150
void *temp = malloc(num_elements * typeSize);
@@ -131,7 +155,7 @@ void read_array_single(hid_t h_grp, const struct io_props props, size_t N,
131155
/* Using HDF5 dataspaces would be better */
132156
const hid_t h_err = H5Dread(h_data, io_hdf5_type(props.type), H5S_ALL,
133157
H5S_ALL, H5P_DEFAULT, temp);
134-
if (h_err < 0) error("Error while reading data array '%s'.", props.name);
158+
if (h_err < 0) error("Error while reading data array '%s'.", dataset_name);
135159

136160
/* Unit conversion if necessary */
137161
const double unit_factor =
@@ -466,7 +490,7 @@ void read_ic_single(
466490
const int with_stars, const int with_black_holes, const int with_cosmology,
467491
const int cleanup_h, const int cleanup_sqrt_a, const double h,
468492
const double a, const int n_threads, const int dry_run, const int remap_ids,
469-
struct ic_info *ics_metadata) {
493+
const int accept_snapshot, struct ic_info *ics_metadata) {
470494

471495
hid_t h_file = 0, h_grp = 0;
472496
/* GADGET has only cubic boxes (in cosmological mode) */
@@ -754,7 +778,7 @@ void read_ic_single(
754778

755779
/* Read array. */
756780
read_array_single(h_grp, list[i], Nparticles, internal_units, ic_units,
757-
cleanup_h, cleanup_sqrt_a, h, a);
781+
cleanup_h, cleanup_sqrt_a, h, a, accept_snapshot);
758782
}
759783

760784
/* Close particle group */

src/single_io.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ void read_ic_single(
4141
const int with_stars, const int with_black_holes, const int with_cosmology,
4242
const int cleanup_h, const int cleanup_sqrt_a, const double h,
4343
const double a, const int nr_threads, const int dry_run,
44-
const int remap_ids, struct ic_info *ics_metadata);
44+
const int remap_ids, const int accept_snapshot,
45+
struct ic_info *ics_metadata);
4546

4647
void write_output_single(struct engine *e,
4748
const struct unit_system *internal_units,

swift.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,8 @@ int main(int argc, char *argv[]) {
10951095
params, "InitialConditions:generate_gas_in_ics", 0);
10961096
const int remap_ids =
10971097
parser_get_opt_param_int(params, "InitialConditions:remap_ids", 0);
1098+
const int accept_snapshot =
1099+
parser_get_opt_param_int(params, "InitialConditions:accept_snapshot", 0);
10981100

10991101
/* Initialise the cosmology */
11001102
if (with_cosmology)
@@ -1281,23 +1283,25 @@ int main(int argc, char *argv[]) {
12811283
with_gravity, with_sinks, with_stars, with_black_holes,
12821284
with_cosmology, cleanup_h, cleanup_sqrt_a, cosmo.h,
12831285
cosmo.a, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL,
1284-
nr_threads, dry_run, remap_ids, &ics_metadata);
1286+
nr_threads, dry_run, remap_ids, accept_snapshot,
1287+
&ics_metadata);
12851288
#else
12861289
read_ic_serial(ICfileName, &us, dim, &parts, &gparts, &sinks, &sparts,
12871290
&bparts, &Ngas, &Ngpart, &Ngpart_background, &Nnupart,
12881291
&Nsink, &Nspart, &Nbpart, &flag_entropy_ICs, with_hydro,
12891292
with_gravity, with_sinks, with_stars, with_black_holes,
12901293
with_cosmology, cleanup_h, cleanup_sqrt_a, cosmo.h, cosmo.a,
12911294
myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL, nr_threads,
1292-
dry_run, remap_ids, &ics_metadata);
1295+
dry_run, remap_ids, accept_snapshot, &ics_metadata);
12931296
#endif
12941297
#else
12951298
read_ic_single(ICfileName, &us, dim, &parts, &gparts, &sinks, &sparts,
12961299
&bparts, &Ngas, &Ngpart, &Ngpart_background, &Nnupart,
12971300
&Nsink, &Nspart, &Nbpart, &flag_entropy_ICs, with_hydro,
12981301
with_gravity, with_sinks, with_stars, with_black_holes,
12991302
with_cosmology, cleanup_h, cleanup_sqrt_a, cosmo.h, cosmo.a,
1300-
nr_threads, dry_run, remap_ids, &ics_metadata);
1303+
nr_threads, dry_run, remap_ids, accept_snapshot,
1304+
&ics_metadata);
13011305
#endif
13021306
#endif
13031307

0 commit comments

Comments
 (0)