Skip to content

Commit b6f6737

Browse files
Update hdf5_save.cpp
1 parent 0238c6b commit b6f6737

1 file changed

Lines changed: 18 additions & 28 deletions

File tree

src/io/hdf5_save.cpp

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#include <iostream>
1818

1919
/**
20-
* @brief Saves the ParticleSystem to an HDF5 file and creates an XDMF sidecar.
21-
* Because we use SoA, we can pass buffer pointers directly to H5Dwrite.
20+
* @brief Saves the ParticleSystem to HDF5.
21+
* Detects real precision to match NEXT_FP32 or NEXT_FP64.
2222
*/
2323
void SaveHDF5(const ParticleSystem& ps, const std::string& filename)
2424
{
@@ -28,14 +28,10 @@ void SaveHDF5(const ParticleSystem& ps, const std::string& filename)
2828
hid_t file = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
2929
if (file < 0) return;
3030

31-
// Gadget format uses PartType1 for DM and PartType4 for Stars.
32-
// To keep it simple, we'll put all particles in PartType1,
33-
// but you could split them using ps.type[i].
3431
hid_t group = H5Gcreate(file, "PartType1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
3532

36-
// 1. Prepare Coordinates (Nx3 interleaved)
37-
// Unfortunately, HDF5 Gadget format expects XYZXYZXYZ.
38-
// Since our SoA is XXXXX, YYYYY, ZZZZZ, we DO need one interleaved buffer for Coords.
33+
// 1. Handle Coordinate/Velocity zipping
34+
// We keep these as float for visualization efficiency (ParaView rarely needs double)
3935
std::vector<float> coords(N * 3);
4036
std::vector<float> vels(N * 3);
4137
std::vector<int> ids(N);
@@ -45,54 +41,47 @@ void SaveHDF5(const ParticleSystem& ps, const std::string& filename)
4541
coords[3*i+0] = (float)ps.x[i];
4642
coords[3*i+1] = (float)ps.y[i];
4743
coords[3*i+2] = (float)ps.z[i];
48-
49-
vels[3*i+0] = (float)ps.vx[i];
50-
vels[3*i+1] = (float)ps.vy[i];
51-
vels[3*i+2] = (float)ps.vz[i];
52-
44+
vels[3*i+0] = (float)ps.vx[i];
45+
vels[3*i+1] = (float)ps.vy[i];
46+
vels[3*i+2] = (float)ps.vz[i];
5347
ids[i] = (int)i + 1;
5448
}
5549

56-
// Dataspaces
5750
hsize_t dims3[2] = { N, 3 };
5851
hid_t space3 = H5Screate_simple(2, dims3, NULL);
5952
hsize_t dims1[1] = { N };
6053
hid_t space1 = H5Screate_simple(1, dims1, NULL);
6154

62-
// Write Coordinates
55+
// Write Coords & Vels (storing as float32)
6356
hid_t dset_coords = H5Dcreate(group, "Coordinates", H5T_NATIVE_FLOAT, space3, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
6457
H5Dwrite(dset_coords, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, coords.data());
6558
H5Dclose(dset_coords);
6659

67-
// Write Velocities
6860
hid_t dset_vels = H5Dcreate(group, "Velocities", H5T_NATIVE_FLOAT, space3, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
6961
H5Dwrite(dset_vels, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, vels.data());
7062
H5Dclose(dset_vels);
7163

72-
// --- DIRECT WRITE WIN ---
73-
// For Masses and Types, we don't need temporary vectors!
74-
// We can pass the ps.m.data() pointer directly.
75-
hid_t dset_masses = H5Dcreate(group, "Masses", H5T_NATIVE_FLOAT, space1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
76-
H5Dwrite(dset_masses, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, ps.m.data());
64+
// --- TYPE-SAFE DIRECT WRITE ---
65+
// Detect if 'real' is float or double for Masses
66+
hid_t h5_real_type = (sizeof(real) == 4) ? H5T_NATIVE_FLOAT : H5T_NATIVE_DOUBLE;
67+
int precision = (sizeof(real) == 4) ? 4 : 8;
68+
69+
hid_t dset_masses = H5Dcreate(group, "Masses", h5_real_type, space1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
70+
H5Dwrite(dset_masses, h5_real_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, ps.m.data());
7771
H5Dclose(dset_masses);
7872

7973
hid_t dset_ids = H5Dcreate(group, "ParticleIDs", H5T_NATIVE_INT, space1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
8074
H5Dwrite(dset_ids, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, ids.data());
8175
H5Dclose(dset_ids);
8276

83-
// Cleanup HDF5
8477
H5Sclose(space3);
8578
H5Sclose(space1);
8679
H5Gclose(group);
8780
H5Fclose(file);
8881

89-
// ===============================
90-
// Write XDMF sidecar for ParaView
91-
// ===============================
82+
// --- XDMF SIDECAR ---
9283
std::string xdmf_filename = filename.substr(0, filename.find_last_of('.')) + ".xdmf";
9384
std::ofstream xmf(xdmf_filename);
94-
95-
// (XDMF content remains same as your original version)
9685
xmf << "<?xml version=\"1.0\" ?>\n<Xdmf Version=\"3.0\">\n <Domain>\n";
9786
xmf << " <Grid Name=\"Particles\" GridType=\"Uniform\">\n";
9887
xmf << " <Topology TopologyType=\"Polyvertex\" NumberOfElements=\"" << N << "\"/>\n";
@@ -101,7 +90,8 @@ void SaveHDF5(const ParticleSystem& ps, const std::string& filename)
10190
xmf << " " << filename << ":/PartType1/Coordinates\n";
10291
xmf << " </DataItem>\n </Geometry>\n";
10392
xmf << " <Attribute Name=\"Mass\" AttributeType=\"Scalar\" Center=\"Node\">\n";
104-
xmf << " <DataItem Dimensions=\"" << N << "\" NumberType=\"Float\" Precision=\"8\" Format=\"HDF\">\n";
93+
// We dynamically set the precision here to match the file
94+
xmf << " <DataItem Dimensions=\"" << N << "\" NumberType=\"Float\" Precision=\"" << precision << "\" Format=\"HDF\">\n";
10595
xmf << " " << filename << ":/PartType1/Masses\n";
10696
xmf << " </DataItem>\n </Attribute>\n";
10797
xmf << " </Grid>\n </Domain>\n</Xdmf>\n";

0 commit comments

Comments
 (0)