-
Loic Hausammann authoredLoic Hausammann authored
logger_io.c 9.99 KiB
/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk),
* Matthieu Schaller (matthieu.schaller@durham.ac.uk).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
/* Config parameters. */
#include "../config.h"
#ifdef WITH_LOGGER
/* Some standard headers. */
#include <hdf5.h>
#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* This object's header. */
#include "logger_io.h"
/* Local includes. */
#include "chemistry_io.h"
#include "common_io.h"
#include "cooling.h"
#include "dimension.h"
#include "engine.h"
#include "error.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 "parallel_io.h"
#include "part.h"
#include "serial_io.h"
#include "single_io.h"
#include "stars_io.h"
#include "units.h"
#include "xmf.h"
/**
* @brief Writes an HDF5 index file
*
* @param e The engine containing all the system.
* @param baseName The common part of the snapshot file name.
* @param internal_units The #unit_system used internally
* @param snapshot_units The #unit_system used in the snapshots
*
* Creates an HDF5 output file and writes the offset and id of particles
* contained in the engine. If such a file already exists, it is erased and
* replaced by the new one.
*
* Calls #error() if an error occurs.
*
*/
void write_index_single(struct engine* e, const char* baseName,
const struct unit_system* internal_units,
const struct unit_system* snapshot_units) {
hid_t h_file = 0, h_grp = 0;
const size_t Ngas = e->s->nr_parts;
const size_t Nstars = e->s->nr_sparts;
const size_t Ntot = e->s->nr_gparts;
int periodic = e->s->periodic;
int numFiles = 1;
struct part* parts = e->s->parts;
struct xpart* xparts = e->s->xparts;
// struct gpart* gparts = e->s->gparts;
struct gpart* dmparts = NULL;
// struct spart* sparts = e->s->sparts;
static int outputCount = 0;
struct logger* log = e->logger;
/* Number of unassociated gparts */
const size_t Ndm = Ntot > 0 ? Ntot - (Ngas + Nstars) : 0;
long long N_total[swift_type_count] = {Ngas, Ndm, 0, 0, Nstars, 0};
/* File name */
char fileName[FILENAME_BUFFER_SIZE];
snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName,
outputCount);
/* Open file */
/* message("Opening file '%s'.", fileName); */
h_file = H5Fcreate(fileName, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
if (h_file < 0) {
error("Error while opening file '%s'.", fileName);
}
/* Open header to write simulation properties */
/* message("Writing runtime parameters..."); */
h_grp =
H5Gcreate(h_file, "/RuntimePars", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (h_grp < 0) error("Error while creating runtime parameters group\n");
/* Write the relevant information */
io_write_attribute(h_grp, "PeriodicBoundariesOn", INT, &periodic, 1);
/* Close runtime parameters */
H5Gclose(h_grp);
/* Open header to write simulation properties */
/* message("Writing file header..."); */
h_grp = H5Gcreate(h_file, "/Header", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (h_grp < 0) error("Error while creating file header\n");
/* Print the relevant information and print status */
io_write_attribute(h_grp, "BoxSize", DOUBLE, e->s->dim, 3);
double dblTime = e->time;
io_write_attribute(h_grp, "Time", DOUBLE, &dblTime, 1);
io_write_attribute(h_grp, "Time Offset", UINT, &log->timestamp_offset, 1);
int dimension = (int)hydro_dimension;
io_write_attribute(h_grp, "Dimension", INT, &dimension, 1);
/* GADGET-2 legacy values */
/* Number of particles of each type */
unsigned int numParticles[swift_type_count] = {0};
unsigned int numParticlesHighWord[swift_type_count] = {0};
for (int ptype = 0; ptype < swift_type_count; ++ptype) {
numParticles[ptype] = (unsigned int)N_total[ptype];
numParticlesHighWord[ptype] = (unsigned int)(N_total[ptype] >> 32);
}
io_write_attribute(h_grp, "NumPart_ThisFile", LONGLONG, N_total,
swift_type_count);
io_write_attribute(h_grp, "NumPart_Total", UINT, numParticles,
swift_type_count);
io_write_attribute(h_grp, "NumPart_Total_HighWord", UINT,
numParticlesHighWord, swift_type_count);
double MassTable[swift_type_count] = {0};
io_write_attribute(h_grp, "MassTable", DOUBLE, MassTable, swift_type_count);
unsigned int flagEntropy[swift_type_count] = {0};
flagEntropy[0] = writeEntropyFlag();
io_write_attribute(h_grp, "Flag_Entropy_ICs", UINT, flagEntropy,
swift_type_count);
io_write_attribute(h_grp, "NumFilesPerSnapshot", INT, &numFiles, 1);
/* Close header */
H5Gclose(h_grp);
/* Print the code version */
io_write_code_description(h_file);
/* 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 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 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);
}
}
/* Loop over all particle types */
for (int ptype = 0; ptype < swift_type_count; ptype++) {
/* Don't do anything if no particle of this kind */
if (numParticles[ptype] == 0) continue;
/* Open the particle group in the file */
char partTypeGroupName[PARTICLE_GROUP_BUFFER_SIZE];
snprintf(partTypeGroupName, PARTICLE_GROUP_BUFFER_SIZE, "/PartType%d",
ptype);
h_grp = H5Gcreate(h_file, partTypeGroupName, H5P_DEFAULT, H5P_DEFAULT,
H5P_DEFAULT);
if (h_grp < 0) {
error("Error while creating particle group.\n");
}
int num_fields = 0;
struct io_props list[100];
size_t N = 0;
/* Write particle fields from the particle structure */
switch (ptype) {
case swift_type_gas:
N = Ngas;
hydro_write_index(parts, xparts, list, &num_fields);
break;
case swift_type_dark_matter:
error("TODO");
break;
case swift_type_stars:
N = Nstars;
error("TODO");
// star_write_index(sparts, list, &num_fields);
break;
default:
error("Particle Type %d not yet supported. Aborting", ptype);
}
/* Write everything */
for (int i = 0; i < num_fields; ++i)
writeArray(e, h_grp, fileName, NULL, partTypeGroupName, list[i], N,
internal_units, snapshot_units);
/* Free temporary array */
if (dmparts) {
free(dmparts);
dmparts = NULL;
}
/* Close particle group */
H5Gclose(h_grp);
}
/* message("Done writing particles..."); */
/* Close file */
H5Fclose(h_file);
++outputCount;
}
#endif /* HAVE_HDF5 */