Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
Hdf5Utils.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* Hdf5Utils.cc (C) 2000-2026 */
9/* */
10/* Utilitaires HDF5. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Iostream.h"
15#include "arcane/utils/Array.h"
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/NotSupportedException.h"
18#include "arcane/utils/ArgumentException.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/TraceInfo.h"
21#include "arcane/utils/IOException.h"
22#include "arcane/utils/Convert.h"
23
24#include "arcane/core/ArcaneException.h"
25#include "arcane/core/IParallelMng.h"
26
27#include "arcane/hdf5/Hdf5Utils.h"
28
29#include <algorithm>
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
35{
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40namespace
41{
42 std::once_flag h5open_once_flag;
43
44#if (defined(H5_HAVE_THREADSAFE) || defined(H5_HAVE_CONCURRENCY))
45 bool global_hdf5_mutex_is_active = false;
46#else
47 bool global_hdf5_mutex_is_active = true;
48#endif
49
50 std::mutex global_hdf5_mutex;
51 Hdf5Mutex hdf5_mutex(global_hdf5_mutex, global_hdf5_mutex_is_active);
52
53#if (defined(H5_HAVE_THREADSAFE) || defined(H5_HAVE_CONCURRENCY))
54#define ARCANE_HDF5_MUTEX
55#else
56 struct ScopedMutex
57 {
58 ScopedMutex()
59 {
60 hdf5_mutex.lock();
61 }
62 ~ScopedMutex()
63 {
64 hdf5_mutex.unlock();
65 }
66 };
67#define ARCANE_HDF5_MUTEX ScopedMutex scoped_mutex
68#endif
69} // namespace
70
71Hdf5Mutex& _ArcaneHdf5UtilsMutex()
72{
73 return hdf5_mutex;
74}
75
76/*---------------------------------------------------------------------------*/
77/*---------------------------------------------------------------------------*/
78
79HInit::
80HInit()
81{
82 // Garanti que cela ne sera appelé qu'une seule fois et protège des appels
83 // concurrents.
84 std::call_once(h5open_once_flag, []() { H5open(); });
85}
86
87/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89
91useMutex([[maybe_unused]] bool is_active, [[maybe_unused]] IParallelMng* pm)
92{
93#if (defined(H5_HAVE_THREADSAFE) || defined(H5_HAVE_CONCURRENCY))
94 pm->traceMng()->info(4) << "HDF5 -- Is HDF5 threadsafe: 1 -- Is Mutex enabled: " << global_hdf5_mutex_is_active;
95#else
96 bool env_is_enable = true;
97 if (const auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_HDF5_DISABLE_MUTEX", true)) {
98 env_is_enable = (v.value() == 0);
99 }
100 pm->barrier();
101 global_hdf5_mutex.lock();
102 global_hdf5_mutex_is_active = env_is_enable && is_active;
103 global_hdf5_mutex.unlock();
104 pm->barrier();
105 pm->traceMng()->info(4) << "HDF5 -- Is HDF5 threadsafe: 0 -- Is Mutex enabled: " << global_hdf5_mutex_is_active;
106#endif
107}
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111
112namespace
113{
114
115 hid_t _H5Gopen(hid_t loc_id, const char* name)
116 {
117 return H5Gopen2(loc_id, name, H5P_DEFAULT);
118 }
119
120 hid_t _H5Gcreate(hid_t loc_id, const char* name)
121 {
122 return H5Gcreate2(loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
123 }
124
125} // namespace
126/*---------------------------------------------------------------------------*/
127/*---------------------------------------------------------------------------*/
128
129extern "C" ARCANE_HDF5_EXPORT herr_t
130_ArcaneHdf5UtilsGroupIterateMe(hid_t g, const char* mn, void* ptr)
131{
132 ARCANE_UNUSED(g);
133 HGroupSearch* rw = reinterpret_cast<HGroupSearch*>(ptr);
134 return rw->iterateMe(mn);
135}
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
140void splitString(const String& str, Array<String>& str_array, char c)
141{
142 const char* str_str = str.localstr();
143 Int64 offset = 0;
144 Int64 len = str.length();
145 for (Int64 i = 0; i < len; ++i) {
146 if (str_str[i] == c && i != offset) {
147 str_array.add(std::string_view(str_str + offset, i - offset));
148 offset = i + 1;
149 }
150 }
151 if (len != offset)
152 str_array.add(std::string_view(str_str + offset, len - offset));
153}
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157
158void HFile::
159openTruncate(const String& var)
160{
161 close();
162 {
163 ARCANE_HDF5_MUTEX;
164 _setId(H5Fcreate(var.localstr(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT));
165 }
166 if (isBad())
167 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
168}
169
170void HFile::
171openAppend(const String& var)
172{
173 close();
174 {
175 ARCANE_HDF5_MUTEX;
176 _setId(H5Fopen(var.localstr(), H5F_ACC_RDWR, H5P_DEFAULT));
177 }
178 if (isBad())
179 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
180}
181
182void HFile::
183openRead(const String& var)
184{
185 close();
186 {
187 ARCANE_HDF5_MUTEX;
188 _setId(H5Fopen(var.localstr(), H5F_ACC_RDONLY, H5P_DEFAULT));
189 }
190 if (isBad())
191 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
192}
193
194void HFile::
195openTruncate(const String& var, hid_t plist_id)
196{
197 close();
198 {
199 ARCANE_HDF5_MUTEX;
200 _setId(H5Fcreate(var.localstr(), H5F_ACC_TRUNC, H5P_DEFAULT, plist_id));
201 }
202 if (isBad())
203 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
204}
205
206void HFile::
207openAppend(const String& var, hid_t plist_id)
208{
209 close();
210 {
211 ARCANE_HDF5_MUTEX;
212 _setId(H5Fopen(var.localstr(), H5F_ACC_RDWR, plist_id));
213 }
214 if (isBad())
215 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
216}
217
218void HFile::
219openRead(const String& var, hid_t plist_id)
220{
221 close();
222 {
223 ARCANE_HDF5_MUTEX;
224 _setId(H5Fopen(var.localstr(), H5F_ACC_RDONLY, plist_id));
225 }
226 if (isBad())
227 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
228}
229
230/*---------------------------------------------------------------------------*/
231/*---------------------------------------------------------------------------*/
232
233herr_t HFile::
234_close()
235{
236 herr_t e = 0;
237 if (id() > 0) {
238 ARCANE_HDF5_MUTEX;
239 e = H5Fclose(id());
240 _setNullId();
241 }
242 return e;
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248void HFile::
249close()
250{
251 herr_t e = _close();
252 if (e < 0)
253 ARCANE_THROW(ReaderWriterException, "Can not close file");
254}
255
256/*---------------------------------------------------------------------------*/
257/*---------------------------------------------------------------------------*/
258
259void HGroup::
260recursiveCreate(const Hid& loc_id, const String& var)
261{
262 UniqueArray<String> bufs;
263 splitString(var, bufs, '/');
264 recursiveCreate(loc_id, bufs);
265}
266
267void HGroup::
268recursiveCreate(const Hid& loc_id, const Array<String>& bufs)
269{
270 close();
271 hid_t last_hid = loc_id.id();
272 Integer nb_create = bufs.size();
273 UniqueArray<hid_t> ref_ids(nb_create);
274 for (Integer i = 0; i < nb_create; ++i) {
275 last_hid = _checkOrCreate(last_hid, bufs[i]);
276 ref_ids[i] = last_hid;
277 }
278 // Libere tous les groupes intermediaires crees
279 ARCANE_HDF5_MUTEX;
280 for (Integer i = 0; i < nb_create - 1; ++i) {
281 H5Gclose(ref_ids[i]);
282 }
283 _setId(last_hid);
284}
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
288
289void HGroup::
290checkDelete(const Hid& loc_id, const String& var)
291{
292 UniqueArray<String> bufs;
293 splitString(var, bufs, '/');
294 hid_t last_hid = loc_id.id();
295 hid_t parent_hid = last_hid;
296 Integer i = 0;
297 Integer size = bufs.size();
298 for (; i < size; ++i) {
299 parent_hid = last_hid;
300 last_hid = _checkExist(last_hid, bufs[i]);
301 if (last_hid == 0)
302 break;
303 }
304 // Groupe trouvé, on le détruit.
305 if (last_hid > 0 && parent_hid > 0 && i == size) {
306 //cerr << "** DELETE <" << bufs[size-1] << "\n";
307 ARCANE_HDF5_MUTEX;
308 H5Gunlink(parent_hid, bufs[size - 1].localstr());
309 }
310}
311
312/*---------------------------------------------------------------------------*/
313/*---------------------------------------------------------------------------*/
314
315void HGroup::
316recursiveOpen(const Hid& loc_id, const String& var)
317{
318 close();
319 UniqueArray<String> bufs;
320 splitString(var, bufs, '/');
321 hid_t last_hid = loc_id.id();
322 Integer nb_open = bufs.size();
323 UniqueArray<hid_t> ref_ids(nb_open);
324 ARCANE_HDF5_MUTEX;
325 for (Integer i = 0; i < nb_open; ++i) {
326 last_hid = _H5Gopen(last_hid, bufs[i].localstr());
327 ref_ids[i] = last_hid;
328 }
329 // Libere tous les groupes intermediaires ouverts
330 for (Integer i = 0; i < nb_open - 1; ++i) {
331 H5Gclose(ref_ids[i]);
332 }
333 _setId(last_hid);
334}
335
336/*---------------------------------------------------------------------------*/
337/*---------------------------------------------------------------------------*/
338
339void HGroup::
340openIfExists(const Hid& loc_id, const Array<String>& paths)
341{
342 close();
343 hid_t last_hid = loc_id.id();
344 bool is_valid = true;
345 Integer nb_open = paths.size();
346 UniqueArray<hid_t> ref_ids;
347 ref_ids.reserve(nb_open);
348 for (Integer i = 0; i < nb_open; ++i) {
349 if (HGroup::hasChildren(last_hid, paths[i].localstr())) {
350 ARCANE_HDF5_MUTEX;
351 last_hid = _H5Gopen(last_hid, paths[i].localstr());
352 ref_ids.add(last_hid);
353 }
354 else {
355 is_valid = false;
356 break;
357 }
358 }
359 if (is_valid)
360 _setId(last_hid);
361 // Ferme tous les groupes intermediaires
362 ARCANE_HDF5_MUTEX;
363 for (Integer i = 0; i < ref_ids.size(); ++i) {
364 if (ref_ids[i] != last_hid) {
365 H5Gclose(ref_ids[i]);
366 }
367 }
368}
369
370/*---------------------------------------------------------------------------*/
371/*---------------------------------------------------------------------------*/
372
373bool HGroup::
374hasChildren(const String& var)
375{
376 return hasChildren(id(), var);
377}
378
379/*---------------------------------------------------------------------------*/
380/*---------------------------------------------------------------------------*/
381
382bool HGroup::
383hasChildren(hid_t loc_id, const String& var)
384{
385 HGroupSearch gs(var);
386 ARCANE_HDF5_MUTEX;
387 herr_t v = H5Giterate(loc_id, ".", 0, _ArcaneHdf5UtilsGroupIterateMe, &gs);
388 bool has_children = v > 0;
389 //cout << "** HAS CHILDREN " << var << " v=" << has_children << '\n';
390 return has_children;
391}
392
393/*---------------------------------------------------------------------------*/
394/*---------------------------------------------------------------------------*/
395
396hid_t HGroup::
397_checkOrCreate(hid_t loc_id, const String& group_name)
398{
399 // Pour vérifier si un groupe existe déjà, comme il n'existe aucune
400 // fonction digne de ce nom dans HDF5, on utilise le mécanisme d'itération
401 // pour stocker tous les groupes fils de ce groupe, et on recherche ensuite
402 // si le groupe souhaité existe
403 HGroupSearch gs(group_name);
404 //cerr << "** CHECK CREATE <" << group_name.str() << ">\n";
405 ARCANE_HDF5_MUTEX;
406 herr_t v = H5Giterate(loc_id, ".", 0, _ArcaneHdf5UtilsGroupIterateMe, &gs);
407
408 // Regarde si le groupe existe déjà
409 //herr_t he = H5Gget_objinfo(loc_id,group_name.str(),true,0);
410 //cerr << "** CHECK CREATE <" << group_name.str() << "> " << v << "\n";
411 //cerr << "** CHECK CREATE <" << group_name.str() << "> " << v << ' ' << he << "\n";
412 if (v > 0) {
413 return _H5Gopen(loc_id, group_name.localstr());
414 }
415 hid_t new_id = _H5Gcreate(loc_id, group_name.localstr());
416 //cerr << "** TRY TO CREATE <" << group_name.str() << "> " << new_id << "\n";
417 return new_id;
418}
419
420/*---------------------------------------------------------------------------*/
421/*---------------------------------------------------------------------------*/
422
423void HGroup::
424create(const Hid& loc_id, const String& group_name)
425{
426 ARCANE_HDF5_MUTEX;
427 _setId(H5Gcreate2(loc_id.id(), group_name.localstr(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
428}
429
430/*---------------------------------------------------------------------------*/
431/*---------------------------------------------------------------------------*/
432
433void HGroup::
434openOrCreate(const Hid& loc_id, const String& group_name)
435{
436 hid_t id = _checkOrCreate(loc_id.id(), group_name);
437 if (id < 0)
438 ARCANE_THROW(ReaderWriterException, "Can not open or create group named '{0}'", group_name);
439 _setId(id);
440}
441
442/*---------------------------------------------------------------------------*/
443/*---------------------------------------------------------------------------*/
444
445void HGroup::
446open(const Hid& loc_id, const String& var)
447{
448 hid_t id = -1;
449 {
450 ARCANE_HDF5_MUTEX;
451 id = _H5Gopen(loc_id.id(), var.localstr());
452 }
453 if (id < 0)
454 ARCANE_THROW(ReaderWriterException, "Can not find group named '{0}'", var);
455 _setId(id);
456}
457
458/*---------------------------------------------------------------------------*/
459/*---------------------------------------------------------------------------*/
460
461void HGroup::
462close()
463{
464 if (id() > 0) {
465 ARCANE_HDF5_MUTEX;
466 H5Gclose(id());
467 _setNullId();
468 }
469}
470
471/*---------------------------------------------------------------------------*/
472/*---------------------------------------------------------------------------*/
473
474hid_t HGroup::
475_checkExist(hid_t loc_id, const String& group_name)
476{
477 // Pour vérifier si un groupe existe déjà, comme il n'existe aucune
478 // fonction digne de ce nom dans HDF5, on utilise le mécanisme d'itération
479 // pour stocker tous les groupes fils de ce groupe, et on recherche ensuite
480 // si le groupe souhaité existe
481 HGroupSearch gs(group_name);
482 //cerr << "** CHECK CREATE <" << group_name.str() << ">\n";
483 ARCANE_HDF5_MUTEX;
484 herr_t v = H5Giterate(loc_id, ".", 0, _ArcaneHdf5UtilsGroupIterateMe, &gs);
485
486 // Regarde si le groupe existe déjà
487 //herr_t he = H5Gget_objinfo(loc_id,group_name.str(),true,0);
488 //cerr << "** CHECK CREATE <" << group_name.str() << "> " << v << "\n";
489 //cerr << "** CHECK CREATE <" << group_name.str() << "> " << v << ' ' << he << "\n";
490 if (v > 0) {
491 return _H5Gopen(loc_id, group_name.localstr());
492 }
493 //hid_t new_id = H5Gcreate(loc_id,group_name.localstr(),0);
494 //cerr << "** TRY TO CREATE <" << group_name.str() << "> " << new_id << "\n";
495 return 0;
496}
497
498/*---------------------------------------------------------------------------*/
499/*---------------------------------------------------------------------------*/
500
501/*---------------------------------------------------------------------------*/
502/*---------------------------------------------------------------------------*/
503
504HSpace::
505~HSpace()
506{
507 if (id() > 0) {
508 ARCANE_HDF5_MUTEX;
509 H5Sclose(id());
510 }
511}
512
513/*---------------------------------------------------------------------------*/
514/*---------------------------------------------------------------------------*/
515
516void HSpace::
517createSimple(int nb, hsize_t dims[])
518{
519 ARCANE_HDF5_MUTEX;
520 _setId(H5Screate_simple(nb, dims, nullptr));
521}
522
523/*---------------------------------------------------------------------------*/
524/*---------------------------------------------------------------------------*/
525
526void HSpace::
527createSimple(int nb, hsize_t dims[], hsize_t max_dims[])
528{
529 ARCANE_HDF5_MUTEX;
530 _setId(H5Screate_simple(nb, dims, max_dims));
531}
532
533/*---------------------------------------------------------------------------*/
534/*---------------------------------------------------------------------------*/
535
536int HSpace::
537nbDimension()
538{
539 ARCANE_HDF5_MUTEX;
540 return H5Sget_simple_extent_ndims(id());
541}
542
543/*---------------------------------------------------------------------------*/
544/*---------------------------------------------------------------------------*/
545
546herr_t HSpace::
547getDimensions(hsize_t dims[], hsize_t max_dims[])
548{
549 ARCANE_HDF5_MUTEX;
550 return H5Sget_simple_extent_dims(id(), dims, max_dims);
551}
552
553/*---------------------------------------------------------------------------*/
554/*---------------------------------------------------------------------------*/
555
556/*---------------------------------------------------------------------------*/
557/*---------------------------------------------------------------------------*/
558
559void HDataset::
560close()
561{
562 if (id() > 0) {
563 ARCANE_HDF5_MUTEX;
564 H5Dclose(id());
565 }
566 _setNullId();
567}
568
569/*---------------------------------------------------------------------------*/
570/*---------------------------------------------------------------------------*/
571
572void HDataset::
573create(const Hid& loc_id, const String& var, hid_t save_type,
574 const HSpace& space_id, hid_t plist)
575{
576 ARCANE_HDF5_MUTEX;
577 hid_t hid = H5Dcreate2(loc_id.id(), var.localstr(), save_type, space_id.id(),
578 plist, H5P_DEFAULT, H5P_DEFAULT);
579 //cerr << "** CREATE ID=" << hid << '\n';
580 _setId(hid);
581}
582
583/*---------------------------------------------------------------------------*/
584/*---------------------------------------------------------------------------*/
585
586void HDataset::
587create(const Hid& loc_id, const String& var, hid_t save_type,
588 const HSpace& space_id, const HProperty& link_plist,
589 const HProperty& creation_plist, const HProperty& access_plist)
590{
591 ARCANE_HDF5_MUTEX;
592 hid_t hid = H5Dcreate2(loc_id.id(), var.localstr(), save_type, space_id.id(),
593 link_plist.id(), creation_plist.id(), access_plist.id());
594 //cerr << "** CREATE ID=" << hid << '\n';
595 _setId(hid);
596}
597
598/*---------------------------------------------------------------------------*/
599/*---------------------------------------------------------------------------*/
600
601herr_t HDataset::
602write(hid_t native_type, const void* array)
603{
604 //cerr << "** WRITE ID=" << id() << '\n';
605 ARCANE_HDF5_MUTEX;
606 return H5Dwrite(id(), native_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, array);
607}
608
609/*---------------------------------------------------------------------------*/
610/*---------------------------------------------------------------------------*/
611
612herr_t HDataset::
613write(hid_t native_type, const void* array, const HSpace& memspace_id,
614 const HSpace& filespace_id, hid_t plist)
615{
616 //cerr << "** WRITE ID=" << id() << '\n';
617 ARCANE_HDF5_MUTEX;
618 return H5Dwrite(id(), native_type, memspace_id.id(), filespace_id.id(), plist, array);
619}
620
621/*---------------------------------------------------------------------------*/
622/*---------------------------------------------------------------------------*/
623
624herr_t HDataset::
625write(hid_t native_type, const void* array, const HSpace& memspace_id,
626 const HSpace& filespace_id, const HProperty& plist)
627{
628 //cerr << "** WRITE ID=" << id() << '\n';
629 ARCANE_HDF5_MUTEX;
630 return H5Dwrite(id(), native_type, memspace_id.id(), filespace_id.id(), plist.id(), array);
631}
632
633/*---------------------------------------------------------------------------*/
634/*---------------------------------------------------------------------------*/
635
636herr_t HDataset::
637read(hid_t native_type, void* array)
638{
639 ARCANE_HDF5_MUTEX;
640 return H5Dread(id(), native_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, array);
641}
642
643/*---------------------------------------------------------------------------*/
644/*---------------------------------------------------------------------------*/
645
646void HDataset::
647readWithException(hid_t native_type, void* array)
648{
649 herr_t err = -1;
650 {
651 ARCANE_HDF5_MUTEX;
652 err = H5Dread(id(), native_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, array);
653 }
654 if (err != 0)
655 ARCANE_THROW(IOException, "Can not read dataset");
656}
657
658/*---------------------------------------------------------------------------*/
659/*---------------------------------------------------------------------------*/
660
661HSpace HDataset::
662getSpace()
663{
664 ARCANE_HDF5_MUTEX;
665 return HSpace(H5Dget_space(id()));
666}
667
668/*---------------------------------------------------------------------------*/
669/*---------------------------------------------------------------------------*/
670
671herr_t HDataset::
672setExtent(const hsize_t new_dims[])
673{
674 ARCANE_HDF5_MUTEX;
675 return H5Dset_extent(id(), new_dims);
676}
677
678/*---------------------------------------------------------------------------*/
679/*---------------------------------------------------------------------------*/
680
681void HDataset::
682recursiveCreate(const Hid& loc_id, const String& var, hid_t save_type,
683 const HSpace& space_id, hid_t plist)
684{
685 // Si le dataset existe déjà, il faut le supprimer
686 // car sinon il n'est pas toujours possible de modifer le space_id
687 UniqueArray<String> paths;
688 splitString(var, paths, '/');
689 Integer nb_path = paths.size();
690 if (nb_path == 1) {
691 if (HGroup::hasChildren(loc_id.id(), var)) {
692 _remove(loc_id.id(), var);
693 }
694 create(loc_id, var, save_type, space_id, plist);
695 return;
696 }
697 String last_name = paths[nb_path - 1];
698 paths.resize(nb_path - 1);
699 HGroup group;
700 group.recursiveCreate(loc_id, paths);
701 if (group.hasChildren(last_name)) {
702 _remove(group.id(), last_name);
703 }
704 create(group.id(), last_name, save_type, space_id, plist);
705}
706
707/*---------------------------------------------------------------------------*/
708/*---------------------------------------------------------------------------*/
709
710void HDataset::
711_remove(hid_t hid, const String& var)
712{
713 ARCANE_HDF5_MUTEX;
714 H5Gunlink(hid, var.localstr());
715}
716
717/*---------------------------------------------------------------------------*/
718/*---------------------------------------------------------------------------*/
719
720HAttribute::
721~HAttribute()
722{
723 if (id() > 0) {
724 ARCANE_HDF5_MUTEX;
725 H5Aclose(id());
726 }
727}
728
729/*---------------------------------------------------------------------------*/
730/*---------------------------------------------------------------------------*/
731
732void HAttribute::
733remove(const Hid& loc_id, const String& var)
734{
735 ARCANE_HDF5_MUTEX;
736 _setId(H5Adelete(loc_id.id(), var.localstr()));
737}
738
739/*---------------------------------------------------------------------------*/
740/*---------------------------------------------------------------------------*/
741
742void HAttribute::
743create(const Hid& loc_id, const String& var, hid_t save_type, const HSpace& space_id)
744{
745 ARCANE_HDF5_MUTEX;
746 _setId(H5Acreate2(loc_id.id(), var.localstr(), save_type, space_id.id(), H5P_DEFAULT, H5P_DEFAULT));
747}
748
749/*---------------------------------------------------------------------------*/
750/*---------------------------------------------------------------------------*/
751
752void HAttribute::
753open(const Hid& loc_id, const String& var)
754{
755 ARCANE_HDF5_MUTEX;
756 _setId(H5Aopen_name(loc_id.id(), var.localstr()));
757}
758
759/*---------------------------------------------------------------------------*/
760/*---------------------------------------------------------------------------*/
761
762herr_t HAttribute::
763write(hid_t native_type, void* array)
764{
765 ARCANE_HDF5_MUTEX;
766 return H5Awrite(id(), native_type, array);
767}
768
769/*---------------------------------------------------------------------------*/
770/*---------------------------------------------------------------------------*/
771
772herr_t HAttribute::
773read(hid_t native_type, void* array)
774{
775 ARCANE_HDF5_MUTEX;
776 return H5Aread(id(), native_type, array);
777}
778
779/*---------------------------------------------------------------------------*/
780/*---------------------------------------------------------------------------*/
781
782HSpace HAttribute::
783getSpace()
784{
785 ARCANE_HDF5_MUTEX;
786 return HSpace(H5Aget_space(id()));
787}
788
789/*---------------------------------------------------------------------------*/
790/*---------------------------------------------------------------------------*/
791
792/*---------------------------------------------------------------------------*/
793/*---------------------------------------------------------------------------*/
794
795HType::
796~HType()
797{
798 if (id() > 0) {
799 ARCANE_HDF5_MUTEX;
800 H5Tclose(id());
801 }
802}
803
804/*---------------------------------------------------------------------------*/
805/*---------------------------------------------------------------------------*/
806
807/*---------------------------------------------------------------------------*/
808/*---------------------------------------------------------------------------*/
809
810void HDataset::
811open(const Hid& loc_id, const String& var)
812{
813 {
814 ARCANE_HDF5_MUTEX;
815 _setId(H5Dopen2(loc_id.id(), var.localstr(), H5P_DEFAULT));
816 }
817 if (isBad())
818 ARCANE_THROW(IOException, "Can not open dataset '{0}'", var);
819}
820
821/*---------------------------------------------------------------------------*/
822/*---------------------------------------------------------------------------*/
823
824void HDataset::
825openIfExists(const Hid& loc_id, const String& var)
826{
827 UniqueArray<String> paths;
828 splitString(var, paths, '/');
829 Integer nb_path = paths.size();
830 HGroup parent_group;
831 String last_name = var;
832 if (nb_path > 1) {
833 last_name = paths[nb_path - 1];
834 paths.resize(nb_path - 1);
835 parent_group.openIfExists(loc_id, paths);
836 }
837 else {
838 parent_group.open(loc_id, ".");
839 }
840 if (parent_group.isBad())
841 return;
842 if (parent_group.hasChildren(last_name))
843 open(loc_id.id(), var.localstr());
844}
845
846/*---------------------------------------------------------------------------*/
847/*---------------------------------------------------------------------------*/
848
849/*---------------------------------------------------------------------------*/
850/*---------------------------------------------------------------------------*/
851
852void HProperty::
853close()
854{
855 if (id() > 0) {
856 ARCANE_HDF5_MUTEX;
857 H5Pclose(id());
858 _setNullId();
859 }
860}
861
862/*---------------------------------------------------------------------------*/
863/*---------------------------------------------------------------------------*/
864
865void HProperty::
866create(hid_t cls_id)
867{
868 close();
869 ARCANE_HDF5_MUTEX;
870 _setId(H5Pcreate(cls_id));
871}
872
873/*---------------------------------------------------------------------------*/
874/*---------------------------------------------------------------------------*/
875
878{
879#ifdef H5_HAVE_PARALLEL
880 void* arcane_comm = pm->getMPICommunicator();
881 if (!arcane_comm)
882 ARCANE_FATAL("No MPI environment available");
883 MPI_Comm mpi_comm = *((MPI_Comm*)arcane_comm);
884 MPI_Info mpi_info = MPI_INFO_NULL;
885
886 create(H5P_FILE_ACCESS);
887 H5Pset_fapl_mpio(id(), mpi_comm, mpi_info);
888#else
889 ARCANE_UNUSED(pm);
890 ARCANE_THROW(NotSupportedException, "HDF5 is not compiled with MPI support");
891#endif
892}
893
894/*---------------------------------------------------------------------------*/
895/*---------------------------------------------------------------------------*/
896
899{
900#ifdef H5_HAVE_PARALLEL
901 create(H5P_DATASET_XFER);
902 H5Pset_dxpl_mpio(id(), H5FD_MPIO_COLLECTIVE);
903
904#if (H5_VERS_MAJOR >= 2 || H5_VERS_MINOR >= 14)
905 H5Pset_selection_io(id(), H5D_SELECTION_IO_MODE_OFF);
906#endif
907
908#else
909 ARCANE_THROW(NotSupportedException, "HDF5 is not compiled with MPI support");
910#endif
911}
912
913/*---------------------------------------------------------------------------*/
914/*---------------------------------------------------------------------------*/
915
918{
919#ifdef H5_HAVE_PARALLEL
920 create(H5P_DATASET_XFER);
921 H5Pset_dxpl_mpio(id(), H5FD_MPIO_INDEPENDENT);
922
923#if (H5_VERS_MAJOR >= 2 || H5_VERS_MINOR >= 14)
924 H5Pset_selection_io(id(), H5D_SELECTION_IO_MODE_OFF);
925#endif
926
927#else
928 ARCANE_THROW(NotSupportedException, "HDF5 is not compiled with MPI support");
929#endif
930}
931
932/*---------------------------------------------------------------------------*/
933/*---------------------------------------------------------------------------*/
934
935/*---------------------------------------------------------------------------*/
936/*---------------------------------------------------------------------------*/
937
943
944/*---------------------------------------------------------------------------*/
945/*---------------------------------------------------------------------------*/
946
948StandardTypes(bool do_init)
949{
950 if (do_init)
951 initialize();
952}
953
954/*---------------------------------------------------------------------------*/
955/*---------------------------------------------------------------------------*/
956
959{
960 ARCANE_HDF5_MUTEX;
961 {
962 hid_t type_id = H5Tcopy(H5T_NATIVE_CHAR);
963 m_char_id.setId(type_id);
964 }
965 {
966 hid_t type_id = H5Tcopy(H5T_NATIVE_UCHAR);
967 m_uchar_id.setId(type_id);
968 }
969 {
970 hid_t type_id = H5Tcopy(H5T_NATIVE_SCHAR);
971 m_schar_id.setId(type_id);
972 }
973 {
974 hid_t type_id = H5Tcopy(H5T_NATIVE_SHORT);
975 H5Tset_precision(type_id, 8 * sizeof(short));
976 H5Tset_order(type_id, H5T_ORDER_LE);
977 m_short_id.setId(type_id);
978 }
979 {
980 hid_t type_id = H5Tcopy(H5T_NATIVE_INT);
981 H5Tset_precision(type_id, 8 * sizeof(int));
982 H5Tset_order(type_id, H5T_ORDER_LE);
983 m_int_id.setId(type_id);
984 }
985 {
986 hid_t type_id = H5Tcopy(H5T_NATIVE_LONG);
987 H5Tset_precision(type_id, 8 * sizeof(long));
988 H5Tset_order(type_id, H5T_ORDER_LE);
989 m_long_id.setId(type_id);
990 }
991 {
992 hid_t type_id = H5Tcopy(H5T_NATIVE_USHORT);
993 H5Tset_precision(type_id, 8 * sizeof(unsigned short));
994 H5Tset_order(type_id, H5T_ORDER_LE);
995 m_ushort_id.setId(type_id);
996 }
997 {
998 hid_t type_id = H5Tcopy(H5T_NATIVE_UINT);
999 H5Tset_precision(type_id, 8 * sizeof(unsigned int));
1000 H5Tset_order(type_id, H5T_ORDER_LE);
1001 m_uint_id.setId(type_id);
1002 }
1003 {
1004 hid_t type_id = H5Tcopy(H5T_NATIVE_ULONG);
1005 H5Tset_precision(type_id, 8 * sizeof(unsigned long));
1006 H5Tset_order(type_id, H5T_ORDER_LE);
1007 m_ulong_id.setId(type_id);
1008 }
1009 {
1010 hid_t type_id = H5Tcopy(H5T_NATIVE_FLOAT);
1011 H5Tset_precision(type_id, 8 * sizeof(float));
1012 H5Tset_order(type_id, H5T_ORDER_LE);
1013 m_float32_id.setId(type_id);
1014 }
1015 {
1016 hid_t type_id = H5Tcopy(H5T_NATIVE_DOUBLE);
1017 H5Tset_precision(type_id, 8 * sizeof(double));
1018 H5Tset_order(type_id, H5T_ORDER_LE);
1019 m_real_id.setId(type_id);
1020 }
1021 {
1022 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real2POD));
1023 _H5Tinsert(type_id, "X", HOFFSET(Real2POD, x), H5T_NATIVE_DOUBLE);
1024 _H5Tinsert(type_id, "Y", HOFFSET(Real2POD, y), H5T_NATIVE_DOUBLE);
1025 m_real2_id.setId(type_id);
1026 }
1027 {
1028 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real3POD));
1029 _H5Tinsert(type_id, "X", HOFFSET(Real3POD, x), H5T_NATIVE_DOUBLE);
1030 _H5Tinsert(type_id, "Y", HOFFSET(Real3POD, y), H5T_NATIVE_DOUBLE);
1031 _H5Tinsert(type_id, "Z", HOFFSET(Real3POD, z), H5T_NATIVE_DOUBLE);
1032 m_real3_id.setId(type_id);
1033 }
1034 {
1035 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real2x2POD));
1036 _H5Tinsert(type_id, "XX", HOFFSET(Real2x2POD, x.x), H5T_NATIVE_DOUBLE);
1037 _H5Tinsert(type_id, "XY", HOFFSET(Real2x2POD, x.y), H5T_NATIVE_DOUBLE);
1038 _H5Tinsert(type_id, "YX", HOFFSET(Real2x2POD, y.x), H5T_NATIVE_DOUBLE);
1039 _H5Tinsert(type_id, "YY", HOFFSET(Real2x2POD, y.y), H5T_NATIVE_DOUBLE);
1040 m_real2x2_id.setId(type_id);
1041 }
1042 {
1043 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real3x3POD));
1044 _H5Tinsert(type_id, "XX", HOFFSET(Real3x3POD, x.x), H5T_NATIVE_DOUBLE);
1045 _H5Tinsert(type_id, "XY", HOFFSET(Real3x3POD, x.y), H5T_NATIVE_DOUBLE);
1046 _H5Tinsert(type_id, "XZ", HOFFSET(Real3x3POD, x.z), H5T_NATIVE_DOUBLE);
1047 _H5Tinsert(type_id, "YX", HOFFSET(Real3x3POD, y.x), H5T_NATIVE_DOUBLE);
1048 _H5Tinsert(type_id, "YY", HOFFSET(Real3x3POD, y.y), H5T_NATIVE_DOUBLE);
1049 _H5Tinsert(type_id, "YZ", HOFFSET(Real3x3POD, y.z), H5T_NATIVE_DOUBLE);
1050 _H5Tinsert(type_id, "ZX", HOFFSET(Real3x3POD, z.x), H5T_NATIVE_DOUBLE);
1051 _H5Tinsert(type_id, "ZY", HOFFSET(Real3x3POD, z.y), H5T_NATIVE_DOUBLE);
1052 _H5Tinsert(type_id, "ZZ", HOFFSET(Real3x3POD, z.z), H5T_NATIVE_DOUBLE);
1053 m_real3x3_id.setId(type_id);
1054 }
1055
1056 // HDF5 1.10 et 1.12 ne supportent pas encore les types 'BFloat16' et 'Float16'.
1057 // Lorsque ce sera le cas, on pourra utiliser le type fourni par HDF5.
1058 // (NOTE: HDF5 1.14.4 supporte Float16)
1059
1060 // Ajoute type opaque pour BFloat16.
1061 {
1062 hid_t type_id = H5Tcopy(H5T_NATIVE_B16);
1063 m_bfloat16_id.setId(type_id);
1064 }
1065 // Ajoute type opaque pour Float16.
1066 {
1067 hid_t type_id = H5Tcopy(H5T_NATIVE_B16);
1068 m_float16_id.setId(type_id);
1069 }
1070}
1071
1072/*---------------------------------------------------------------------------*/
1073/*---------------------------------------------------------------------------*/
1074
1075StandardTypes::
1076~StandardTypes()
1077{
1078}
1079
1080/*---------------------------------------------------------------------------*/
1081/*---------------------------------------------------------------------------*/
1082
1083void StandardTypes::
1084_H5Tinsert(hid_t type, const char* name, Integer offset, hid_t field_id)
1085{
1086 // Mutex géré par initialize.
1087 herr_t herr = H5Tinsert(type, name, offset, field_id);
1088 if (herr < 0) {
1089 ARCANE_FATAL("Can not insert type");
1090 }
1091}
1092/*---------------------------------------------------------------------------*/
1093/*---------------------------------------------------------------------------*/
1094
1095#ifdef ARCANE_REAL_NOT_BUILTIN
1096hid_t StandardTypes::
1097nativeType(Real) const
1098{
1099 ARCANE_FATAL("Real is a complex type");
1100}
1101#endif
1102
1103hid_t StandardTypes::
1104saveType(eDataType sd) const
1105{
1106 switch (sd) {
1107 case DT_Byte:
1108 return saveType(Byte());
1109 case DT_Real:
1110 return saveType(Real());
1111 case DT_Real2:
1112 return saveType(Real2());
1113 case DT_Real2x2:
1114 return saveType(Real2x2());
1115 case DT_Real3:
1116 return saveType(Real3());
1117 case DT_Real3x3:
1118 return saveType(Real3x3());
1119 case DT_Int8:
1120 return saveType(Int8());
1121 case DT_Int16:
1122 return saveType(Int16());
1123 case DT_Int32:
1124 return saveType(Int32());
1125 case DT_Int64:
1126 return saveType(Int64());
1127 case DT_Float32:
1128 return saveType(Float32());
1129 case DT_Float16:
1130 return saveType(Float16());
1131 case DT_BFloat16:
1132 return saveType(BFloat16());
1133 default:
1134 throw ArgumentException(String::format("Bad type '{0}'", sd));
1135 }
1136}
1137
1138/*---------------------------------------------------------------------------*/
1139/*---------------------------------------------------------------------------*/
1140
1141hid_t StandardTypes::
1142nativeType(eDataType sd) const
1143{
1144 switch (sd) {
1145 case DT_Byte:
1146 return nativeType(Byte());
1147 case DT_Real:
1148 return nativeType(Real());
1149 case DT_Real2:
1150 return nativeType(Real2());
1151 case DT_Real2x2:
1152 return nativeType(Real2x2());
1153 case DT_Real3:
1154 return nativeType(Real3());
1155 case DT_Real3x3:
1156 return nativeType(Real3x3());
1157 case DT_Int8:
1158 return nativeType(Int8());
1159 case DT_Int16:
1160 return nativeType(Int16());
1161 case DT_Int32:
1162 return nativeType(Int32());
1163 case DT_Int64:
1164 return nativeType(Int64());
1165 case DT_Float32:
1166 return nativeType(Float32());
1167 case DT_Float16:
1168 return nativeType(Float16());
1169 case DT_BFloat16:
1170 return nativeType(BFloat16());
1171 default:
1172 throw ArgumentException(String::format("Bad type '{0}'", sd));
1173 }
1174}
1175
1176/*---------------------------------------------------------------------------*/
1177/*---------------------------------------------------------------------------*/
1178
1179/*---------------------------------------------------------------------------*/
1180/*---------------------------------------------------------------------------*/
1181
1182StandardArray::
1183StandardArray(hid_t hfile, const String& hpath)
1184: m_hfile(hfile)
1185, m_hpath(hpath)
1186, m_ids_hpath(hpath + "_Ids")
1187, m_is_init(false)
1188{
1189}
1190
1191/*---------------------------------------------------------------------------*/
1192/*---------------------------------------------------------------------------*/
1193
1194void StandardArray::
1195readDim()
1196{
1197 if (m_is_init)
1198 return;
1199 m_is_init = true;
1200 m_hdataset.open(m_hfile, m_hpath);
1201 HSpace hspace(m_hdataset.getSpace());
1202 {
1203 const int max_dim = 256; // Nombre maxi de dimensions des tableaux HDF
1204 hsize_t hdf_dims[max_dim];
1205 hsize_t max_dims[max_dim];
1206 int nb_dim = -1;
1207 {
1208 ARCANE_HDF5_MUTEX;
1209 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1210 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1211 }
1212 for (Integer i = 0; i < nb_dim; ++i) {
1213 //cerr << "** DIM i=" << i << " hdim=" << hdf_dims[i]
1214 // << " max=" << max_dims[i] << '\n';
1215 m_dimensions.add((Int64)hdf_dims[i]);
1216 }
1217 }
1218 // Vérifie s'il existe une variable suffixée '_Ids' contenant les numéros
1219 // uniques des entités
1220 m_ids_dataset.openIfExists(m_hfile, m_ids_hpath);
1221 //cout << "TRY OPEN ID DATASET path=" << m_ids_hpath << " r=" << m_ids_dataset.id()>0 << '\n';
1222}
1223
1224/*---------------------------------------------------------------------------*/
1225/*---------------------------------------------------------------------------*/
1226
1228setIdsPath(const String& ids_path)
1229{
1230 m_ids_hpath = ids_path;
1231}
1232
1233/*---------------------------------------------------------------------------*/
1234/*---------------------------------------------------------------------------*/
1235
1236void StandardArray::
1237_write(const void* buffer, Integer nb_element, hid_t save_type, hid_t native_type)
1238{
1239 if (!m_is_init) {
1240 hsize_t dims[1];
1241 dims[0] = nb_element;
1242
1243 HSpace hspace;
1244 hspace.createSimple(1, dims);
1245 if (hspace.isBad())
1246 ARCANE_THROW(IOException, "Can not create space");
1247
1248 m_dimensions.clear();
1249 m_dimensions.add(nb_element);
1250
1251 m_hdataset.recursiveCreate(m_hfile, m_hpath, save_type, hspace, H5P_DEFAULT);
1252 if (m_hdataset.isBad())
1253 ARCANE_THROW(IOException, "Can not create dataset");
1254
1255 m_is_init = true;
1256 }
1257
1258 m_hdataset.write(native_type, buffer);
1259}
1260
1261/*---------------------------------------------------------------------------*/
1262/*---------------------------------------------------------------------------*/
1263
1264bool StandardArray::
1265exists() const
1266{
1267 HDataset dataset;
1268 dataset.openIfExists(m_hfile, m_hpath);
1269 return dataset.id() > 0;
1270}
1271
1272/*---------------------------------------------------------------------------*/
1273/*---------------------------------------------------------------------------*/
1274
1275template <typename DataType> StandardArrayT<DataType>::
1276StandardArrayT(hid_t hfile, const String& hpath)
1277: StandardArray(hfile, hpath)
1278{
1279}
1280
1281/*---------------------------------------------------------------------------*/
1282/*---------------------------------------------------------------------------*/
1283
1284template <typename DataType> void StandardArrayT<DataType>::
1286{
1287 m_hdataset.readWithException(st.nativeType(DataType()), buffer.data());
1288}
1289
1290/*---------------------------------------------------------------------------*/
1291/*---------------------------------------------------------------------------*/
1292
1293template <typename DataType> void StandardArrayT<DataType>::
1295{
1296 readDim();
1297 buffer.resize(m_dimensions[0]);
1298 read(st, buffer);
1299}
1300
1301/*---------------------------------------------------------------------------*/
1302/*---------------------------------------------------------------------------*/
1303
1304template <typename DataType> void StandardArrayT<DataType>::
1306{
1307 bool is_master = pm->isMasterIO();
1308 Integer master_rank = pm->masterIORank();
1309 bool has_ids = false;
1310 if (is_master) {
1311 read(st, buffer);
1312 Integer buf_size = buffer.size();
1313 if (m_ids_dataset.id() > 0) {
1314 has_ids = true;
1315 m_ids_dataset.read(st.nativeType(Int64()), unique_ids.data());
1316 }
1317 Integer infos[2];
1318 infos[0] = buf_size;
1319 infos[1] = has_ids ? 1 : 0;
1320 IntegerArrayView iav(2, infos);
1321 pm->broadcast(iav, master_rank);
1322 pm->broadcast(buffer, master_rank);
1323 pm->broadcast(unique_ids, master_rank);
1324 }
1325 else {
1326 Integer infos[2];
1327 IntegerArrayView iav(2, infos);
1328 pm->broadcast(iav, master_rank);
1329 Integer buf_size = infos[0];
1330 has_ids = infos[1] != 0;
1331 buffer.resize(buf_size);
1332 unique_ids.resize(buf_size);
1333 pm->broadcast(buffer, master_rank);
1334 pm->broadcast(unique_ids, master_rank);
1335 }
1336 if (!has_ids) {
1337 for (Integer i = 0, is = unique_ids.size(); i < is; ++i)
1338 unique_ids[i] = i;
1339 }
1340}
1341
1342/*---------------------------------------------------------------------------*/
1343/*---------------------------------------------------------------------------*/
1344
1345template <typename DataType> void StandardArrayT<DataType>::
1346write(StandardTypes& st, ConstArrayView<DataType> buffer)
1347{
1348 Integer nb_element = buffer.size();
1349 _write(buffer.data(), nb_element, st.saveType(DataType()), st.nativeType(DataType()));
1350}
1351
1352/*---------------------------------------------------------------------------*/
1353/*---------------------------------------------------------------------------*/
1354
1355template <typename DataType> void StandardArrayT<DataType>::
1356_writeSortedValues(ITraceMng* tm, StandardTypes& st,
1357 ConstArrayView<DataType> buffer,
1358 Int64ConstArrayView unique_ids)
1359{
1360 ARCANE_UNUSED(tm);
1361
1362 Integer total_size = buffer.size();
1363 Integer nb_element = unique_ids.size();
1364 Integer dim2_size = 1;
1365 if (nb_element != total_size) {
1366 if (nb_element == 0)
1367 ARCANE_THROW(ArgumentException, "unique_ids size is zero but not buffer size ({0})",
1368 total_size);
1369 dim2_size = total_size / nb_element;
1370 if (dim2_size * nb_element != total_size)
1371 ARCANE_THROW(ArgumentException, "buffer size ({0}) is not a multiple of unique_ids size ({1})",
1372 total_size, nb_element);
1373 }
1374
1375 UniqueArray<ValueWithUid> values_to_sort(nb_element);
1376 UniqueArray<DataType> out_buffer(total_size);
1377 //tm->info() << " WRITE total_size=" << total_size
1378 //<< " uid_size=" << unique_ids.size();
1379 for (Integer i = 0; i < nb_element; ++i) {
1380 values_to_sort[i].m_uid = unique_ids[i];
1381 values_to_sort[i].m_index = i;
1382 //values_to_sort[i].m_value = buffer[i];
1383 //tm->info() << "BEFORE SORT i=" << i << " uid=" << unique_ids[i];
1384 }
1385 std::sort(std::begin(values_to_sort), std::end(values_to_sort));
1386 for (Integer i = 0; i < nb_element; ++i) {
1387 Integer old_index = values_to_sort[i].m_index;
1388 for (Integer j = 0; j < dim2_size; ++j) {
1389 Integer pos = (i * dim2_size) + j;
1390 out_buffer[pos] = buffer[(old_index * dim2_size) + j];
1391 //tm->info() << "AFTER SORT i=" << i << " uid=" << values_to_sort[i].m_uid
1392 // << " j=" << j << " pos=" << pos
1393 // << " value=" << out_buffer[pos];
1394 }
1395 }
1396 write(st, out_buffer);
1397}
1398
1399/*---------------------------------------------------------------------------*/
1400/*---------------------------------------------------------------------------*/
1401
1402template <typename DataType> void StandardArrayT<DataType>::
1403parallelWrite(IParallelMng* pm, StandardTypes& st,
1404 ConstArrayView<DataType> buffer, Int64ConstArrayView unique_ids)
1405{
1406 //TODO:
1407 // Pour l'instant, seul le proc maitre ecrit.
1408 // Il recupère toutes les valeurs, les trie par uniqueId croissant
1409 // et les écrit.
1410 // Il est important que tout soit trié par ordre croissant car
1411 // cela permet de garder le même ordre d'écriture même en présence
1412 // de repartitionnement du maillage. La relecture considère
1413 // que cette contrainte est respectée et ne relit les informations
1414 // des uniqueId qu'au démarrage du cas.
1415 bool is_parallel = pm->isParallel();
1416 ITraceMng* tm = pm->traceMng();
1417
1418 if (!is_parallel) {
1419 _writeSortedValues(tm, st, buffer, unique_ids);
1420 return;
1421 }
1422
1423 bool is_master = pm->isMasterIO();
1424 Integer master_rank = pm->masterIORank();
1425 Integer nb_rank = pm->commSize();
1426 Integer buf_size = buffer.size();
1427 Integer unique_id_size = unique_ids.size();
1428 IntegerUniqueArray rank_sizes(2 * nb_rank);
1429 // Le sous-domaine maitre récupère les infos de tous les autres.
1430 // Si un sous-domaine n'a pas d'éléments à envoyer, il ne fait rien
1431 // (on n'envoie pas de buffers vides)
1432 if (is_master) {
1433 Integer buf[2];
1434 buf[0] = buf_size;
1435 buf[1] = unique_id_size;
1436 IntegerArrayView iav(2, buf);
1437 pm->allGather(iav, rank_sizes);
1438
1439 Integer buffer_total_size = 0;
1440 Integer unique_id_total_size = 0;
1441 IntegerUniqueArray buffer_rank_index(nb_rank);
1442 IntegerUniqueArray unique_id_rank_index(nb_rank);
1443
1444 for (Integer i = 0; i < nb_rank; ++i) {
1445 buffer_rank_index[i] = buffer_total_size;
1446 buffer_total_size += rank_sizes[(i * 2)];
1447 unique_id_rank_index[i] = unique_id_total_size;
1448 unique_id_total_size += rank_sizes[(i * 2) + 1];
1449 }
1450
1451 UniqueArray<DataType> full_buffer(buffer_total_size);
1452 Int64UniqueArray full_unique_ids(unique_id_total_size);
1453
1454 for (Integer i = 0; i < nb_rank; ++i) {
1455 // Ne recoit pas de valeurs des processus n'ayant pas de valeurs
1456 if (rank_sizes[(i * 2)] == 0)
1457 continue;
1458 ArrayView<DataType> local_buf(rank_sizes[(i * 2)], &full_buffer[buffer_rank_index[i]]);
1459 Int64ArrayView local_unique_ids(rank_sizes[(i * 2) + 1], &full_unique_ids[unique_id_rank_index[i]]);
1460 if (i == master_rank) {
1461 local_buf.copy(buffer);
1462 local_unique_ids.copy(unique_ids);
1463 }
1464 else {
1465 pm->recv(local_buf, i);
1466 pm->recv(local_unique_ids, i);
1467 }
1468 }
1469 tm->info(5) << "PARALLEL WRITE path=" << m_hpath << " total_size=" << full_buffer.size();
1470 _writeSortedValues(tm, st, full_buffer, full_unique_ids);
1471 }
1472 else {
1473 Integer buf[2];
1474 buf[0] = buf_size;
1475 buf[1] = unique_id_size;
1476 IntegerArrayView iav(2, buf);
1477 pm->allGather(iav, rank_sizes);
1478 // Pas la peine d'envoyer des buffers vides
1479 if (buffer.size() > 0) {
1480 pm->send(buffer, master_rank);
1481 pm->send(unique_ids, master_rank);
1482 }
1483 }
1484}
1485
1486/*---------------------------------------------------------------------------*/
1487/*---------------------------------------------------------------------------*/
1488
1489template class StandardArrayT<Real>;
1490template class StandardArrayT<Real3>;
1491template class StandardArrayT<Real3x3>;
1492template class StandardArrayT<Real2>;
1493template class StandardArrayT<Real2x2>;
1494template class StandardArrayT<Int16>;
1495template class StandardArrayT<Int32>;
1496template class StandardArrayT<Int64>;
1497template class StandardArrayT<Byte>;
1498template class StandardArrayT<Int8>;
1499template class StandardArrayT<Float32>;
1500// NOTE: on ne peut pas encore instantier ces types car ils nécessitent
1501// de pouvoir faire des send/receive via le IParallelMng et cela n'est pas
1502// encore implémenté.
1503//template class StandardArrayT<Float16>;
1504//template class StandardArrayT<BFloat16>;
1505
1506/*---------------------------------------------------------------------------*/
1507/*---------------------------------------------------------------------------*/
1508
1509template <typename DataType> DataType
1512{
1513 Hdf5Utils::HDataset m_hdataset;
1514 m_hdataset.open(m_hfile, m_hpath);
1515 Hdf5Utils::HSpace hspace(m_hdataset.getSpace());
1516 {
1517 const int max_dim = 256; // Nombre maxi de dimensions des tableaux HDF
1518 hsize_t hdf_dims[max_dim];
1519 hsize_t max_dims[max_dim];
1520 int nb_dim = -1;
1521 {
1522 ARCANE_HDF5_MUTEX;
1523 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1524 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1525 }
1526 if (nb_dim != 1 || hdf_dims[0] != 1)
1527 ARCANE_THROW(IOException, "Cannot read non scalar");
1528 }
1529
1530 DataType dummy;
1531 m_hdataset.read(st.nativeType(DataType()), &dummy);
1532 return dummy;
1533}
1534
1535/*---------------------------------------------------------------------------*/
1536
1537template <> String
1540{
1541 ByteUniqueArray utf8_bytes;
1542
1543 Hdf5Utils::HDataset m_hdataset;
1544 m_hdataset.open(m_hfile, m_hpath);
1545 Hdf5Utils::HSpace hspace(m_hdataset.getSpace());
1546 {
1547 const int max_dim = 256; // Nombre maxi de dimensions des tableaux HDF
1548 hsize_t hdf_dims[max_dim];
1549 hsize_t max_dims[max_dim];
1550 int nb_dim = -1;
1551 {
1552 ARCANE_HDF5_MUTEX;
1553 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1554 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1555 }
1556
1557 if (nb_dim != 1)
1558 ARCANE_THROW(IOException, "Cannot read multidim string");
1559 utf8_bytes.resize(hdf_dims[0]);
1560 }
1561
1562 m_hdataset.read(st.nativeType(Byte()), utf8_bytes.data());
1563 return String(utf8_bytes);
1564}
1565
1566/*---------------------------------------------------------------------------*/
1567
1568template <typename DataType> void
1570write(Hdf5Utils::StandardTypes& st, const DataType& t)
1571{
1572 hsize_t dims[1] = { 1 };
1573 Hdf5Utils::HSpace hspace;
1574 hspace.createSimple(1, dims);
1575 if (hspace.isBad())
1576 ARCANE_THROW(IOException, "Can not create space");
1577
1578 Hdf5Utils::HDataset m_hdataset;
1579 m_hdataset.recursiveCreate(m_hfile, m_hpath, st.saveType(DataType()), hspace, H5P_DEFAULT);
1580 if (m_hdataset.isBad())
1581 ARCANE_THROW(IOException, "Can not create dataset");
1582
1583 herr_t herr = m_hdataset.write(st.nativeType(DataType()), &t);
1584 if (herr < 0)
1585 ARCANE_THROW(IOException, "Cannot write data");
1586}
1587
1588/*---------------------------------------------------------------------------*/
1589
1590template <> void
1593{
1594 ByteConstArrayView utf8_bytes = s.utf8();
1595
1596 hsize_t dims[1];
1597 dims[0] = utf8_bytes.size() + 1;
1598
1599 Hdf5Utils::HSpace hspace;
1600 hspace.createSimple(1, dims);
1601 if (hspace.isBad())
1602 ARCANE_THROW(IOException, "Can not create space");
1603
1604 Hdf5Utils::HDataset m_hdataset;
1605 m_hdataset.recursiveCreate(m_hfile, m_hpath, st.saveType(Byte()), hspace, H5P_DEFAULT);
1606 if (m_hdataset.isBad())
1607 ARCANE_THROW(IOException, "Can not create dataset");
1608
1609 herr_t herr = m_hdataset.write(st.nativeType(Byte()), utf8_bytes.data());
1610 if (herr < 0)
1611 ARCANE_THROW(IOException, "Cannot write data");
1612}
1613
1614/*---------------------------------------------------------------------------*/
1615
1616template class StandardScalarT<String>;
1617template class StandardScalarT<Real>;
1618template class StandardScalarT<Real3>;
1619template class StandardScalarT<Real3x3>;
1620template class StandardScalarT<Real2>;
1621template class StandardScalarT<Real2x2>;
1622template class StandardScalarT<Int16>;
1623template class StandardScalarT<Int32>;
1624template class StandardScalarT<Int64>;
1625template class StandardScalarT<Byte>;
1626template class StandardScalarT<Int8>;
1627template class StandardScalarT<Float16>;
1628template class StandardScalarT<BFloat16>;
1629template class StandardScalarT<Float32>;
1630
1631/*---------------------------------------------------------------------------*/
1632/*---------------------------------------------------------------------------*/
1633
1634} // namespace Arcane::Hdf5Utils
1635
1636/*---------------------------------------------------------------------------*/
1637/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
constexpr const_pointer data() const noexcept
Pointeur sur le début de la vue.
Tableau d'items de types quelconques.
void clear()
Supprime les éléments du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
const T * data() const
Accès à la racine du tableau hors toute protection.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Classe template pour convertir un type.
Encapsule un hid_t pour un dataset.
Classe d'aide pour rechercher un groupe.
static void useMutex(bool is_active, IParallelMng *pm)
Fonction permettant d'activer ou de désactiver les verrous à chaque appel à HDF5.
Definition Hdf5Utils.cc:91
Encapsule un hid_t pour une propriété (H5P*).
void createDatasetTransfertCollectiveMPIIO()
Créé une propriété de dataset pour MPIIO.
Definition Hdf5Utils.cc:898
void createFilePropertyMPIIO(IParallelMng *pm)
Créé une propriété de fichier pour MPIIO.
Definition Hdf5Utils.cc:877
void createDatasetTransfertIndependentMPIIO()
Créé une propriété de dataset pour MPIIO.
Definition Hdf5Utils.cc:917
Encapsule un hid_t pour un dataspace.
Encapsule un hid_t.
Encapsule un dataset simple d'un fichier HDF5 qui représente un tableau.
void read(StandardTypes &st, ArrayView< DataType > buffer)
Lit le dataset d'un tableau 1D. Cette opération n'est valide qu'après un appel à readDim()....
void directRead(StandardTypes &st, Array< DataType > &buffer)
Lit le dataset d'un tableau 1D.
Encapsule un dataset simple d'un fichier HDF5 qui représente un tableau.
void setIdsPath(const String &ids_path)
En lecture, positionne le chemin dans hfile du dataset contenant les unique_ids.
Encapsule un dataset simple d'un fichier HDF5 qui représente un scalaire (éventuellement String).
DataType read(Hdf5Utils::StandardTypes &st)
Lit une donnée.
void write(Hdf5Utils::StandardTypes &st, const DataType &t)
Ecrit une donnée.
Définition des types standards Arcane pour hdf5.
HType m_bfloat16_id
Identifiant HDF pour les BFloat16.
HType m_real2x2_id
Identifiant HDF pour les Real2x2.
StandardTypes()
Créé une instance en initialisant les types.
Definition Hdf5Utils.cc:939
HType m_long_id
Identifiant HDF des entiers long signés.
HType m_int_id
Identifiant HDF des entiers signés.
HType m_short_id
Identifiant HDF des entiers signés.
HType m_real3x3_id
Identifiant HDF pour les Real3x3.
HType m_real_id
Identifiant HDF des réels.
HType m_ushort_id
Identifiant HDF des entiers long signés.
HType m_ulong_id
Identifiant HDF des entiers long non signés.
HType m_schar_id
Identifiant HDF des caractères signés.
HType m_uchar_id
Identifiant HDF des caractères non-signés.
HType m_real2_id
Identifiant HDF pour les Real2.
HType m_float32_id
Identifiant HDF pour les Float16.
HType m_float16_id
Identifiant HDF pour les Float16.
HType m_char_id
Identifiant HDF des charactères.
void initialize()
Initialise les types.
Definition Hdf5Utils.cc:958
HType m_uint_id
Identifiant HDF des entiers non signés.
HType m_real3_id
Identifiant HDF pour les Real3.
Exception lorsqu'une erreur d'entrée/sortie est détectée.
Definition IOException.h:32
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual bool isMasterIO() const =0
true si l'instance est un gestionnaire maître des entrées/sorties.
virtual Integer masterIORank() const =0
Rang de l'instance gérant les entrées/sorties (pour laquelle isMasterIO() est vrai).
virtual void * getMPICommunicator()=0
Adresse du communicateur MPI associé à ce gestionnaire.
Exception lorsqu'une opération n'est pas supportée.
Chaîne de caractères unicode.
ByteConstArrayView utf8() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:276
Integer len(const char *s)
Retourne la longueur de la chaîne s.
Fonctions utilitaires pour Hdf5.
Definition Hdf5Utils.cc:35
std::int8_t Int8
Type entier signé sur 8 bits.
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:119
ArrayView< Int64 > Int64ArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:449
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:337
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ArrayView< Integer > IntegerArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:455
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:478
UniqueArray< Byte > ByteUniqueArray
Tableau dynamique à une dimension de caractères.
Definition UtilsTypes.h:333
std::int16_t Int16
Type entier signé sur 16 bits.
double Real
Type représentant un réel.
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:474
unsigned char Byte
Type d'un octet.
Definition BaseTypes.h:42
float Float32
Type flottant IEEE-753 simple précision.
eDataType
Type d'une donnée.
Definition DataTypes.h:39
@ DT_Float32
Donnée de type 'Float32'.
Definition DataTypes.h:52
@ DT_Real2x2
Donnée de type tenseur 3x3.
Definition DataTypes.h:48
@ DT_Int16
Donnée de type entier 16 bits.
Definition DataTypes.h:42
@ DT_Int8
Donnée de type entier sur 8 bits.
Definition DataTypes.h:53
@ DT_Real3x3
Donnée de type tenseur 3x3.
Definition DataTypes.h:49
@ DT_Int32
Donnée de type entier 32 bits.
Definition DataTypes.h:43
@ DT_Real3
Donnée de type vecteur 3.
Definition DataTypes.h:47
@ DT_Float16
Donnée de type 'Float16'.
Definition DataTypes.h:51
@ DT_Int64
Donnée de type entier 64 bits.
Definition DataTypes.h:44
@ DT_BFloat16
Donnée de type 'BFloat16'.
Definition DataTypes.h:50
@ DT_Real2
Donnée de type vecteur 2.
Definition DataTypes.h:46
@ DT_Real
Donnée de type réel.
Definition DataTypes.h:41
@ DT_Byte
Donnée de type octet.
Definition DataTypes.h:40
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:345
std::int32_t Int32
Type entier signé sur 32 bits.
Arcane::BFloat16 BFloat16
Type 'Brain Float16'.
Structure POD pour un Real2x2.
Structure POD pour un Real3x3.