TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
FichierHDF.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15#include <EntreeSortie.h>
16#include <FichierHDF.h>
17#include <vector>
18#include <communications.h>
19
20#ifndef MED_
22{
23 Cerr << "FichierHDF needs HDF (so MED) to be used!" << finl;
24 Process::exit(-1);
25}
27
28void FichierHDF::create(Nom filename) {}
29void FichierHDF::open(Nom filename, bool readOnly) {}
31
33void FichierHDF::create_and_fill_dataset_MW(Nom dataset_basename, SChaine& sortie) {}
35void FichierHDF::fill_dataset(Nom dataset_name, Sortie_Brute& sortie) {}
36
37void FichierHDF::read_dataset(Nom dataset_basename, int proc_rank, Entree_Brute& entree) {}
38
39bool FichierHDF::exists(const char* dataset_name)
40{
41 return true;
42}
43bool FichierHDF::is_hdf5(const char *file_name)
44{
45 return false;
46}
47
50#else
51
52
53template<typename T>
54static inline void hdf5_error(T status)
55{
56 if (status <0)
57 {
58 Cerr << "HDF5 error occured - exiting" << finl;
60 }
61}
62
63FichierHDF::FichierHDF(): file_id_(0), file_access_plst_(0),
64 dataset_transfer_plst_(0) {}
65
67{
68 //close();
69}
70
71void FichierHDF::create(Nom filename)
72{
74 file_id_ = H5Fcreate(filename, H5F_ACC_TRUNC /*H5F_ACC_EXCL*/, H5P_DEFAULT, file_access_plst_);
75 hdf5_error<hid_t>(file_id_);
76 Cerr << "HDF5 " << filename << " file created !" << finl;
78}
79
80void FichierHDF::open(Nom filename, bool readOnly)
81{
83 unsigned st = readOnly ? H5F_ACC_RDONLY : H5F_ACC_RDWR;
84 file_id_ = H5Fopen(filename, st, file_access_plst_);
85 hdf5_error<hid_t>(file_id_);
86 Cerr << "HDF5 " << filename << " file opened !" << finl;
87 check_int_size(filename);
88}
89
91{
92 file_access_plst_ = H5Pcreate(H5P_FILE_ACCESS);
93
94 //increasing size of the B-tree containing metadata info (to approximately match the size striping)
95 //useful when we are writing a lot of chunks
96 // see https://www.nersc.gov/users/training/online-tutorials/introduction-to-scientific-i-o/?show_all=1
97 // file_creation_plst_ = H5Pcreate(H5P_FILE_CREATE);
98 // hsize_t btree_ik = (stripe_size - 4096) / 96;
99 // H5Pset_istore_k(file_creation_plst_, btree_ik);
100}
101
103{
104 dataset_transfer_plst_ = H5Pcreate(H5P_DATASET_XFER);
105}
106
107
109{
110 Cerr << "[HDF5] closing file..." << finl;
111
112 //getting file name
113 char filename[100];
114 H5Fget_name(file_id_, filename, 100);
115
116 H5Fclose(file_id_);
117
118 if(file_access_plst_) H5Pclose(file_access_plst_);
119 if(dataset_transfer_plst_) H5Pclose(dataset_transfer_plst_);
120 Cerr << "HDF5 " << filename << " file closed !" << finl;
121
122}
123
124void FichierHDF::read_dataset(Nom dataset_basename, int proc_rank, Entree_Brute& entree)
125{
127
128 Nom dataset_name = dataset_basename;
129 dataset_name = dataset_name.nom_me(proc_rank, 0, 1 /*without_padding*/);
130
131 hid_t dataset_id = H5Dopen2(file_id_, dataset_name, H5P_DEFAULT);
132 hid_t dataspace_id = H5Dget_space(dataset_id);
133 hssize_t sz = H5Sget_simple_extent_npoints(dataspace_id);
134 char * dset_data = new char[sz];
135 Cerr << "[HDF5] Reading into HDF dataset " << dataset_name << "...";
136 H5Dread(dataset_id, H5T_NATIVE_OPAQUE, H5S_ALL, H5S_ALL, dataset_transfer_plst_, dset_data);
137 Cerr << " Done !" << finl;
138
139 // Put extracted data in a standard Entree_Brute from TRUST, that we then use to feed TRUST objects
140 if(is_different_int_size_)
141#ifdef INT_is_64_
142 entree.set_64b(false);
143#else
144 entree.set_64b(true);
145#endif
146 entree.set_data(dset_data, (unsigned) sz); // data are copied into the Entree
147
148 delete[] dset_data;
149 H5Dclose(dataset_id);
150 H5Sclose(dataspace_id);
151
152}
153
154
155void FichierHDF::create_datasets(Noms dataset_names, hsize_t length)
156{
157 hid_t dataspace_id = H5Screate_simple(1, &length, nullptr);
158
159 // Create the dataset
160 for(int i=0; i<dataset_names.size(); i++)
161 {
162 Nom dataset_name = dataset_names[i];
163 hid_t dataset_id = H5Dcreate2(file_id_, dataset_name, H5T_NATIVE_OPAQUE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
164 hdf5_error<herr_t>(H5Dclose(dataset_id));
165 }
166 // Close dataset and dataspace
167 hdf5_error<herr_t>(H5Sclose(dataspace_id));
168
169 Cerr << "[HDF5] All datasets created !" << finl;
170}
171
172
173void FichierHDF::fill_dataset(Nom dataset_name, Sortie_Brute& sortie)
174{
176
177 hsize_t lenData = sortie.get_size();
178 const char * data = sortie.get_data();
179
180 hsize_t dims[1] = {lenData};
181 hid_t dataspace_id = H5Screate_simple(1, dims, nullptr);
182
183 // Open the dataset
184 hid_t dataset_id = H5Dopen2(file_id_, dataset_name, H5P_DEFAULT);
185 hdf5_error<hid_t>(dataset_id );
186
187 // Writing into it:
188 Cerr << "[HDF5] Writing into HDF dataset " << dataset_name << "...";
189 hdf5_error<herr_t>(H5Dwrite(dataset_id, H5T_NATIVE_OPAQUE, H5S_ALL, dataspace_id, dataset_transfer_plst_, data));
190 Cerr << " Done !" << finl;
191
192 // Close dataset and dataspace
193 hdf5_error<herr_t>(H5Dclose(dataset_id));
194 hdf5_error<herr_t>(H5Sclose(dataspace_id));
195
196}
197
198
199
200void FichierHDF::create_and_fill_dataset_MW(Nom dataset_basename, Sortie_Brute& sortie)
201{
202 hsize_t lenData = sortie.get_size();
203 const char * data = sortie.get_data();
204
205 create_and_fill_dataset_MW(dataset_basename, data, lenData, H5T_NATIVE_OPAQUE);
206}
207
208
209void FichierHDF::create_and_fill_dataset_MW(Nom dataset_basename, SChaine& sortie)
210{
211 hsize_t lenData = sortie.get_size();
212 const char * data = sortie.get_str();
213
214 create_and_fill_dataset_MW(dataset_basename, data, lenData, H5T_C_S1);
215}
216
217
218void FichierHDF::create_and_fill_dataset_MW(Nom dataset_basename, const char* data, hsize_t lenData, hid_t datatype)
219{
220 //collecting the lengths of the datasets from every other processors
221 long long init_value = lenData;
222 std::vector<long long> datasets_len(Process::nproc(), init_value);
223 envoyer_all_to_all(datasets_len, datasets_len);
224
225 // Creating the datasets from every processor
226 // (metadata have to be written collectively)
227 std::vector<hid_t> datasets_id(Process::nproc());
228 Nom my_dataset_name;
229
230 for(int p = 0; p < Process::nproc(); p++)
231 {
232 Nom dname = dataset_basename;
233 dname = dname.nom_me(p, 0, 1 /*without_padding*/);
234 if(p == Process::me()) my_dataset_name = dname;
235 hsize_t dlen= datasets_len[p];
236 hid_t dspace = H5Screate_simple(1, &dlen, nullptr);
237
238 datasets_id[p] = H5Dcreate2(file_id_, dname, datatype, dspace,
239 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
240 H5Sclose(dspace);
241 }
242
243 Cerr << "[HDF5] All datasets created !" << finl;
244
245 hid_t dataspace_id = H5Screate_simple(1, &lenData, nullptr);
246
247 Cerr << "[HDF5] Writing into HDF dataset " << my_dataset_name << "...";
248 // Writing my own dataset
249 H5Dwrite(datasets_id[Process::me()], datatype, dataspace_id, H5S_ALL, dataset_transfer_plst_, data);
250 Cerr << " Dataset written !" << finl;
251
252 // Close dataset and dataspace
253 for(int p = 0; p < Process::nproc(); p++)
254 H5Dclose(datasets_id[p]);
255 Cerr << "[HDF5] All datasets closed !" << finl;
256
257 H5Sclose(dataspace_id);
258}
259
261{
263
264 hsize_t lenData = sortie.get_size();
265 const char * data = sortie.get_data();
266
267 hsize_t dims[1] = {lenData};
268 hid_t dataspace_id = H5Screate_simple(1, dims, nullptr);
269
270 // Create the dataset
271 hid_t dataset_id = H5Dcreate2(file_id_, dataset_name, H5T_NATIVE_OPAQUE, dataspace_id,
272 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
273
274 // Writing into it:
275 Cerr << "[HDF5] Writing into HDF dataset " << dataset_name << "...";
276 H5Dwrite(dataset_id, H5T_NATIVE_OPAQUE, H5S_ALL, H5S_ALL, dataset_transfer_plst_, data);
277 Cerr << " Done !" << finl;
278
279 // Close dataset and dataspace
280 H5Dclose(dataset_id);
281 H5Sclose(dataspace_id);
282
283}
284
285
286
287bool FichierHDF::exists(const char* dataset_name)
288{
289 return H5Lexists( file_id_, dataset_name, H5P_DEFAULT )>0;
290}
291
292bool FichierHDF::is_hdf5(const char * file_name)
293{
294 return H5Fis_hdf5(file_name)>0;
295}
296
297
299{
300 // Create attribute specifying whether ints are 32 or 64 bits
301 hid_t space_id = H5Screate(H5S_SCALAR);
302 hid_t attr_id = H5Acreate(file_id_, "int_size_in_bits", H5T_NATIVE_INT32, space_id, H5P_DEFAULT, H5P_DEFAULT);
303#ifdef INT_is_64_
304 int int_size = 64;
305#else
306 int int_size = 32;
307#endif
308 H5Awrite(attr_id, H5T_NATIVE_INT32, &int_size);
309 H5Aclose(attr_id);
310 H5Sclose(space_id);
311
312}
313
314void FichierHDF::check_int_size(Nom filename)
315{
316 int TRUST_int_type_exists_in_file = H5Aexists(file_id_, "int_size_in_bits");
317 if (TRUST_int_type_exists_in_file < 0)
318 {
319 Cerr << "Error " << (int) TRUST_int_type_exists_in_file;
320 Cerr << " while getting the attribute 'int_size_in_bits' in the ";
321 Cerr << filename << " HDF file" << finl;
322 Process::exit(-1);
323 }
324 else if (TRUST_int_type_exists_in_file == 0)
325 {
326 Cerr << "Warning, we can't find whether the " << filename << " HDF file was written with -int32 or -int64" << finl;
327 Cerr << "Possibly old files created before 1.8.4 version" << finl;
328 Cerr << "If an error occurs, or results seem weird, try opening it with ";
329#ifdef INT_is_64_
330 Cerr << "an -int32 TRUST version." << finl;
331#else
332 Cerr << "an -int64 TRUST version." << finl;
333#endif
334 Cerr << "Or set environment variable TRUST_FORCE_DIFFERENT_INT_SIZE to 1 to try" << finl;
335 Cerr << "reading the int32 (or int64) file by a int64 (or int32) TRUST binary." << finl;
336 if (getenv("TRUST_FORCE_DIFFERENT_INT_SIZE")!=nullptr) is_different_int_size_ = true;
337 }
338 else
339 {
340 hid_t attr_id = H5Aopen(file_id_, "int_size_in_bits", H5P_DEFAULT);
341 int int_size_in_bits;
342 H5Aread(attr_id, H5T_NATIVE_INT32, &int_size_in_bits);
343 Cerr << "[HDF5] We read that "<< filename << " was written in -int" << (int)int_size_in_bits << finl;
344
345 if (!(int_size_in_bits == 32 || int_size_in_bits == 64))
346 {
347 Cerr << "[HDF5] We read -int"<< (int)int_size_in_bits << " in " << filename << " which is abnormal." << finl;
348 H5Aclose(attr_id);
349 Process::exit(-1);
350 }
351
352#ifdef INT_is_64_
353 if (int_size_in_bits == 32) is_different_int_size_ = true;
354#else
355 if (int_size_in_bits == 64)
356 {
357 is_different_int_size_ = true;
358 Cerr << "Warning, HDF file " << filename << " was written with an -int64 version and you are reading it with an -int32 version."<< finl;
359 Cerr << "Make sure your mesh doesn't contain more than 2^32 elements, nodes or faces." << finl;
360 }
361#endif
362
363 H5Aclose(attr_id);
364 }
365}
366
367// void FichierHDF::get_chunking(hsize_t datasetLen)
368// {
369// hsize_t FourGB = 4294967296; //maximum limit tolerated by HDF5
370// //if the dataset is not big enough, there's no need for chunking
371// if(datasetLen > FourGB)
372// chunk_size_ = FourGB;
373// }
374
375#endif
virtual void set_64b(bool is_64b)
Definition AbstractIO.h:38
An Entree whose main source of data is an arbitrary binary buffer set using the set_data() method.
void set_data(const char *data, unsigned sz)
void check_int_size(Nom filename)
static bool is_hdf5(const char *file_name)
virtual void create_and_fill_dataset_MW(Nom dataset_basename, Sortie_Brute &sortie)
virtual void prepare_file_props()
void fill_dataset(Nom dataset_name, Sortie_Brute &sortie)
virtual void read_dataset(Nom dataset_basename, int proc_rank, Entree_Brute &entree)
virtual void open(Nom filename, bool readOnly)
virtual bool exists(const char *dataset_name)
virtual void create_and_fill_dataset_SW(Nom datasetname, Sortie_Brute &sortie)
void set_int_size()
virtual void prepare_dataset_props()
void create_datasets(Noms dataset_names, long length)
Definition FichierHDF.h:74
virtual ~FichierHDF()
virtual void close()
virtual void create(Nom filename)
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Nom nom_me(int, const char *prefix=0, int without_padding=0) const
Insere _prefix000n (n=me() ou nproc()) dans un nom de fichier (par ex:toto.
Definition Nom.cpp:387
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Cette classe derivee de Sortie empile ce qu'on lui envoie dans une chaine de caracteres.
Definition SChaine.h:26
const char * get_str() const
returns a copy of the string stored by the SChaine
Definition SChaine.cpp:72
unsigned get_size() const
Definition SChaine.cpp:80
This derived class of Sortie stacks whatever it receives in an internal binary buffer.
unsigned get_size() const
const char * get_data() const
returns a pointer to the internal data.