Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
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/* HDF5 Utilities. */
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
23#include "arcane/core/ArcaneException.h"
24#include "arcane/core/IParallelMng.h"
25
26#include "arcane/hdf5/Hdf5Utils.h"
27
28#include <algorithm>
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39namespace
40{
41 std::once_flag h5open_once_flag;
42
43#if (defined(H5_HAVE_THREADSAFE) || defined(H5_HAVE_CONCURRENCY))
44 bool global_hdf5_mutex_is_active = false;
45#else
46 bool global_hdf5_mutex_is_active = true;
47#endif
48
49 std::mutex global_hdf5_mutex;
50 Hdf5Mutex hdf5_mutex(global_hdf5_mutex, global_hdf5_mutex_is_active);
51
52#if (defined(H5_HAVE_THREADSAFE) || defined(H5_HAVE_CONCURRENCY))
53#define ARCANE_HDF5_MUTEX
54#else
55 struct ScopedMutex
56 {
57 ScopedMutex()
58 {
59 hdf5_mutex.lock();
60 }
61 ~ScopedMutex()
62 {
63 hdf5_mutex.unlock();
64 }
65 };
66#define ARCANE_HDF5_MUTEX ScopedMutex scoped_mutex
67#endif
68} // namespace
69
70Hdf5Mutex& _ArcaneHdf5UtilsMutex()
71{
72 return hdf5_mutex;
73}
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
77
78HInit::
79HInit()
80{
81 // Ensure this is called only once and protects against concurrent calls.
82 std::call_once(h5open_once_flag, []() { H5open(); });
83}
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
89useMutex([[maybe_unused]] bool is_active, [[maybe_unused]] IParallelMng* pm)
90{
91#if (defined(H5_HAVE_THREADSAFE) || defined(H5_HAVE_CONCURRENCY))
92 pm->traceMng()->info(4) << "HDF5 -- Is HDF5 threadsafe: 1 -- Is Mutex enabled: " << global_hdf5_mutex_is_active;
93#else
94 bool env_is_enable = true;
95 if (const auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_HDF5_DISABLE_MUTEX", true)) {
96 env_is_enable = (v.value() == 0);
97 }
98 pm->barrier();
99 global_hdf5_mutex.lock();
100 global_hdf5_mutex_is_active = env_is_enable && is_active;
101 global_hdf5_mutex.unlock();
102 pm->barrier();
103 pm->traceMng()->info(4) << "HDF5 -- Is HDF5 threadsafe: 0 -- Is Mutex enabled: " << global_hdf5_mutex_is_active;
104#endif
105}
106
107/*---------------------------------------------------------------------------*/
108/*---------------------------------------------------------------------------*/
109
110namespace
111{
112
113 hid_t _H5Gopen(hid_t loc_id, const char* name)
114 {
115 return H5Gopen2(loc_id, name, H5P_DEFAULT);
116 }
117
118 hid_t _H5Gcreate(hid_t loc_id, const char* name)
119 {
120 return H5Gcreate2(loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
121 }
122
123} // namespace
124/*---------------------------------------------------------------------------*/
125/*---------------------------------------------------------------------------*/
126
127extern "C" ARCANE_HDF5_EXPORT herr_t
128_ArcaneHdf5UtilsGroupIterateMe(hid_t g, const char* mn, void* ptr)
129{
130 ARCANE_UNUSED(g);
131 HGroupSearch* rw = reinterpret_cast<HGroupSearch*>(ptr);
132 return rw->iterateMe(mn);
133}
134
135/*---------------------------------------------------------------------------*/
136/*---------------------------------------------------------------------------*/
137
138void splitString(const String& str, Array<String>& str_array, char c)
139{
140 const char* str_str = str.localstr();
141 Int64 offset = 0;
142 Int64 len = str.length();
143 for (Int64 i = 0; i < len; ++i) {
144 if (str_str[i] == c && i != offset) {
145 str_array.add(std::string_view(str_str + offset, i - offset));
146 offset = i + 1;
147 }
148 }
149 if (len != offset)
150 str_array.add(std::string_view(str_str + offset, len - offset));
151}
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
156void HFile::
157openTruncate(const String& var)
158{
159 close();
160 {
161 ARCANE_HDF5_MUTEX;
162 _setId(H5Fcreate(var.localstr(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT));
163 }
164 if (isBad())
165 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
166}
167
168void HFile::
169openAppend(const String& var)
170{
171 close();
172 {
173 ARCANE_HDF5_MUTEX;
174 _setId(H5Fopen(var.localstr(), H5F_ACC_RDWR, H5P_DEFAULT));
175 }
176 if (isBad())
177 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
178}
179
180void HFile::
181openRead(const String& var)
182{
183 close();
184 {
185 ARCANE_HDF5_MUTEX;
186 _setId(H5Fopen(var.localstr(), H5F_ACC_RDONLY, H5P_DEFAULT));
187 }
188 if (isBad())
189 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
190}
191
192void HFile::
193openTruncate(const String& var, hid_t plist_id)
194{
195 close();
196 {
197 ARCANE_HDF5_MUTEX;
198 _setId(H5Fcreate(var.localstr(), H5F_ACC_TRUNC, H5P_DEFAULT, plist_id));
199 }
200 if (isBad())
201 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
202}
203
204void HFile::
205openAppend(const String& var, hid_t plist_id)
206{
207 close();
208 {
209 ARCANE_HDF5_MUTEX;
210 _setId(H5Fopen(var.localstr(), H5F_ACC_RDWR, plist_id));
211 }
212 if (isBad())
213 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
214}
215
216void HFile::
217openRead(const String& var, hid_t plist_id)
218{
219 close();
220 {
221 ARCANE_HDF5_MUTEX;
222 _setId(H5Fopen(var.localstr(), H5F_ACC_RDONLY, plist_id));
223 }
224 if (isBad())
225 ARCANE_THROW(ReaderWriterException, "Can not open file '{0}'", var);
226}
227
228/*---------------------------------------------------------------------------*/
229/*---------------------------------------------------------------------------*/
230
231herr_t HFile::
232_close()
233{
234 herr_t e = 0;
235 if (id() > 0) {
236 ARCANE_HDF5_MUTEX;
237 e = H5Fclose(id());
238 _setNullId();
239 }
240 return e;
241}
242
243/*---------------------------------------------------------------------------*/
244/*---------------------------------------------------------------------------*/
245
246void HFile::
247close()
248{
249 herr_t e = _close();
250 if (e < 0)
251 ARCANE_THROW(ReaderWriterException, "Can not close file");
252}
253
254/*---------------------------------------------------------------------------*/
255/*---------------------------------------------------------------------------*/
256
257void HGroup::
258recursiveCreate(const Hid& loc_id, const String& var)
259{
260 UniqueArray<String> bufs;
261 splitString(var, bufs, '/');
262 recursiveCreate(loc_id, bufs);
263}
264
265void HGroup::
266recursiveCreate(const Hid& loc_id, const Array<String>& bufs)
267{
268 close();
269 hid_t last_hid = loc_id.id();
270 Integer nb_create = bufs.size();
271 UniqueArray<hid_t> ref_ids(nb_create);
272 for (Integer i = 0; i < nb_create; ++i) {
273 last_hid = _checkOrCreate(last_hid, bufs[i]);
274 ref_ids[i] = last_hid;
275 }
276 // Release all intermediate created groups
277 ARCANE_HDF5_MUTEX;
278 for (Integer i = 0; i < nb_create - 1; ++i) {
279 H5Gclose(ref_ids[i]);
280 }
281 _setId(last_hid);
282}
283
284/*---------------------------------------------------------------------------*/
285/*---------------------------------------------------------------------------*/
286
287void HGroup::
288checkDelete(const Hid& loc_id, const String& var)
289{
290 UniqueArray<String> bufs;
291 splitString(var, bufs, '/');
292 hid_t last_hid = loc_id.id();
293 hid_t parent_hid = last_hid;
294 Integer i = 0;
295 Integer size = bufs.size();
296 for (; i < size; ++i) {
297 parent_hid = last_hid;
298 last_hid = _checkExist(last_hid, bufs[i]);
299 if (last_hid == 0)
300 break;
301 }
302 // Group found, we delete it.
303 if (last_hid > 0 && parent_hid > 0 && i == size) {
304 //cerr << "** DELETE <" << bufs[size-1] << "\n";
305 ARCANE_HDF5_MUTEX;
306 H5Gunlink(parent_hid, bufs[size - 1].localstr());
307 }
308}
309
310/*---------------------------------------------------------------------------*/
311/*---------------------------------------------------------------------------*/
312
313void HGroup::
314recursiveOpen(const Hid& loc_id, const String& var)
315{
316 close();
317 UniqueArray<String> bufs;
318 splitString(var, bufs, '/');
319 hid_t last_hid = loc_id.id();
320 Integer nb_open = bufs.size();
321 UniqueArray<hid_t> ref_ids(nb_open);
322 ARCANE_HDF5_MUTEX;
323 for (Integer i = 0; i < nb_open; ++i) {
324 last_hid = _H5Gopen(last_hid, bufs[i].localstr());
325 ref_ids[i] = last_hid;
326 }
327 // Release all intermediate opened groups
328 for (Integer i = 0; i < nb_open - 1; ++i) {
329 H5Gclose(ref_ids[i]);
330 }
331 _setId(last_hid);
332}
333
334/*---------------------------------------------------------------------------*/
335/*---------------------------------------------------------------------------*/
336
337void HGroup::
338openIfExists(const Hid& loc_id, const Array<String>& paths)
339{
340 close();
341 hid_t last_hid = loc_id.id();
342 bool is_valid = true;
343 Integer nb_open = paths.size();
344 UniqueArray<hid_t> ref_ids;
345 ref_ids.reserve(nb_open);
346 for (Integer i = 0; i < nb_open; ++i) {
347 if (HGroup::hasChildren(last_hid, paths[i].localstr())) {
348 ARCANE_HDF5_MUTEX;
349 last_hid = _H5Gopen(last_hid, paths[i].localstr());
350 ref_ids.add(last_hid);
351 }
352 else {
353 is_valid = false;
354 break;
355 }
356 }
357 if (is_valid)
358 _setId(last_hid);
359 // Close all intermediate groups
360 ARCANE_HDF5_MUTEX;
361 for (Integer i = 0; i < ref_ids.size(); ++i) {
362 if (ref_ids[i] != last_hid) {
363 H5Gclose(ref_ids[i]);
364 }
365 }
366}
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
371bool HGroup::
372hasChildren(const String& var)
373{
374 return hasChildren(id(), var);
375}
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
380bool HGroup::
381hasChildren(hid_t loc_id, const String& var)
382{
383 HGroupSearch gs(var);
384 ARCANE_HDF5_MUTEX;
385 herr_t v = H5Giterate(loc_id, ".", 0, _ArcaneHdf5UtilsGroupIterateMe, &gs);
386 bool has_children = v > 0;
387 //cout << "** HAS CHILDREN " << var << " v=" << has_children << '\n';
388 return has_children;
389}
390
391/*---------------------------------------------------------------------------*/
392/*---------------------------------------------------------------------------*/
393
394hid_t HGroup::
395_checkOrCreate(hid_t loc_id, const String& group_name)
396{
397 // To check if a group already exists, since there is no
398 // worthy function in HDF5, we use the iteration mechanism
399 // to store all child groups of this group, and then search
400 // if the desired group exists
401 HGroupSearch gs(group_name);
402 //cerr << "** CHECK CREATE <" << group_name.str() << ">\n";
403 ARCANE_HDF5_MUTEX;
404 herr_t v = H5Giterate(loc_id, ".", 0, _ArcaneHdf5UtilsGroupIterateMe, &gs);
405
406 // Check if the group already exists
407 //herr_t he = H5Gget_objinfo(loc_id,group_name.str(),true,0);
408 //cerr << "** CHECK CREATE <" << group_name.str() << "> " << v << "\n";
409 //cerr << "** CHECK CREATE <" << group_name.str() << "> " << v << ' ' << he << "\n";
410 if (v > 0) {
411 return _H5Gopen(loc_id, group_name.localstr());
412 }
413 hid_t new_id = _H5Gcreate(loc_id, group_name.localstr());
414 //cerr << "** TRY TO CREATE <" << group_name.str() << "> " << new_id << "\n";
415 return new_id;
416}
417
418/*---------------------------------------------------------------------------*/
419/*---------------------------------------------------------------------------*/
420
421void HGroup::
422create(const Hid& loc_id, const String& group_name)
423{
424 ARCANE_HDF5_MUTEX;
425 _setId(H5Gcreate2(loc_id.id(), group_name.localstr(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
426}
427
428/*---------------------------------------------------------------------------*/
429/*---------------------------------------------------------------------------*/
430
431void HGroup::
432openOrCreate(const Hid& loc_id, const String& group_name)
433{
434 hid_t id = _checkOrCreate(loc_id.id(), group_name);
435 if (id < 0)
436 ARCANE_THROW(ReaderWriterException, "Can not open or create group named '{0}'", group_name);
437 _setId(id);
438}
439
440/*---------------------------------------------------------------------------*/
441/*---------------------------------------------------------------------------*/
442
443void HGroup::
444open(const Hid& loc_id, const String& var)
445{
446 hid_t id = -1;
447 {
448 ARCANE_HDF5_MUTEX;
449 id = _H5Gopen(loc_id.id(), var.localstr());
450 }
451 if (id < 0)
452 ARCANE_THROW(ReaderWriterException, "Can not find group named '{0}'", var);
453 _setId(id);
454}
455
456/*---------------------------------------------------------------------------*/
457/*---------------------------------------------------------------------------*/
458
459void HGroup::
460close()
461{
462 if (id() > 0) {
463 ARCANE_HDF5_MUTEX;
464 H5Gclose(id());
465 _setNullId();
466 }
467}
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471
472hid_t HGroup::
473_checkExist(hid_t loc_id, const String& group_name)
474{
475 // To check if a group already exists, since there is no
476 // proper function in HDF5, we use the iteration mechanism
477 // to store all child groups of this group, and then search
478 // if the desired group exists
479 HGroupSearch gs(group_name);
480 //cerr << "** CHECK CREATE <" << group_name.str() << ">\n";
481 ARCANE_HDF5_MUTEX;
482 herr_t v = H5Giterate(loc_id, ".", 0, _ArcaneHdf5UtilsGroupIterateMe, &gs);
483
484 // Check if the group already exists
485 //herr_t he = H5Gget_objinfo(loc_id,group_name.str(),true,0);
486 //cerr << "** CHECK CREATE <" << group_name.str() << "> " << v << "\n";
487 //cerr << "** CHECK CREATE <" << group_name.str() << "> " << v << ' ' << he << "\n";
488 if (v > 0) {
489 return _H5Gopen(loc_id, group_name.localstr());
490 }
491 //hid_t new_id = H5Gcreate(loc_id,group_name.localstr(),0);
492 //cerr << "** TRY TO CREATE <" << group_name.str() << "> " << new_id << "\n";
493 return 0;
494}
495
496/*---------------------------------------------------------------------------*/
497/*---------------------------------------------------------------------------*/
498
499/*---------------------------------------------------------------------------*/
500/*---------------------------------------------------------------------------*/
501
502HSpace::
503~HSpace()
504{
505 if (id() > 0) {
506 ARCANE_HDF5_MUTEX;
507 H5Sclose(id());
508 }
509}
510
511/*---------------------------------------------------------------------------*/
512/*---------------------------------------------------------------------------*/
513
514void HSpace::
515createSimple(int nb, hsize_t dims[])
516{
517 ARCANE_HDF5_MUTEX;
518 _setId(H5Screate_simple(nb, dims, nullptr));
519}
520
521/*---------------------------------------------------------------------------*/
522/*---------------------------------------------------------------------------*/
523
524void HSpace::
525createSimple(int nb, hsize_t dims[], hsize_t max_dims[])
526{
527 ARCANE_HDF5_MUTEX;
528 _setId(H5Screate_simple(nb, dims, max_dims));
529}
530
531/*---------------------------------------------------------------------------*/
532/*---------------------------------------------------------------------------*/
533
534int HSpace::
535nbDimension()
536{
537 ARCANE_HDF5_MUTEX;
538 return H5Sget_simple_extent_ndims(id());
539}
540
541/*---------------------------------------------------------------------------*/
542/*---------------------------------------------------------------------------*/
543
544herr_t HSpace::
545getDimensions(hsize_t dims[], hsize_t max_dims[])
546{
547 ARCANE_HDF5_MUTEX;
548 return H5Sget_simple_extent_dims(id(), dims, max_dims);
549}
550
551/*---------------------------------------------------------------------------*/
552/*---------------------------------------------------------------------------*/
553
554/*---------------------------------------------------------------------------*/
555/*---------------------------------------------------------------------------*/
556
557void HDataset::
558close()
559{
560 if (id() > 0) {
561 ARCANE_HDF5_MUTEX;
562 H5Dclose(id());
563 }
564 _setNullId();
565}
566
567/*---------------------------------------------------------------------------*/
568/*---------------------------------------------------------------------------*/
569
570void HDataset::
571create(const Hid& loc_id, const String& var, hid_t save_type,
572 const HSpace& space_id, hid_t plist)
573{
574 ARCANE_HDF5_MUTEX;
575 hid_t hid = H5Dcreate2(loc_id.id(), var.localstr(), save_type, space_id.id(),
576 plist, H5P_DEFAULT, H5P_DEFAULT);
577 //cerr << "** CREATE ID=" << hid << '\n';
578 _setId(hid);
579}
580
581/*---------------------------------------------------------------------------*/
582/*---------------------------------------------------------------------------*/
583
584void HDataset::
585create(const Hid& loc_id, const String& var, hid_t save_type,
586 const HSpace& space_id, const HProperty& link_plist,
587 const HProperty& creation_plist, const HProperty& access_plist)
588{
589 ARCANE_HDF5_MUTEX;
590 hid_t hid = H5Dcreate2(loc_id.id(), var.localstr(), save_type, space_id.id(),
591 link_plist.id(), creation_plist.id(), access_plist.id());
592 //cerr << "** CREATE ID=" << hid << '\n';
593 _setId(hid);
594}
595
596/*---------------------------------------------------------------------------*/
597/*---------------------------------------------------------------------------*/
598
599herr_t HDataset::
600write(hid_t native_type, const void* array)
601{
602 //cerr << "** WRITE ID=" << id() << '\n';
603 ARCANE_HDF5_MUTEX;
604 return H5Dwrite(id(), native_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, array);
605}
606
607/*---------------------------------------------------------------------------*/
608/*---------------------------------------------------------------------------*/
609
610herr_t HDataset::
611write(hid_t native_type, const void* array, const HSpace& memspace_id,
612 const HSpace& filespace_id, hid_t plist)
613{
614 //cerr << "** WRITE ID=" << id() << '\n';
615 ARCANE_HDF5_MUTEX;
616 return H5Dwrite(id(), native_type, memspace_id.id(), filespace_id.id(), plist, array);
617}
618
619/*---------------------------------------------------------------------------*/
620/*---------------------------------------------------------------------------*/
621
622herr_t HDataset::
623write(hid_t native_type, const void* array, const HSpace& memspace_id,
624 const HSpace& filespace_id, const HProperty& plist)
625{
626 //cerr << "** WRITE ID=" << id() << '\n';
627 ARCANE_HDF5_MUTEX;
628 return H5Dwrite(id(), native_type, memspace_id.id(), filespace_id.id(), plist.id(), array);
629}
630
631/*---------------------------------------------------------------------------*/
632/*---------------------------------------------------------------------------*/
633
634herr_t HDataset::
635read(hid_t native_type, void* array)
636{
637 ARCANE_HDF5_MUTEX;
638 return H5Dread(id(), native_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, array);
639}
640
641/*---------------------------------------------------------------------------*/
642/*---------------------------------------------------------------------------*/
643
644void HDataset::
645readWithException(hid_t native_type, void* array)
646{
647 herr_t err = -1;
648 {
649 ARCANE_HDF5_MUTEX;
650 err = H5Dread(id(), native_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, array);
651 }
652 if (err != 0)
653 ARCANE_THROW(IOException, "Can not read dataset");
654}
655
656/*---------------------------------------------------------------------------*/
657/*---------------------------------------------------------------------------*/
658
659HSpace HDataset::
660getSpace()
661{
662 ARCANE_HDF5_MUTEX;
663 return HSpace(H5Dget_space(id()));
664}
665
666/*---------------------------------------------------------------------------*/
667/*---------------------------------------------------------------------------*/
668
669herr_t HDataset::
670setExtent(const hsize_t new_dims[])
671{
672 ARCANE_HDF5_MUTEX;
673 return H5Dset_extent(id(), new_dims);
674}
675
676/*---------------------------------------------------------------------------*/
677/*---------------------------------------------------------------------------*/
678
679void HDataset::
680recursiveCreate(const Hid& loc_id, const String& var, hid_t save_type,
681 const HSpace& space_id, hid_t plist)
682{
683 // If the dataset already exists, it must be removed
684 // otherwise it is not always possible to modify the space_id
685 UniqueArray<String> paths;
686 splitString(var, paths, '/');
687 Integer nb_path = paths.size();
688 if (nb_path == 1) {
689 if (HGroup::hasChildren(loc_id.id(), var)) {
690 _remove(loc_id.id(), var);
691 }
692 create(loc_id, var, save_type, space_id, plist);
693 return;
694 }
695 String last_name = paths[nb_path - 1];
696 paths.resize(nb_path - 1);
697 HGroup group;
698 group.recursiveCreate(loc_id, paths);
699 if (group.hasChildren(last_name)) {
700 _remove(group.id(), last_name);
701 }
702 create(group.id(), last_name, save_type, space_id, plist);
703}
704
705/*---------------------------------------------------------------------------*/
706/*---------------------------------------------------------------------------*/
707
708void HDataset::
709_remove(hid_t hid, const String& var)
710{
711 ARCANE_HDF5_MUTEX;
712 H5Gunlink(hid, var.localstr());
713}
714
715/*---------------------------------------------------------------------------*/
716/*---------------------------------------------------------------------------*/
717
718HAttribute::
719~HAttribute()
720{
721 if (id() > 0) {
722 ARCANE_HDF5_MUTEX;
723 H5Aclose(id());
724 }
725}
726
727/*---------------------------------------------------------------------------*/
728/*---------------------------------------------------------------------------*/
729
730void HAttribute::
731remove(const Hid& loc_id, const String& var)
732{
733 ARCANE_HDF5_MUTEX;
734 _setId(H5Adelete(loc_id.id(), var.localstr()));
735}
736
737/*---------------------------------------------------------------------------*/
738/*---------------------------------------------------------------------------*/
739
740void HAttribute::
741create(const Hid& loc_id, const String& var, hid_t save_type, const HSpace& space_id)
742{
743 ARCANE_HDF5_MUTEX;
744 _setId(H5Acreate2(loc_id.id(), var.localstr(), save_type, space_id.id(), H5P_DEFAULT, H5P_DEFAULT));
745}
746
747/*---------------------------------------------------------------------------*/
748/*---------------------------------------------------------------------------*/
749
750void HAttribute::
751open(const Hid& loc_id, const String& var)
752{
753 ARCANE_HDF5_MUTEX;
754 _setId(H5Aopen_name(loc_id.id(), var.localstr()));
755}
756
757/*---------------------------------------------------------------------------*/
758/*---------------------------------------------------------------------------*/
759
760herr_t HAttribute::
761write(hid_t native_type, void* array)
762{
763 ARCANE_HDF5_MUTEX;
764 return H5Awrite(id(), native_type, array);
765}
766
767/*---------------------------------------------------------------------------*/
768/*---------------------------------------------------------------------------*/
769
770herr_t HAttribute::
771read(hid_t native_type, void* array)
772{
773 ARCANE_HDF5_MUTEX;
774 return H5Aread(id(), native_type, array);
775}
776
777/*---------------------------------------------------------------------------*/
778/*---------------------------------------------------------------------------*/
779
780HSpace HAttribute::
781getSpace()
782{
783 ARCANE_HDF5_MUTEX;
784 return HSpace(H5Aget_space(id()));
785}
786
787/*---------------------------------------------------------------------------*/
788/*---------------------------------------------------------------------------*/
789
790/*---------------------------------------------------------------------------*/
791/*---------------------------------------------------------------------------*/
792
793HType::
794~HType()
795{
796 if (id() > 0) {
797 ARCANE_HDF5_MUTEX;
798 H5Tclose(id());
799 }
800}
801
802/*---------------------------------------------------------------------------*/
803/*---------------------------------------------------------------------------*/
804
805/*---------------------------------------------------------------------------*/
806/*---------------------------------------------------------------------------*/
807
808void HDataset::
809open(const Hid& loc_id, const String& var)
810{
811 {
812 ARCANE_HDF5_MUTEX;
813 _setId(H5Dopen2(loc_id.id(), var.localstr(), H5P_DEFAULT));
814 }
815 if (isBad())
816 ARCANE_THROW(IOException, "Can not open dataset '{0}'", var);
817}
818
819/*---------------------------------------------------------------------------*/
820/*---------------------------------------------------------------------------*/
821
822void HDataset::
823openIfExists(const Hid& loc_id, const String& var)
824{
825 UniqueArray<String> paths;
826 splitString(var, paths, '/');
827 Integer nb_path = paths.size();
828 HGroup parent_group;
829 String last_name = var;
830 if (nb_path > 1) {
831 last_name = paths[nb_path - 1];
832 paths.resize(nb_path - 1);
833 parent_group.openIfExists(loc_id, paths);
834 }
835 else {
836 parent_group.open(loc_id, ".");
837 }
838 if (parent_group.isBad())
839 return;
840 if (parent_group.hasChildren(last_name))
841 open(loc_id.id(), var.localstr());
842}
843
844/*---------------------------------------------------------------------------*/
845/*---------------------------------------------------------------------------*/
846
847/*---------------------------------------------------------------------------*/
848/*---------------------------------------------------------------------------*/
849
850void HProperty::
851close()
852{
853 if (id() > 0) {
854 ARCANE_HDF5_MUTEX;
855 H5Pclose(id());
856 _setNullId();
857 }
858}
859
860/*---------------------------------------------------------------------------*/
861/*---------------------------------------------------------------------------*/
862
863void HProperty::
864create(hid_t cls_id)
865{
866 close();
867 ARCANE_HDF5_MUTEX;
868 _setId(H5Pcreate(cls_id));
869}
870
871/*---------------------------------------------------------------------------*/
872/*---------------------------------------------------------------------------*/
873
876{
877#ifdef H5_HAVE_PARALLEL
878 void* arcane_comm = pm->getMPICommunicator();
879 if (!arcane_comm)
880 ARCANE_FATAL("No MPI environment available");
881 MPI_Comm mpi_comm = *((MPI_Comm*)arcane_comm);
882 MPI_Info mpi_info = MPI_INFO_NULL;
883
884 create(H5P_FILE_ACCESS);
885 H5Pset_fapl_mpio(id(), mpi_comm, mpi_info);
886#else
887 ARCANE_UNUSED(pm);
888 ARCANE_THROW(NotSupportedException, "HDF5 is not compiled with MPI support");
889#endif
890}
891
892/*---------------------------------------------------------------------------*/
893/*---------------------------------------------------------------------------*/
894
897{
898#ifdef H5_HAVE_PARALLEL
899 create(H5P_DATASET_XFER);
900 H5Pset_dxpl_mpio(id(), H5FD_MPIO_COLLECTIVE);
901
902#if (H5_VERS_MAJOR >= 2 || H5_VERS_MINOR >= 14)
903 H5Pset_selection_io(id(), H5D_SELECTION_IO_MODE_OFF);
904#endif
905
906#else
907 ARCANE_THROW(NotSupportedException, "HDF5 is not compiled with MPI support");
908#endif
909}
910
911/*---------------------------------------------------------------------------*/
912/*---------------------------------------------------------------------------*/
913
916{
917#ifdef H5_HAVE_PARALLEL
918 create(H5P_DATASET_XFER);
919 H5Pset_dxpl_mpio(id(), H5FD_MPIO_INDEPENDENT);
920
921#if (H5_VERS_MAJOR >= 2 || H5_VERS_MINOR >= 14)
922 H5Pset_selection_io(id(), H5D_SELECTION_IO_MODE_OFF);
923#endif
924
925#else
926 ARCANE_THROW(NotSupportedException, "HDF5 is not compiled with MPI support");
927#endif
928}
929
930/*---------------------------------------------------------------------------*/
931/*---------------------------------------------------------------------------*/
932
933/*---------------------------------------------------------------------------*/
934/*---------------------------------------------------------------------------*/
935
941
942/*---------------------------------------------------------------------------*/
943/*---------------------------------------------------------------------------*/
944
946StandardTypes(bool do_init)
947{
948 if (do_init)
949 initialize();
950}
951
952/*---------------------------------------------------------------------------*/
953/*---------------------------------------------------------------------------*/
954
957{
958 ARCANE_HDF5_MUTEX;
959 {
960 hid_t type_id = H5Tcopy(H5T_NATIVE_CHAR);
961 m_char_id.setId(type_id);
962 }
963 {
964 hid_t type_id = H5Tcopy(H5T_NATIVE_UCHAR);
965 m_uchar_id.setId(type_id);
966 }
967 {
968 hid_t type_id = H5Tcopy(H5T_NATIVE_SCHAR);
969 m_schar_id.setId(type_id);
970 }
971 {
972 hid_t type_id = H5Tcopy(H5T_NATIVE_SHORT);
973 H5Tset_precision(type_id, 8 * sizeof(short));
974 H5Tset_order(type_id, H5T_ORDER_LE);
975 m_short_id.setId(type_id);
976 }
977 {
978 hid_t type_id = H5Tcopy(H5T_NATIVE_INT);
979 H5Tset_precision(type_id, 8 * sizeof(int));
980 H5Tset_order(type_id, H5T_ORDER_LE);
981 m_int_id.setId(type_id);
982 }
983 {
984 hid_t type_id = H5Tcopy(H5T_NATIVE_LONG);
985 H5Tset_precision(type_id, 8 * sizeof(long));
986 H5Tset_order(type_id, H5T_ORDER_LE);
987 m_long_id.setId(type_id);
988 }
989 {
990 hid_t type_id = H5Tcopy(H5T_NATIVE_USHORT);
991 H5Tset_precision(type_id, 8 * sizeof(unsigned short));
992 H5Tset_order(type_id, H5T_ORDER_LE);
993 m_ushort_id.setId(type_id);
994 }
995 {
996 hid_t type_id = H5Tcopy(H5T_NATIVE_UINT);
997 H5Tset_precision(type_id, 8 * sizeof(unsigned int));
998 H5Tset_order(type_id, H5T_ORDER_LE);
999 m_uint_id.setId(type_id);
1000 }
1001 {
1002 hid_t type_id = H5Tcopy(H5T_NATIVE_ULONG);
1003 H5Tset_precision(type_id, 8 * sizeof(unsigned long));
1004 H5Tset_order(type_id, H5T_ORDER_LE);
1005 m_ulong_id.setId(type_id);
1006 }
1007 {
1008 hid_t type_id = H5Tcopy(H5T_NATIVE_FLOAT);
1009 H5Tset_precision(type_id, 8 * sizeof(float));
1010 H5Tset_order(type_id, H5T_ORDER_LE);
1011 m_float32_id.setId(type_id);
1012 }
1013 {
1014 hid_t type_id = H5Tcopy(H5T_NATIVE_DOUBLE);
1015 H5Tset_precision(type_id, 8 * sizeof(double));
1016 H5Tset_order(type_id, H5T_ORDER_LE);
1017 m_real_id.setId(type_id);
1018 }
1019 {
1020 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real2POD));
1021 _H5Tinsert(type_id, "X", HOFFSET(Real2POD, x), H5T_NATIVE_DOUBLE);
1022 _H5Tinsert(type_id, "Y", HOFFSET(Real2POD, y), H5T_NATIVE_DOUBLE);
1023 m_real2_id.setId(type_id);
1024 }
1025 {
1026 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real3POD));
1027 _H5Tinsert(type_id, "X", HOFFSET(Real3POD, x), H5T_NATIVE_DOUBLE);
1028 _H5Tinsert(type_id, "Y", HOFFSET(Real3POD, y), H5T_NATIVE_DOUBLE);
1029 _H5Tinsert(type_id, "Z", HOFFSET(Real3POD, z), H5T_NATIVE_DOUBLE);
1030 m_real3_id.setId(type_id);
1031 }
1032 {
1033 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real2x2POD));
1034 _H5Tinsert(type_id, "XX", HOFFSET(Real2x2POD, x.x), H5T_NATIVE_DOUBLE);
1035 _H5Tinsert(type_id, "XY", HOFFSET(Real2x2POD, x.y), H5T_NATIVE_DOUBLE);
1036 _H5Tinsert(type_id, "YX", HOFFSET(Real2x2POD, y.x), H5T_NATIVE_DOUBLE);
1037 _H5Tinsert(type_id, "YY", HOFFSET(Real2x2POD, y.y), H5T_NATIVE_DOUBLE);
1038 m_real2x2_id.setId(type_id);
1039 }
1040 {
1041 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real3x3POD));
1042 _H5Tinsert(type_id, "XX", HOFFSET(Real3x3POD, x.x), H5T_NATIVE_DOUBLE);
1043 _H5Tinsert(type_id, "XY", HOFFSET(Real3x3POD, x.y), H5T_NATIVE_DOUBLE);
1044 _H5Tinsert(type_id, "XZ", HOFFSET(Real3x3POD, x.z), H5T_NATIVE_DOUBLE);
1045 _H5Tinsert(type_id, "YX", HOFFSET(Real3x3POD, y.x), H5T_NATIVE_DOUBLE);
1046 _H5Tinsert(type_id, "YY", HOFFSET(Real3x3POD, y.y), H5T_NATIVE_DOUBLE);
1047 _H5Tinsert(type_id, "YZ", HOFFSET(Real3x3POD, y.z), H5T_NATIVE_DOUBLE);
1048 _H5Tinsert(type_id, "ZX", HOFFSET(Real3x3POD, z.x), H5T_NATIVE_DOUBLE);
1049 _H5Tinsert(type_id, "ZY", HOFFSET(Real3x3POD, z.y), H5T_NATIVE_DOUBLE);
1050 _H5Tinsert(type_id, "ZZ", HOFFSET(Real3x3POD, z.z), H5T_NATIVE_DOUBLE);
1051 m_real3x3_id.setId(type_id);
1052 }
1053
1054 // HDF5 1.10 and 1.12 do not yet support 'BFloat16' and 'Float16' types.
1055 // When that is the case, we will be able to use the type provided by HDF5.
1056 // (NOTE: HDF5 1.14.4 supports Float16)
1057
1058 // Add opaque type for BFloat16.
1059 {
1060 hid_t type_id = H5Tcopy(H5T_NATIVE_B16);
1061 m_bfloat16_id.setId(type_id);
1062 }
1063 // Add opaque type for Float16.
1064 {
1065 hid_t type_id = H5Tcopy(H5T_NATIVE_B16);
1066 m_float16_id.setId(type_id);
1067 }
1068}
1069
1070/*---------------------------------------------------------------------------*/
1071/*---------------------------------------------------------------------------*/
1072
1073StandardTypes::
1074~StandardTypes()
1075{
1076}
1077
1078/*---------------------------------------------------------------------------*/
1079/*---------------------------------------------------------------------------*/
1080
1081void StandardTypes::
1082_H5Tinsert(hid_t type, const char* name, Integer offset, hid_t field_id)
1083{
1084 // Mutex managed by initialize.
1085 herr_t herr = H5Tinsert(type, name, offset, field_id);
1086 if (herr < 0) {
1087 ARCANE_FATAL("Can not insert type");
1088 }
1089}
1090
1091/*---------------------------------------------------------------------------*/
1092/*---------------------------------------------------------------------------*/
1093
1094#ifdef ARCANE_REAL_NOT_BUILTIN
1095hid_t StandardTypes::
1096nativeType(Real) const
1097{
1098 ARCANE_FATAL("Real is a complex type");
1099}
1100#endif
1101
1102hid_t StandardTypes::
1103saveType(eDataType sd) const
1104{
1105 switch (sd) {
1106 case DT_Byte:
1107 return saveType(Byte());
1108 case DT_Real:
1109 return saveType(Real());
1110 case DT_Real2:
1111 return saveType(Real2());
1112 case DT_Real2x2:
1113 return saveType(Real2x2());
1114 case DT_Real3:
1115 return saveType(Real3());
1116 case DT_Real3x3:
1117 return saveType(Real3x3());
1118 case DT_Int8:
1119 return saveType(Int8());
1120 case DT_Int16:
1121 return saveType(Int16());
1122 case DT_Int32:
1123 return saveType(Int32());
1124 case DT_Int64:
1125 return saveType(Int64());
1126 case DT_Float32:
1127 return saveType(Float32());
1128 case DT_Float16:
1129 return saveType(Float16());
1130 case DT_BFloat16:
1131 return saveType(BFloat16());
1132 default:
1133 throw ArgumentException(String::format("Bad type '{0}'", sd));
1134 }
1135}
1136
1137/*---------------------------------------------------------------------------*/
1138/*---------------------------------------------------------------------------*/
1139
1140hid_t StandardTypes::
1141nativeType(eDataType sd) const
1142{
1143 switch (sd) {
1144 case DT_Byte:
1145 return nativeType(Byte());
1146 case DT_Real:
1147 return nativeType(Real());
1148 case DT_Real2:
1149 return nativeType(Real2());
1150 case DT_Real2x2:
1151 return nativeType(Real2x2());
1152 case DT_Real3:
1153 return nativeType(Real3());
1154 case DT_Real3x3:
1155 return nativeType(Real3x3());
1156 case DT_Int8:
1157 return nativeType(Int8());
1158 case DT_Int16:
1159 return nativeType(Int16());
1160 case DT_Int32:
1161 return nativeType(Int32());
1162 case DT_Int64:
1163 return nativeType(Int64());
1164 case DT_Float32:
1165 return nativeType(Float32());
1166 case DT_Float16:
1167 return nativeType(Float16());
1168 case DT_BFloat16:
1169 return nativeType(BFloat16());
1170 default:
1171 throw ArgumentException(String::format("Bad type '{0}'", sd));
1172 }
1173}
1174
1175/*---------------------------------------------------------------------------*/
1176/*---------------------------------------------------------------------------*/
1177
1178/*---------------------------------------------------------------------------*/
1179/*---------------------------------------------------------------------------*/
1180
1181StandardArray::
1182StandardArray(hid_t hfile, const String& hpath)
1183: m_hfile(hfile)
1184, m_hpath(hpath)
1185, m_ids_hpath(hpath + "_Ids")
1186, m_is_init(false)
1187{
1188}
1189
1190/*---------------------------------------------------------------------------*/
1191/*---------------------------------------------------------------------------*/
1192
1193void StandardArray::
1194readDim()
1195{
1196 if (m_is_init)
1197 return;
1198 m_is_init = true;
1199 m_hdataset.open(m_hfile, m_hpath);
1200 HSpace hspace(m_hdataset.getSpace());
1201 {
1202 const int max_dim = 256; // Maximum number of dimensions for HDF arrays
1203 hsize_t hdf_dims[max_dim];
1204 hsize_t max_dims[max_dim];
1205 int nb_dim = -1;
1206 {
1207 ARCANE_HDF5_MUTEX;
1208 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1209 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1210 }
1211 for (Integer i = 0; i < nb_dim; ++i) {
1212 //cerr << "** DIM i=" << i << " hdim=" << hdf_dims[i]
1213 // << " max=" << max_dims[i] << '\n';
1214 m_dimensions.add((Int64)hdf_dims[i]);
1215 }
1216 }
1217 // Checks if a variable suffixed '_Ids' exists containing the unique numbers
1218 // of the entities
1219 m_ids_dataset.openIfExists(m_hfile, m_ids_hpath);
1220 //cout << "TRY OPEN ID DATASET path=" << m_ids_hpath << " r=" << m_ids_dataset.id()>0 << '\n';
1221}
1222
1223/*---------------------------------------------------------------------------*/
1224/*---------------------------------------------------------------------------*/
1225
1227setIdsPath(const String& ids_path)
1228{
1229 m_ids_hpath = ids_path;
1230}
1231
1232/*---------------------------------------------------------------------------*/
1233/*---------------------------------------------------------------------------*/
1234
1235void StandardArray::
1236_write(const void* buffer, Integer nb_element, hid_t save_type, hid_t native_type)
1237{
1238 if (!m_is_init) {
1239 hsize_t dims[1];
1240 dims[0] = nb_element;
1241
1242 HSpace hspace;
1243 hspace.createSimple(1, dims);
1244 if (hspace.isBad())
1245 ARCANE_THROW(IOException, "Can not create space");
1246
1247 m_dimensions.clear();
1248 m_dimensions.add(nb_element);
1249
1250 m_hdataset.recursiveCreate(m_hfile, m_hpath, save_type, hspace, H5P_DEFAULT);
1251 if (m_hdataset.isBad())
1252 ARCANE_THROW(IOException, "Can not create dataset");
1253
1254 m_is_init = true;
1255 }
1256
1257 m_hdataset.write(native_type, buffer);
1258}
1259
1260/*---------------------------------------------------------------------------*/
1261/*---------------------------------------------------------------------------*/
1262
1263bool StandardArray::
1264exists() const
1265{
1266 HDataset dataset;
1267 dataset.openIfExists(m_hfile, m_hpath);
1268 return dataset.id() > 0;
1269}
1270
1271/*---------------------------------------------------------------------------*/
1272/*---------------------------------------------------------------------------*/
1273
1274template <typename DataType> StandardArrayT<DataType>::
1275StandardArrayT(hid_t hfile, const String& hpath)
1276: StandardArray(hfile, hpath)
1277{
1278}
1279
1280/*---------------------------------------------------------------------------*/
1281/*---------------------------------------------------------------------------*/
1282
1283template <typename DataType> void StandardArrayT<DataType>::
1285{
1286 m_hdataset.readWithException(st.nativeType(DataType()), buffer.data());
1287}
1288
1289/*---------------------------------------------------------------------------*/
1290/*---------------------------------------------------------------------------*/
1291
1292template <typename DataType> void StandardArrayT<DataType>::
1294{
1295 readDim();
1296 buffer.resize(m_dimensions[0]);
1297 read(st, buffer);
1298}
1299
1300/*---------------------------------------------------------------------------*/
1301/*---------------------------------------------------------------------------*/
1302
1303template <typename DataType> void StandardArrayT<DataType>::
1305{
1306 bool is_master = pm->isMasterIO();
1307 Integer master_rank = pm->masterIORank();
1308 bool has_ids = false;
1309 if (is_master) {
1310 read(st, buffer);
1311 Integer buf_size = buffer.size();
1312 if (m_ids_dataset.id() > 0) {
1313 has_ids = true;
1314 m_ids_dataset.read(st.nativeType(Int64()), unique_ids.data());
1315 }
1316 Integer infos[2];
1317 infos[0] = buf_size;
1318 infos[1] = has_ids ? 1 : 0;
1319 IntegerArrayView iav(2, infos);
1320 pm->broadcast(iav, master_rank);
1321 pm->broadcast(buffer, master_rank);
1322 pm->broadcast(unique_ids, master_rank);
1323 }
1324 else {
1325 Integer infos[2];
1326 IntegerArrayView iav(2, infos);
1327 pm->broadcast(iav, master_rank);
1328 Integer buf_size = infos[0];
1329 has_ids = infos[1] != 0;
1330 buffer.resize(buf_size);
1331 unique_ids.resize(buf_size);
1332 pm->broadcast(buffer, master_rank);
1333 pm->broadcast(unique_ids, master_rank);
1334 }
1335 if (!has_ids) {
1336 for (Integer i = 0, is = unique_ids.size(); i < is; ++i)
1337 unique_ids[i] = i;
1338 }
1339}
1340
1341/*---------------------------------------------------------------------------*/
1342/*---------------------------------------------------------------------------*/
1343
1344template <typename DataType> void StandardArrayT<DataType>::
1345write(StandardTypes& st, ConstArrayView<DataType> buffer)
1346{
1347 Integer nb_element = buffer.size();
1348 _write(buffer.data(), nb_element, st.saveType(DataType()), st.nativeType(DataType()));
1349}
1350
1351/*---------------------------------------------------------------------------*/
1352/*---------------------------------------------------------------------------*/
1353
1354template <typename DataType> void StandardArrayT<DataType>::
1355_writeSortedValues(ITraceMng* tm, StandardTypes& st,
1356 ConstArrayView<DataType> buffer,
1357 Int64ConstArrayView unique_ids)
1358{
1359 ARCANE_UNUSED(tm);
1360
1361 Integer total_size = buffer.size();
1362 Integer nb_element = unique_ids.size();
1363 Integer dim2_size = 1;
1364 if (nb_element != total_size) {
1365 if (nb_element == 0)
1366 ARCANE_THROW(ArgumentException, "unique_ids size is zero but not buffer size ({0})",
1367 total_size);
1368 dim2_size = total_size / nb_element;
1369 if (dim2_size * nb_element != total_size)
1370 ARCANE_THROW(ArgumentException, "buffer size ({0}) is not a multiple of unique_ids size ({1})",
1371 total_size, nb_element);
1372 }
1373
1374 UniqueArray<ValueWithUid> values_to_sort(nb_element);
1375 UniqueArray<DataType> out_buffer(total_size);
1376 //tm->info() << " WRITE total_size=" << total_size
1377 //<< " uid_size=" << unique_ids.size();
1378 for (Integer i = 0; i < nb_element; ++i) {
1379 values_to_sort[i].m_uid = unique_ids[i];
1380 values_to_sort[i].m_index = i;
1381 //values_to_sort[i].m_value = buffer[i];
1382 //tm->info() << "BEFORE SORT i=" << i << " uid=" << unique_ids[i];
1383 }
1384 std::sort(std::begin(values_to_sort), std::end(values_to_sort));
1385 for (Integer i = 0; i < nb_element; ++i) {
1386 Integer old_index = values_to_sort[i].m_index;
1387 for (Integer j = 0; j < dim2_size; ++j) {
1388 Integer pos = (i * dim2_size) + j;
1389 out_buffer[pos] = buffer[(old_index * dim2_size) + j];
1390 //tm->info() << "AFTER SORT i=" << i << " uid=" << values_to_sort[i].m_uid
1391 // << " j=" << j << " pos=" << pos
1392 // << " value=" << out_buffer[pos];
1393 }
1394 }
1395 write(st, out_buffer);
1396}
1397
1398/*---------------------------------------------------------------------------*/
1399/*---------------------------------------------------------------------------*/
1400
1401template <typename DataType> void StandardArrayT<DataType>::
1402parallelWrite(IParallelMng* pm, StandardTypes& st,
1403 ConstArrayView<DataType> buffer, Int64ConstArrayView unique_ids)
1404{
1405 //TODO:
1406 // For now, only the master process writes.
1407 // It retrieves all values, sorts them by increasing uniqueId
1408 // and writes them.
1409 // It is important that everything is sorted in ascending order because
1410 // this allows maintaining the same writing order even when mesh partitioning
1411 // occurs. The read operation assumes this constraint is met and only reads the
1412 // uniqueId information at the start of the case.
1413 bool is_parallel = pm->isParallel();
1414 ITraceMng* tm = pm->traceMng();
1415
1416 if (!is_parallel) {
1417 _writeSortedValues(tm, st, buffer, unique_ids);
1418 return;
1419 }
1420
1421 bool is_master = pm->isMasterIO();
1422 Integer master_rank = pm->masterIORank();
1423 Integer nb_rank = pm->commSize();
1424 Integer buf_size = buffer.size();
1425 Integer unique_id_size = unique_ids.size();
1426 IntegerUniqueArray rank_sizes(2 * nb_rank);
1427 // The master subdomain retrieves information from all others.
1428 // If a subdomain has no elements to send, it does nothing
1429 // (it does not send empty buffers)
1430 if (is_master) {
1431 Integer buf[2];
1432 buf[0] = buf_size;
1433 buf[1] = unique_id_size;
1434 IntegerArrayView iav(2, buf);
1435 pm->allGather(iav, rank_sizes);
1436
1437 Integer buffer_total_size = 0;
1438 Integer unique_id_total_size = 0;
1439 IntegerUniqueArray buffer_rank_index(nb_rank);
1440 IntegerUniqueArray unique_id_rank_index(nb_rank);
1441
1442 for (Integer i = 0; i < nb_rank; ++i) {
1443 buffer_rank_index[i] = buffer_total_size;
1444 buffer_total_size += rank_sizes[(i * 2)];
1445 unique_id_rank_index[i] = unique_id_total_size;
1446 unique_id_total_size += rank_sizes[(i * 2) + 1];
1447 }
1448
1449 UniqueArray<DataType> full_buffer(buffer_total_size);
1450 Int64UniqueArray full_unique_ids(unique_id_total_size);
1451
1452 for (Integer i = 0; i < nb_rank; ++i) {
1453 // Ne recoit pas de valeurs des processus n'ayant pas de valeurs
1454 if (rank_sizes[(i * 2)] == 0)
1455 continue;
1456 ArrayView<DataType> local_buf(rank_sizes[(i * 2)], &full_buffer[buffer_rank_index[i]]);
1457 Int64ArrayView local_unique_ids(rank_sizes[(i * 2) + 1], &full_unique_ids[unique_id_rank_index[i]]);
1458 if (i == master_rank) {
1459 local_buf.copy(buffer);
1460 local_unique_ids.copy(unique_ids);
1461 }
1462 else {
1463 pm->recv(local_buf, i);
1464 pm->recv(local_unique_ids, i);
1465 }
1466 }
1467 tm->info(5) << "PARALLEL WRITE path=" << m_hpath << " total_size=" << full_buffer.size();
1468 _writeSortedValues(tm, st, full_buffer, full_unique_ids);
1469 }
1470 else {
1471 Integer buf[2];
1472 buf[0] = buf_size;
1473 buf[1] = unique_id_size;
1474 IntegerArrayView iav(2, buf);
1475 pm->allGather(iav, rank_sizes);
1476 // No need to send empty buffers
1477 if (buffer.size() > 0) {
1478 pm->send(buffer, master_rank);
1479 pm->send(unique_ids, master_rank);
1480 }
1481 }
1482}
1483
1484/*---------------------------------------------------------------------------*/
1485/*---------------------------------------------------------------------------*/
1486
1487template class StandardArrayT<Real>;
1488template class StandardArrayT<Real3>;
1489template class StandardArrayT<Real3x3>;
1490template class StandardArrayT<Real2>;
1491template class StandardArrayT<Real2x2>;
1492template class StandardArrayT<Int16>;
1493template class StandardArrayT<Int32>;
1494template class StandardArrayT<Int64>;
1495template class StandardArrayT<Byte>;
1496template class StandardArrayT<Int8>;
1497template class StandardArrayT<Float32>;
1498// NOTE: these types cannot yet be instantiated because they require
1499// the ability to perform send/receive via IParallelMng, which is not
1500// yet implemented.
1501//template class StandardArrayT<Float16>;
1502//template class StandardArrayT<BFloat16>;
1503
1504/*---------------------------------------------------------------------------*/
1505/*---------------------------------------------------------------------------*/
1506
1507template <typename DataType> DataType
1510{
1511 Hdf5Utils::HDataset m_hdataset;
1512 m_hdataset.open(m_hfile, m_hpath);
1513 Hdf5Utils::HSpace hspace(m_hdataset.getSpace());
1514 {
1515 const int max_dim = 256; // Maximum number of HDF array dimensions
1516 hsize_t hdf_dims[max_dim];
1517 hsize_t max_dims[max_dim];
1518 int nb_dim = -1;
1519 {
1520 ARCANE_HDF5_MUTEX;
1521 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1522 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1523 }
1524 if (nb_dim != 1 || hdf_dims[0] != 1)
1525 ARCANE_THROW(IOException, "Cannot read non scalar");
1526 }
1527
1528 DataType dummy;
1529 m_hdataset.read(st.nativeType(DataType()), &dummy);
1530 return dummy;
1531}
1532
1533/*---------------------------------------------------------------------------*/
1534
1535template <> String
1538{
1539 ByteUniqueArray utf8_bytes;
1540
1541 Hdf5Utils::HDataset m_hdataset;
1542 m_hdataset.open(m_hfile, m_hpath);
1543 Hdf5Utils::HSpace hspace(m_hdataset.getSpace());
1544 {
1545 const int max_dim = 256; // Maximum number of HDF array dimensions
1546 hsize_t hdf_dims[max_dim];
1547 hsize_t max_dims[max_dim];
1548 int nb_dim = -1;
1549 {
1550 ARCANE_HDF5_MUTEX;
1551 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1552 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1553 }
1554
1555 if (nb_dim != 1)
1556 ARCANE_THROW(IOException, "Cannot read multidim string");
1557 utf8_bytes.resize(hdf_dims[0]);
1558 }
1559
1560 m_hdataset.read(st.nativeType(Byte()), utf8_bytes.data());
1561 return String(utf8_bytes);
1562}
1563
1564/*---------------------------------------------------------------------------*/
1565
1566template <typename DataType> void
1568write(Hdf5Utils::StandardTypes& st, const DataType& t)
1569{
1570 hsize_t dims[1] = { 1 };
1571 Hdf5Utils::HSpace hspace;
1572 hspace.createSimple(1, dims);
1573 if (hspace.isBad())
1574 ARCANE_THROW(IOException, "Can not create space");
1575
1576 Hdf5Utils::HDataset m_hdataset;
1577 m_hdataset.recursiveCreate(m_hfile, m_hpath, st.saveType(DataType()), hspace, H5P_DEFAULT);
1578 if (m_hdataset.isBad())
1579 ARCANE_THROW(IOException, "Can not create dataset");
1580
1581 herr_t herr = m_hdataset.write(st.nativeType(DataType()), &t);
1582 if (herr < 0)
1583 ARCANE_THROW(IOException, "Cannot write data");
1584}
1585
1586/*---------------------------------------------------------------------------*/
1587
1588template <> void
1591{
1592 ByteConstArrayView utf8_bytes = s.utf8();
1593
1594 hsize_t dims[1];
1595 dims[0] = utf8_bytes.size() + 1;
1596
1597 Hdf5Utils::HSpace hspace;
1598 hspace.createSimple(1, dims);
1599 if (hspace.isBad())
1600 ARCANE_THROW(IOException, "Can not create space");
1601
1602 Hdf5Utils::HDataset m_hdataset;
1603 m_hdataset.recursiveCreate(m_hfile, m_hpath, st.saveType(Byte()), hspace, H5P_DEFAULT);
1604 if (m_hdataset.isBad())
1605 ARCANE_THROW(IOException, "Can not create dataset");
1606
1607 herr_t herr = m_hdataset.write(st.nativeType(Byte()), utf8_bytes.data());
1608 if (herr < 0)
1609 ARCANE_THROW(IOException, "Cannot write data");
1610}
1611
1612/*---------------------------------------------------------------------------*/
1613
1614template class StandardScalarT<String>;
1615template class StandardScalarT<Real>;
1616template class StandardScalarT<Real3>;
1617template class StandardScalarT<Real3x3>;
1618template class StandardScalarT<Real2>;
1619template class StandardScalarT<Real2x2>;
1620template class StandardScalarT<Int16>;
1621template class StandardScalarT<Int32>;
1622template class StandardScalarT<Int64>;
1623template class StandardScalarT<Byte>;
1624template class StandardScalarT<Int8>;
1625template class StandardScalarT<Float16>;
1626template class StandardScalarT<BFloat16>;
1627template class StandardScalarT<Float32>;
1628
1629/*---------------------------------------------------------------------------*/
1630/*---------------------------------------------------------------------------*/
1631
1632} // namespace Arcane::Hdf5Utils
1633
1634/*---------------------------------------------------------------------------*/
1635/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Integer size() const
Number of elements in the vector.
Modifiable view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the start of the view.
Base class for 1D data vectors.
void resize(Int64 s)
Changes the number of elements in the array to s.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
const T * data() const
Access to the root of the array without any protection.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
Template class for converting a type.
Encapsulates a hid_t for a dataset.
Helper class for searching a group.
static void useMutex(bool is_active, IParallelMng *pm)
Function allowing activation or deactivation of locks on each HDF5 call.
Definition Hdf5Utils.cc:89
Encapsulates a hid_t for a property (H5P*).
void createDatasetTransfertCollectiveMPIIO()
Creates a dataset property for MPIIO.
Definition Hdf5Utils.cc:896
void createFilePropertyMPIIO(IParallelMng *pm)
Creates a file property for MPIIO.
Definition Hdf5Utils.cc:875
void createDatasetTransfertIndependentMPIIO()
Creates a dataset property for MPIIO.
Definition Hdf5Utils.cc:915
Encapsulates a hid_t for a dataspace.
Encapsulates a hid_t.
Encapsulates a simple dataset from an HDF5 file that represents an array.
void read(StandardTypes &st, ArrayView< DataType > buffer)
Reads the dataset of a 1D array. This operation is only valid after calling readDim()....
void directRead(StandardTypes &st, Array< DataType > &buffer)
Reads the dataset of a 1D array.
Encapsulates a simple dataset from an HDF5 file that represents an array.
void setIdsPath(const String &ids_path)
When reading, positions the path in hfile to the dataset containing the unique_ids.
Encapsulates a simple dataset from an HDF5 file that represents a scalar (possibly String).
DataType read(Hdf5Utils::StandardTypes &st)
Reads a data item.
void write(Hdf5Utils::StandardTypes &st, const DataType &t)
Writes a data item.
Definition of standard Arcane types for hdf5.
HType m_bfloat16_id
HDF identifier for BFloat16.
HType m_real2x2_id
HDF identifier for Real2x2.
StandardTypes()
Creates an instance by initializing the types.
Definition Hdf5Utils.cc:937
HType m_long_id
HDF identifier for signed longs.
HType m_int_id
HDF identifier for signed integers.
HType m_short_id
HDF identifier for signed shorts.
HType m_real3x3_id
HDF identifier for Real3x3.
HType m_real_id
HDF identifier for reals.
HType m_ushort_id
HDF identifier for unsigned shorts.
HType m_ulong_id
HDF identifier for unsigned longs.
HType m_schar_id
HDF identifier for signed characters.
HType m_uchar_id
HDF identifier for unsigned characters.
HType m_real2_id
HDF identifier for Real2.
HType m_float32_id
HDF identifier for Float32.
HType m_float16_id
HDF identifier for Float16.
HType m_char_id
HDF identifier for characters.
void initialize()
Initializes the types.
Definition Hdf5Utils.cc:956
HType m_uint_id
HDF identifier for unsigned integers.
HType m_real3_id
HDF identifier for Real3.
Exception when an input/output error is detected.
Definition IOException.h:34
Interface of the parallelism manager for a subdomain.
virtual bool isMasterIO() const =0
true if the instance is a master I/O manager.
virtual Integer masterIORank() const =0
Rank of the instance managing I/O (for which isMasterIO() is true).
virtual void * getMPICommunicator()=0
Address of the MPI communicator associated with this manager.
ByteConstArrayView utf8() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:277
Integer len(const char *s)
Returns the length of the string s.
Utility functions for Hdf5.
Definition Hdf5Utils.cc:34
std::int8_t Int8
Signed integer type of 8 bits.
Array< Int64 > Int64Array
Dynamic one-dimensional array of 64-bit integers.
Definition UtilsTypes.h:125
ArrayView< Int64 > Int64ArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:451
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:339
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ArrayView< Integer > IntegerArrayView
C equivalent of a 1D array of integers.
Definition UtilsTypes.h:457
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:335
std::int16_t Int16
Signed integer type of 16 bits.
double Real
Type representing a real number.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:43
float Float32
IEEE-753 single-precision floating-point type.
eDataType
Data type.
Definition DataTypes.h:41
@ DT_Float32
'Float32' data type
Definition DataTypes.h:54
@ DT_Real2x2
2x2 tensor data type
Definition DataTypes.h:50
@ DT_Int16
16-bit integer data type
Definition DataTypes.h:44
@ DT_Int8
8-bit integer data type
Definition DataTypes.h:55
@ DT_Real3x3
3x3 tensor data type
Definition DataTypes.h:51
@ DT_Int32
32-bit integer data type
Definition DataTypes.h:45
@ DT_Real3
Vector 3 data type.
Definition DataTypes.h:49
@ DT_Float16
'Float16' data type
Definition DataTypes.h:53
@ DT_Int64
64-bit integer data type
Definition DataTypes.h:46
@ DT_BFloat16
'BFloat16' data type
Definition DataTypes.h:52
@ DT_Real2
Vector 2 data type.
Definition DataTypes.h:48
@ DT_Real
Real data type.
Definition DataTypes.h:43
@ DT_Byte
Byte data type.
Definition DataTypes.h:42
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:347
std::int32_t Int32
Signed integer type of 32 bits.
Arcane::BFloat16 BFloat16
Type 'Brain Float16'.
POD structure for a Real2x2.
Definition Real2x2.h:32
POD structure for a Real3x3.
Definition Real3x3.h:32