From ef62b5214f7b23c8466ac0cdb1f6a3bc740a8a3b Mon Sep 17 00:00:00 2001
From: Matthieu Schaller <schaller@strw.leidenuniv.nl>
Date: Thu, 16 Apr 2020 15:18:22 +0200
Subject: [PATCH] Move the writing of the snapshot meta-data to a separate
 unique function for all schemes

---
 src/common_io.c      | 132 +++++++++++++++++++++++++++++++++++++++++++
 src/common_io.h      |   4 ++
 src/distributed_io.c | 119 +-------------------------------------
 src/parallel_io.c    | 119 +-------------------------------------
 src/serial_io.c      | 119 +-------------------------------------
 src/single_io.c      | 119 +-------------------------------------
 6 files changed, 144 insertions(+), 468 deletions(-)

diff --git a/src/common_io.c b/src/common_io.c
index 6f99851d84..d7c292f91e 100644
--- a/src/common_io.c
+++ b/src/common_io.c
@@ -33,6 +33,7 @@
 #include "const.h"
 #include "cooling_io.h"
 #include "error.h"
+#include "feedback.h"
 #include "fof_io.h"
 #include "gravity_io.h"
 #include "hydro.h"
@@ -482,6 +483,137 @@ void io_write_attribute_s(hid_t grp, const char* name, const char* str) {
   io_writeStringAttribute(grp, name, str, strlen(str));
 }
 
+/**
+ * @brief Writes the meta-dat of the run to an open hdf5 snapshot file.
+ *
+ * @param h_file The opened hdf5 file.
+ * @param e The #engine containing the meta-data.
+ * @param internal_units The system of units used internally.
+ * @param snapshot_units The system of units used in snapshots.
+ */
+void io_write_meta_data(hid_t h_file, const struct engine* e,
+                        const struct unit_system* internal_units,
+                        const struct unit_system* snapshot_units) {
+
+  hid_t h_grp;
+
+  /* Print the code version */
+  io_write_code_description(h_file);
+
+  /* Print the run's policy */
+  io_write_engine_policy(h_file, e);
+
+  /* Print the physical constants */
+  phys_const_print_snapshot(h_file, e->physical_constants);
+
+  /* Print the SPH parameters */
+  if (e->policy & engine_policy_hydro) {
+    h_grp = H5Gcreate(h_file, "/HydroScheme", H5P_DEFAULT, H5P_DEFAULT,
+                      H5P_DEFAULT);
+    if (h_grp < 0) error("Error while creating SPH group");
+    hydro_props_print_snapshot(h_grp, e->hydro_properties);
+    hydro_write_flavour(h_grp);
+    H5Gclose(h_grp);
+  }
+
+  /* Print the subgrid parameters */
+  h_grp = H5Gcreate(h_file, "/SubgridScheme", H5P_DEFAULT, H5P_DEFAULT,
+                    H5P_DEFAULT);
+  if (h_grp < 0) error("Error while creating subgrid group");
+  hid_t h_grp_columns =
+      H5Gcreate(h_grp, "NamedColumns", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  if (h_grp_columns < 0) error("Error while creating named columns group");
+  entropy_floor_write_flavour(h_grp);
+  cooling_write_flavour(h_grp, h_grp_columns, e->cooling_func);
+  chemistry_write_flavour(h_grp, h_grp_columns, e);
+  tracers_write_flavour(h_grp);
+  feedback_write_flavour(e->feedback_props, h_grp);
+  H5Gclose(h_grp_columns);
+  H5Gclose(h_grp);
+
+  /* Print the gravity parameters */
+  if (e->policy & engine_policy_self_gravity) {
+    h_grp = H5Gcreate(h_file, "/GravityScheme", H5P_DEFAULT, H5P_DEFAULT,
+                      H5P_DEFAULT);
+    if (h_grp < 0) error("Error while creating gravity group");
+    gravity_props_print_snapshot(h_grp, e->gravity_properties);
+    H5Gclose(h_grp);
+  }
+
+  /* Print the stellar parameters */
+  if (e->policy & engine_policy_stars) {
+    h_grp = H5Gcreate(h_file, "/StarsScheme", H5P_DEFAULT, H5P_DEFAULT,
+                      H5P_DEFAULT);
+    if (h_grp < 0) error("Error while creating stars group");
+    stars_props_print_snapshot(h_grp, e->stars_properties);
+    H5Gclose(h_grp);
+  }
+
+  /* Print the cosmological model  */
+  h_grp =
+      H5Gcreate(h_file, "/Cosmology", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  if (h_grp < 0) error("Error while creating cosmology group");
+  if (e->policy & engine_policy_cosmology)
+    io_write_attribute_i(h_grp, "Cosmological run", 1);
+  else
+    io_write_attribute_i(h_grp, "Cosmological run", 0);
+  cosmology_write_model(h_grp, e->cosmology);
+  H5Gclose(h_grp);
+
+  /* Print the runtime parameters */
+  h_grp =
+      H5Gcreate(h_file, "/Parameters", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  if (h_grp < 0) error("Error while creating parameters group");
+  parser_write_params_to_hdf5(e->parameter_file, h_grp, /*write_used=*/1);
+  H5Gclose(h_grp);
+
+  /* Print the runtime unused parameters */
+  h_grp = H5Gcreate(h_file, "/UnusedParameters", H5P_DEFAULT, H5P_DEFAULT,
+                    H5P_DEFAULT);
+  if (h_grp < 0) error("Error while creating parameters group");
+  parser_write_params_to_hdf5(e->parameter_file, h_grp, /*write_used=*/0);
+  H5Gclose(h_grp);
+
+  /* Print the system of Units used in the spashot */
+  io_write_unit_system(h_file, snapshot_units, "Units");
+
+  /* Print the system of Units used internally */
+  io_write_unit_system(h_file, internal_units, "InternalCodeUnits");
+
+  /* Tell the user if a conversion will be needed */
+  if (e->verbose) {
+    if (units_are_equal(snapshot_units, internal_units)) {
+
+      message("Snapshot and internal units match. No conversion needed.");
+
+    } else {
+
+      message("Conversion needed from:");
+      message("(Snapshot) Unit system: U_M =      %e g.",
+              snapshot_units->UnitMass_in_cgs);
+      message("(Snapshot) Unit system: U_L =      %e cm.",
+              snapshot_units->UnitLength_in_cgs);
+      message("(Snapshot) Unit system: U_t =      %e s.",
+              snapshot_units->UnitTime_in_cgs);
+      message("(Snapshot) Unit system: U_I =      %e A.",
+              snapshot_units->UnitCurrent_in_cgs);
+      message("(Snapshot) Unit system: U_T =      %e K.",
+              snapshot_units->UnitTemperature_in_cgs);
+      message("to:");
+      message("(internal) Unit system: U_M = %e g.",
+              internal_units->UnitMass_in_cgs);
+      message("(internal) Unit system: U_L = %e cm.",
+              internal_units->UnitLength_in_cgs);
+      message("(internal) Unit system: U_t = %e s.",
+              internal_units->UnitTime_in_cgs);
+      message("(internal) Unit system: U_I = %e A.",
+              internal_units->UnitCurrent_in_cgs);
+      message("(internal) Unit system: U_T = %e K.",
+              internal_units->UnitTemperature_in_cgs);
+    }
+  }
+}
+
 /**
  * @brief Reads the Unit System from an IC file.
  *
diff --git a/src/common_io.h b/src/common_io.h
index 4da7e52a92..0fe2427d53 100644
--- a/src/common_io.h
+++ b/src/common_io.h
@@ -90,6 +90,10 @@ void io_write_attribute_i(hid_t grp, const char* name, int data);
 void io_write_attribute_l(hid_t grp, const char* name, long data);
 void io_write_attribute_s(hid_t grp, const char* name, const char* str);
 
+void io_write_meta_data(hid_t h_file, const struct engine* e,
+                        const struct unit_system* internal_units,
+                        const struct unit_system* snapshot_units);
+
 void io_write_code_description(hid_t h_file);
 void io_write_engine_policy(hid_t h_file, const struct engine* e);
 
diff --git a/src/distributed_io.c b/src/distributed_io.c
index 3b1c888590..4ef0570193 100644
--- a/src/distributed_io.c
+++ b/src/distributed_io.c
@@ -42,14 +42,12 @@
 #include "dimension.h"
 #include "engine.h"
 #include "error.h"
-#include "feedback.h"
 #include "fof_io.h"
 #include "gravity_io.h"
 #include "gravity_properties.h"
 #include "hydro_io.h"
 #include "hydro_properties.h"
 #include "io_properties.h"
-#include "kernel_hydro.h"
 #include "memuse.h"
 #include "part.h"
 #include "part_type.h"
@@ -368,88 +366,8 @@ void write_output_distributed(struct engine* e, const char* baseName,
   /* Close header */
   H5Gclose(h_grp);
 
-  /* Print the code version */
-  io_write_code_description(h_file);
-
-  /* Print the run's policy */
-  io_write_engine_policy(h_file, e);
-
-  /* Print the physical constants */
-  phys_const_print_snapshot(h_file, e->physical_constants);
-
-  /* Print the SPH parameters */
-  if (e->policy & engine_policy_hydro) {
-    h_grp = H5Gcreate(h_file, "/HydroScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating SPH group");
-    hydro_props_print_snapshot(h_grp, e->hydro_properties);
-    hydro_write_flavour(h_grp);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the subgrid parameters */
-  h_grp = H5Gcreate(h_file, "/SubgridScheme", H5P_DEFAULT, H5P_DEFAULT,
-                    H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating subgrid group");
-  hid_t h_grp_columns =
-      H5Gcreate(h_grp, "NamedColumns", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp_columns < 0) error("Error while creating named columns group");
-  entropy_floor_write_flavour(h_grp);
-  cooling_write_flavour(h_grp, h_grp_columns, e->cooling_func);
-  chemistry_write_flavour(h_grp, h_grp_columns, e);
-  tracers_write_flavour(h_grp);
-  feedback_write_flavour(e->feedback_props, h_grp);
-  H5Gclose(h_grp_columns);
-  H5Gclose(h_grp);
-
-  /* Print the gravity parameters */
-  if (e->policy & engine_policy_self_gravity) {
-    h_grp = H5Gcreate(h_file, "/GravityScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating gravity group");
-    gravity_props_print_snapshot(h_grp, e->gravity_properties);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the stellar parameters */
-  if (e->policy & engine_policy_stars) {
-    h_grp = H5Gcreate(h_file, "/StarsScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating stars group");
-    stars_props_print_snapshot(h_grp, e->stars_properties);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the cosmological model  */
-  h_grp =
-      H5Gcreate(h_file, "/Cosmology", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating cosmology group");
-  if (e->policy & engine_policy_cosmology)
-    io_write_attribute_i(h_grp, "Cosmological run", 1);
-  else
-    io_write_attribute_i(h_grp, "Cosmological run", 0);
-  cosmology_write_model(h_grp, e->cosmology);
-  H5Gclose(h_grp);
-
-  /* Print the runtime parameters */
-  h_grp =
-      H5Gcreate(h_file, "/Parameters", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating parameters group");
-  parser_write_params_to_hdf5(e->parameter_file, h_grp, 1);
-  H5Gclose(h_grp);
-
-  /* Print the runtime unused parameters */
-  h_grp = H5Gcreate(h_file, "/UnusedParameters", H5P_DEFAULT, H5P_DEFAULT,
-                    H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating parameters group");
-  parser_write_params_to_hdf5(e->parameter_file, h_grp, 0);
-  H5Gclose(h_grp);
-
-  /* Print the system of Units used in the spashot */
-  io_write_unit_system(h_file, snapshot_units, "Units");
-
-  /* Print the system of Units used internally */
-  io_write_unit_system(h_file, internal_units, "InternalCodeUnits");
+  /* Write all the meta-data */
+  io_write_meta_data(h_file, e, internal_units, snapshot_units);
 
   /* Now write the top-level cell structure
    * We use a global offset of 0 here. This means that the cells will write
@@ -466,39 +384,6 @@ void write_output_distributed(struct engine* e, const char* baseName,
                         internal_units, snapshot_units);
   H5Gclose(h_grp);
 
-  /* Tell the user if a conversion will be needed */
-  if (e->verbose) {
-    if (units_are_equal(snapshot_units, internal_units)) {
-
-      message("Snapshot and internal units match. No conversion needed.");
-
-    } else {
-
-      message("Conversion needed from:");
-      message("(Snapshot) Unit system: U_M =      %e g.",
-              snapshot_units->UnitMass_in_cgs);
-      message("(Snapshot) Unit system: U_L =      %e cm.",
-              snapshot_units->UnitLength_in_cgs);
-      message("(Snapshot) Unit system: U_t =      %e s.",
-              snapshot_units->UnitTime_in_cgs);
-      message("(Snapshot) Unit system: U_I =      %e A.",
-              snapshot_units->UnitCurrent_in_cgs);
-      message("(Snapshot) Unit system: U_T =      %e K.",
-              snapshot_units->UnitTemperature_in_cgs);
-      message("to:");
-      message("(internal) Unit system: U_M = %e g.",
-              internal_units->UnitMass_in_cgs);
-      message("(internal) Unit system: U_L = %e cm.",
-              internal_units->UnitLength_in_cgs);
-      message("(internal) Unit system: U_t = %e s.",
-              internal_units->UnitTime_in_cgs);
-      message("(internal) Unit system: U_I = %e A.",
-              internal_units->UnitCurrent_in_cgs);
-      message("(internal) Unit system: U_T = %e K.",
-              internal_units->UnitTemperature_in_cgs);
-    }
-  }
-
   /* Loop over all particle types */
   for (int ptype = 0; ptype < swift_type_count; ptype++) {
 
diff --git a/src/parallel_io.c b/src/parallel_io.c
index a7b2855180..686b6ab600 100644
--- a/src/parallel_io.c
+++ b/src/parallel_io.c
@@ -44,14 +44,12 @@
 #include "dimension.h"
 #include "engine.h"
 #include "error.h"
-#include "feedback.h"
 #include "fof_io.h"
 #include "gravity_io.h"
 #include "gravity_properties.h"
 #include "hydro_io.h"
 #include "hydro_properties.h"
 #include "io_properties.h"
-#include "kernel_hydro.h"
 #include "memuse.h"
 #include "part.h"
 #include "part_type.h"
@@ -1158,88 +1156,8 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6],
   /* Close header */
   H5Gclose(h_grp);
 
-  /* Print the code version */
-  io_write_code_description(h_file);
-
-  /* Print the run's policy */
-  io_write_engine_policy(h_file, e);
-
-  /* Print the physical constants */
-  phys_const_print_snapshot(h_file, e->physical_constants);
-
-  /* Print the SPH parameters */
-  if (e->policy & engine_policy_hydro) {
-    h_grp = H5Gcreate(h_file, "/HydroScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating SPH group");
-    hydro_props_print_snapshot(h_grp, e->hydro_properties);
-    hydro_write_flavour(h_grp);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the subgrid parameters */
-  h_grp = H5Gcreate(h_file, "/SubgridScheme", H5P_DEFAULT, H5P_DEFAULT,
-                    H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating subgrid group");
-  hid_t h_grp_columns =
-      H5Gcreate(h_grp, "NamedColumns", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp_columns < 0) error("Error while creating named columns group");
-  entropy_floor_write_flavour(h_grp);
-  cooling_write_flavour(h_grp, h_grp_columns, e->cooling_func);
-  chemistry_write_flavour(h_grp, h_grp_columns, e);
-  tracers_write_flavour(h_grp);
-  feedback_write_flavour(e->feedback_props, h_grp);
-  H5Gclose(h_grp_columns);
-  H5Gclose(h_grp);
-
-  /* Print the gravity parameters */
-  if (e->policy & engine_policy_self_gravity) {
-    h_grp = H5Gcreate(h_file, "/GravityScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating gravity group");
-    gravity_props_print_snapshot(h_grp, e->gravity_properties);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the stellar parameters */
-  if (e->policy & engine_policy_stars) {
-    h_grp = H5Gcreate(h_file, "/StarsScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating stars group");
-    stars_props_print_snapshot(h_grp, e->stars_properties);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the cosmological parameters */
-  h_grp =
-      H5Gcreate(h_file, "/Cosmology", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating cosmology group");
-  if (e->policy & engine_policy_cosmology)
-    io_write_attribute_i(h_grp, "Cosmological run", 1);
-  else
-    io_write_attribute_i(h_grp, "Cosmological run", 0);
-  cosmology_write_model(h_grp, e->cosmology);
-  H5Gclose(h_grp);
-
-  /* Print the runtime parameters */
-  h_grp =
-      H5Gcreate(h_file, "/Parameters", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating parameters group");
-  parser_write_params_to_hdf5(e->parameter_file, h_grp, 1);
-  H5Gclose(h_grp);
-
-  /* Print the runtime unused parameters */
-  h_grp = H5Gcreate(h_file, "/UnusedParameters", H5P_DEFAULT, H5P_DEFAULT,
-                    H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating parameters group");
-  parser_write_params_to_hdf5(e->parameter_file, h_grp, 0);
-  H5Gclose(h_grp);
-
-  /* Print the system of Units used in the spashot */
-  io_write_unit_system(h_file, snapshot_units, "Units");
-
-  /* Print the system of Units used internally */
-  io_write_unit_system(h_file, internal_units, "InternalCodeUnits");
+  /* Write all the meta-data */
+  io_write_meta_data(h_file, e, internal_units, snapshot_units);
 
   /* Loop over all particle types */
   for (int ptype = 0; ptype < swift_type_count; ptype++) {
@@ -1584,39 +1502,6 @@ void write_output_parallel(struct engine* e, const char* baseName,
   tic = getticks();
 #endif
 
-  /* Tell the user if a conversion will be needed */
-  if (e->verbose && mpi_rank == 0) {
-    if (units_are_equal(snapshot_units, internal_units)) {
-
-      message("Snapshot and internal units match. No conversion needed.");
-
-    } else {
-
-      message("Conversion needed from:");
-      message("(Snapshot) Unit system: U_M =      %e g.",
-              snapshot_units->UnitMass_in_cgs);
-      message("(Snapshot) Unit system: U_L =      %e cm.",
-              snapshot_units->UnitLength_in_cgs);
-      message("(Snapshot) Unit system: U_t =      %e s.",
-              snapshot_units->UnitTime_in_cgs);
-      message("(Snapshot) Unit system: U_I =      %e A.",
-              snapshot_units->UnitCurrent_in_cgs);
-      message("(Snapshot) Unit system: U_T =      %e K.",
-              snapshot_units->UnitTemperature_in_cgs);
-      message("to:");
-      message("(internal) Unit system: U_M = %e g.",
-              internal_units->UnitMass_in_cgs);
-      message("(internal) Unit system: U_L = %e cm.",
-              internal_units->UnitLength_in_cgs);
-      message("(internal) Unit system: U_t = %e s.",
-              internal_units->UnitTime_in_cgs);
-      message("(internal) Unit system: U_I = %e A.",
-              internal_units->UnitCurrent_in_cgs);
-      message("(internal) Unit system: U_T = %e K.",
-              internal_units->UnitTemperature_in_cgs);
-    }
-  }
-
   /* Loop over all particle types */
   for (int ptype = 0; ptype < swift_type_count; ptype++) {
 
diff --git a/src/serial_io.c b/src/serial_io.c
index fea7bcf671..74e9362575 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -44,14 +44,12 @@
 #include "dimension.h"
 #include "engine.h"
 #include "error.h"
-#include "feedback.h"
 #include "fof_io.h"
 #include "gravity_io.h"
 #include "gravity_properties.h"
 #include "hydro_io.h"
 #include "hydro_properties.h"
 #include "io_properties.h"
-#include "kernel_hydro.h"
 #include "memuse.h"
 #include "part.h"
 #include "part_type.h"
@@ -1018,121 +1016,8 @@ void write_output_serial(struct engine* e, const char* baseName,
     /* Close header */
     H5Gclose(h_grp);
 
-    /* Print the code version */
-    io_write_code_description(h_file);
-
-    /* Print the run's policy */
-    io_write_engine_policy(h_file, e);
-
-    /* Print the physical constants */
-    phys_const_print_snapshot(h_file, e->physical_constants);
-
-    /* Print the SPH parameters */
-    if (e->policy & engine_policy_hydro) {
-      h_grp = H5Gcreate(h_file, "/HydroScheme", H5P_DEFAULT, H5P_DEFAULT,
-                        H5P_DEFAULT);
-      if (h_grp < 0) error("Error while creating SPH group");
-      hydro_props_print_snapshot(h_grp, e->hydro_properties);
-      hydro_write_flavour(h_grp);
-      H5Gclose(h_grp);
-    }
-
-    /* Print the subgrid parameters */
-    h_grp = H5Gcreate(h_file, "/SubgridScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating subgrid group");
-    hid_t h_grp_columns =
-        H5Gcreate(h_grp, "NamedColumns", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-    if (h_grp_columns < 0) error("Error while creating named columns group");
-    entropy_floor_write_flavour(h_grp);
-    cooling_write_flavour(h_grp, h_grp_columns, e->cooling_func);
-    chemistry_write_flavour(h_grp, h_grp_columns, e);
-    tracers_write_flavour(h_grp);
-    feedback_write_flavour(e->feedback_props, h_grp);
-    H5Gclose(h_grp_columns);
-    H5Gclose(h_grp);
-
-    /* Print the gravity parameters */
-    if (e->policy & engine_policy_self_gravity) {
-      h_grp = H5Gcreate(h_file, "/GravityScheme", H5P_DEFAULT, H5P_DEFAULT,
-                        H5P_DEFAULT);
-      if (h_grp < 0) error("Error while creating gravity group");
-      gravity_props_print_snapshot(h_grp, e->gravity_properties);
-      H5Gclose(h_grp);
-    }
-
-    /* Print the stellar parameters */
-    if (e->policy & engine_policy_stars) {
-      h_grp = H5Gcreate(h_file, "/StarsScheme", H5P_DEFAULT, H5P_DEFAULT,
-                        H5P_DEFAULT);
-      if (h_grp < 0) error("Error while creating stars group");
-      stars_props_print_snapshot(h_grp, e->stars_properties);
-      H5Gclose(h_grp);
-    }
-
-    /* Print the cosmological model */
-    h_grp =
-        H5Gcreate(h_file, "/Cosmology", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating cosmology group");
-    if (e->policy & engine_policy_cosmology)
-      io_write_attribute_i(h_grp, "Cosmological run", 1);
-    else
-      io_write_attribute_i(h_grp, "Cosmological run", 0);
-    cosmology_write_model(h_grp, e->cosmology);
-    H5Gclose(h_grp);
-
-    /* Print the runtime parameters */
-    h_grp =
-        H5Gcreate(h_file, "/Parameters", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating parameters group");
-    parser_write_params_to_hdf5(e->parameter_file, h_grp, 1);
-    H5Gclose(h_grp);
-
-    /* Print the runtime unused parameters */
-    h_grp = H5Gcreate(h_file, "/UnusedParameters", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating parameters group");
-    parser_write_params_to_hdf5(e->parameter_file, h_grp, 0);
-    H5Gclose(h_grp);
-
-    /* Print the system of Units used in the spashot */
-    io_write_unit_system(h_file, snapshot_units, "Units");
-
-    /* Print the system of Units used internally */
-    io_write_unit_system(h_file, internal_units, "InternalCodeUnits");
-
-    /* Tell the user if a conversion will be needed */
-    if (e->verbose) {
-      if (units_are_equal(snapshot_units, internal_units)) {
-
-        message("Snapshot and internal units match. No conversion needed.");
-
-      } else {
-
-        message("Conversion needed from:");
-        message("(Snapshot) Unit system: U_M =      %e g.",
-                snapshot_units->UnitMass_in_cgs);
-        message("(Snapshot) Unit system: U_L =      %e cm.",
-                snapshot_units->UnitLength_in_cgs);
-        message("(Snapshot) Unit system: U_t =      %e s.",
-                snapshot_units->UnitTime_in_cgs);
-        message("(Snapshot) Unit system: U_I =      %e A.",
-                snapshot_units->UnitCurrent_in_cgs);
-        message("(Snapshot) Unit system: U_T =      %e K.",
-                snapshot_units->UnitTemperature_in_cgs);
-        message("to:");
-        message("(internal) Unit system: U_M = %e g.",
-                internal_units->UnitMass_in_cgs);
-        message("(internal) Unit system: U_L = %e cm.",
-                internal_units->UnitLength_in_cgs);
-        message("(internal) Unit system: U_t = %e s.",
-                internal_units->UnitTime_in_cgs);
-        message("(internal) Unit system: U_I = %e A.",
-                internal_units->UnitCurrent_in_cgs);
-        message("(internal) Unit system: U_T = %e K.",
-                internal_units->UnitTemperature_in_cgs);
-      }
-    }
+    /* Write all the meta-data */
+    io_write_meta_data(h_file, e, internal_units, snapshot_units);
 
     /* Loop over all particle types */
     for (int ptype = 0; ptype < swift_type_count; ptype++) {
diff --git a/src/single_io.c b/src/single_io.c
index 76612b5239..bb4a548222 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -43,14 +43,12 @@
 #include "dimension.h"
 #include "engine.h"
 #include "error.h"
-#include "feedback.h"
 #include "fof_io.h"
 #include "gravity_io.h"
 #include "gravity_properties.h"
 #include "hydro_io.h"
 #include "hydro_properties.h"
 #include "io_properties.h"
-#include "kernel_hydro.h"
 #include "memuse.h"
 #include "part.h"
 #include "part_type.h"
@@ -862,88 +860,8 @@ void write_output_single(struct engine* e, const char* baseName,
   /* Close header */
   H5Gclose(h_grp);
 
-  /* Print the code version */
-  io_write_code_description(h_file);
-
-  /* Print the run's policy */
-  io_write_engine_policy(h_file, e);
-
-  /* Print the physical constants */
-  phys_const_print_snapshot(h_file, e->physical_constants);
-
-  /* Print the SPH parameters */
-  if (e->policy & engine_policy_hydro) {
-    h_grp = H5Gcreate(h_file, "/HydroScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating SPH group");
-    hydro_props_print_snapshot(h_grp, e->hydro_properties);
-    hydro_write_flavour(h_grp);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the subgrid parameters */
-  h_grp = H5Gcreate(h_file, "/SubgridScheme", H5P_DEFAULT, H5P_DEFAULT,
-                    H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating subgrid group");
-  hid_t h_grp_columns =
-      H5Gcreate(h_grp, "NamedColumns", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp_columns < 0) error("Error while creating named columns group");
-  entropy_floor_write_flavour(h_grp);
-  cooling_write_flavour(h_grp, h_grp_columns, e->cooling_func);
-  chemistry_write_flavour(h_grp, h_grp_columns, e);
-  tracers_write_flavour(h_grp);
-  feedback_write_flavour(e->feedback_props, h_grp);
-  H5Gclose(h_grp_columns);
-  H5Gclose(h_grp);
-
-  /* Print the gravity parameters */
-  if (e->policy & engine_policy_self_gravity) {
-    h_grp = H5Gcreate(h_file, "/GravityScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating gravity group");
-    gravity_props_print_snapshot(h_grp, e->gravity_properties);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the stellar parameters */
-  if (e->policy & engine_policy_stars) {
-    h_grp = H5Gcreate(h_file, "/StarsScheme", H5P_DEFAULT, H5P_DEFAULT,
-                      H5P_DEFAULT);
-    if (h_grp < 0) error("Error while creating stars group");
-    stars_props_print_snapshot(h_grp, e->stars_properties);
-    H5Gclose(h_grp);
-  }
-
-  /* Print the cosmological model  */
-  h_grp =
-      H5Gcreate(h_file, "/Cosmology", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating cosmology group");
-  if (e->policy & engine_policy_cosmology)
-    io_write_attribute_i(h_grp, "Cosmological run", 1);
-  else
-    io_write_attribute_i(h_grp, "Cosmological run", 0);
-  cosmology_write_model(h_grp, e->cosmology);
-  H5Gclose(h_grp);
-
-  /* Print the runtime parameters */
-  h_grp =
-      H5Gcreate(h_file, "/Parameters", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating parameters group");
-  parser_write_params_to_hdf5(e->parameter_file, h_grp, 1);
-  H5Gclose(h_grp);
-
-  /* Print the runtime unused parameters */
-  h_grp = H5Gcreate(h_file, "/UnusedParameters", H5P_DEFAULT, H5P_DEFAULT,
-                    H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating parameters group");
-  parser_write_params_to_hdf5(e->parameter_file, h_grp, 0);
-  H5Gclose(h_grp);
-
-  /* Print the system of Units used in the spashot */
-  io_write_unit_system(h_file, snapshot_units, "Units");
-
-  /* Print the system of Units used internally */
-  io_write_unit_system(h_file, internal_units, "InternalCodeUnits");
+  /* Write all the meta-data */
+  io_write_meta_data(h_file, e, internal_units, snapshot_units);
 
   /* Now write the top-level cell structure */
   long long global_offsets[swift_type_count] = {0};
@@ -957,39 +875,6 @@ void write_output_single(struct engine* e, const char* baseName,
                         internal_units, snapshot_units);
   H5Gclose(h_grp);
 
-  /* Tell the user if a conversion will be needed */
-  if (e->verbose) {
-    if (units_are_equal(snapshot_units, internal_units)) {
-
-      message("Snapshot and internal units match. No conversion needed.");
-
-    } else {
-
-      message("Conversion needed from:");
-      message("(Snapshot) Unit system: U_M =      %e g.",
-              snapshot_units->UnitMass_in_cgs);
-      message("(Snapshot) Unit system: U_L =      %e cm.",
-              snapshot_units->UnitLength_in_cgs);
-      message("(Snapshot) Unit system: U_t =      %e s.",
-              snapshot_units->UnitTime_in_cgs);
-      message("(Snapshot) Unit system: U_I =      %e A.",
-              snapshot_units->UnitCurrent_in_cgs);
-      message("(Snapshot) Unit system: U_T =      %e K.",
-              snapshot_units->UnitTemperature_in_cgs);
-      message("to:");
-      message("(internal) Unit system: U_M = %e g.",
-              internal_units->UnitMass_in_cgs);
-      message("(internal) Unit system: U_L = %e cm.",
-              internal_units->UnitLength_in_cgs);
-      message("(internal) Unit system: U_t = %e s.",
-              internal_units->UnitTime_in_cgs);
-      message("(internal) Unit system: U_I = %e A.",
-              internal_units->UnitCurrent_in_cgs);
-      message("(internal) Unit system: U_T = %e K.",
-              internal_units->UnitTemperature_in_cgs);
-    }
-  }
-
   /* Loop over all particle types */
   for (int ptype = 0; ptype < swift_type_count; ptype++) {
 
-- 
GitLab