Arcane  4.2.3.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_LLONG);
993 H5Tset_precision(type_id, 8 * sizeof(long long));
994 H5Tset_order(type_id, H5T_ORDER_LE);
995 m_llong_id.setId(type_id);
996 }
997 {
998 hid_t type_id = H5Tcopy(H5T_NATIVE_USHORT);
999 H5Tset_precision(type_id, 8 * sizeof(unsigned short));
1000 H5Tset_order(type_id, H5T_ORDER_LE);
1001 m_ushort_id.setId(type_id);
1002 }
1003 {
1004 hid_t type_id = H5Tcopy(H5T_NATIVE_UINT);
1005 H5Tset_precision(type_id, 8 * sizeof(unsigned int));
1006 H5Tset_order(type_id, H5T_ORDER_LE);
1007 m_uint_id.setId(type_id);
1008 }
1009 {
1010 hid_t type_id = H5Tcopy(H5T_NATIVE_ULONG);
1011 H5Tset_precision(type_id, 8 * sizeof(unsigned long));
1012 H5Tset_order(type_id, H5T_ORDER_LE);
1013 m_ulong_id.setId(type_id);
1014 }
1015 {
1016 hid_t type_id = H5Tcopy(H5T_NATIVE_ULLONG);
1017 H5Tset_precision(type_id, 8 * sizeof(unsigned long long));
1018 H5Tset_order(type_id, H5T_ORDER_LE);
1019 m_ullong_id.setId(type_id);
1020 }
1021 {
1022 hid_t type_id = H5Tcopy(H5T_NATIVE_FLOAT);
1023 H5Tset_precision(type_id, 8 * sizeof(float));
1024 H5Tset_order(type_id, H5T_ORDER_LE);
1025 m_float32_id.setId(type_id);
1026 }
1027 {
1028 hid_t type_id = H5Tcopy(H5T_NATIVE_DOUBLE);
1029 H5Tset_precision(type_id, 8 * sizeof(double));
1030 H5Tset_order(type_id, H5T_ORDER_LE);
1031 m_real_id.setId(type_id);
1032 }
1033 {
1034 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real2POD));
1035 _H5Tinsert(type_id, "X", HOFFSET(Real2POD, x), H5T_NATIVE_DOUBLE);
1036 _H5Tinsert(type_id, "Y", HOFFSET(Real2POD, y), H5T_NATIVE_DOUBLE);
1037 m_real2_id.setId(type_id);
1038 }
1039 {
1040 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real3POD));
1041 _H5Tinsert(type_id, "X", HOFFSET(Real3POD, x), H5T_NATIVE_DOUBLE);
1042 _H5Tinsert(type_id, "Y", HOFFSET(Real3POD, y), H5T_NATIVE_DOUBLE);
1043 _H5Tinsert(type_id, "Z", HOFFSET(Real3POD, z), H5T_NATIVE_DOUBLE);
1044 m_real3_id.setId(type_id);
1045 }
1046 {
1047 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real2x2POD));
1048 _H5Tinsert(type_id, "XX", HOFFSET(Real2x2POD, x.x), H5T_NATIVE_DOUBLE);
1049 _H5Tinsert(type_id, "XY", HOFFSET(Real2x2POD, x.y), H5T_NATIVE_DOUBLE);
1050 _H5Tinsert(type_id, "YX", HOFFSET(Real2x2POD, y.x), H5T_NATIVE_DOUBLE);
1051 _H5Tinsert(type_id, "YY", HOFFSET(Real2x2POD, y.y), H5T_NATIVE_DOUBLE);
1052 m_real2x2_id.setId(type_id);
1053 }
1054 {
1055 hid_t type_id = H5Tcreate(H5T_COMPOUND, sizeof(Real3x3POD));
1056 _H5Tinsert(type_id, "XX", HOFFSET(Real3x3POD, x.x), H5T_NATIVE_DOUBLE);
1057 _H5Tinsert(type_id, "XY", HOFFSET(Real3x3POD, x.y), H5T_NATIVE_DOUBLE);
1058 _H5Tinsert(type_id, "XZ", HOFFSET(Real3x3POD, x.z), H5T_NATIVE_DOUBLE);
1059 _H5Tinsert(type_id, "YX", HOFFSET(Real3x3POD, y.x), H5T_NATIVE_DOUBLE);
1060 _H5Tinsert(type_id, "YY", HOFFSET(Real3x3POD, y.y), H5T_NATIVE_DOUBLE);
1061 _H5Tinsert(type_id, "YZ", HOFFSET(Real3x3POD, y.z), H5T_NATIVE_DOUBLE);
1062 _H5Tinsert(type_id, "ZX", HOFFSET(Real3x3POD, z.x), H5T_NATIVE_DOUBLE);
1063 _H5Tinsert(type_id, "ZY", HOFFSET(Real3x3POD, z.y), H5T_NATIVE_DOUBLE);
1064 _H5Tinsert(type_id, "ZZ", HOFFSET(Real3x3POD, z.z), H5T_NATIVE_DOUBLE);
1065 m_real3x3_id.setId(type_id);
1066 }
1067
1068 // HDF5 1.10 et 1.12 ne supportent pas encore les types 'BFloat16' et 'Float16'.
1069 // Lorsque ce sera le cas, on pourra utiliser le type fourni par HDF5.
1070 // (NOTE: HDF5 1.14.4 supporte Float16)
1071
1072 // Ajoute type opaque pour BFloat16.
1073 {
1074 hid_t type_id = H5Tcopy(H5T_NATIVE_B16);
1075 m_bfloat16_id.setId(type_id);
1076 }
1077 // Ajoute type opaque pour Float16.
1078 {
1079 hid_t type_id = H5Tcopy(H5T_NATIVE_B16);
1080 m_float16_id.setId(type_id);
1081 }
1082}
1083
1084/*---------------------------------------------------------------------------*/
1085/*---------------------------------------------------------------------------*/
1086
1087StandardTypes::
1088~StandardTypes()
1089{
1090}
1091
1092/*---------------------------------------------------------------------------*/
1093/*---------------------------------------------------------------------------*/
1094
1095void StandardTypes::
1096_H5Tinsert(hid_t type, const char* name, Integer offset, hid_t field_id)
1097{
1098 // Mutex géré par initialize.
1099 herr_t herr = H5Tinsert(type, name, offset, field_id);
1100 if (herr < 0) {
1101 ARCANE_FATAL("Can not insert type");
1102 }
1103}
1104/*---------------------------------------------------------------------------*/
1105/*---------------------------------------------------------------------------*/
1106
1107#ifdef ARCANE_REAL_NOT_BUILTIN
1108hid_t StandardTypes::
1109nativeType(Real) const
1110{
1111 ARCANE_FATAL("Real is a complex type");
1112}
1113#endif
1114
1115hid_t StandardTypes::
1116saveType(eDataType sd) const
1117{
1118 switch (sd) {
1119 case DT_Byte:
1120 return saveType(Byte());
1121 case DT_Real:
1122 return saveType(Real());
1123 case DT_Real2:
1124 return saveType(Real2());
1125 case DT_Real2x2:
1126 return saveType(Real2x2());
1127 case DT_Real3:
1128 return saveType(Real3());
1129 case DT_Real3x3:
1130 return saveType(Real3x3());
1131 case DT_Int8:
1132 return saveType(Int8());
1133 case DT_Int16:
1134 return saveType(Int16());
1135 case DT_Int32:
1136 return saveType(Int32());
1137 case DT_Int64:
1138 return saveType(Int64());
1139 case DT_Float32:
1140 return saveType(Float32());
1141 case DT_Float16:
1142 return saveType(Float16());
1143 case DT_BFloat16:
1144 return saveType(BFloat16());
1145 default:
1146 throw ArgumentException(String::format("Bad type '{0}'", sd));
1147 }
1148}
1149
1150/*---------------------------------------------------------------------------*/
1151/*---------------------------------------------------------------------------*/
1152
1153hid_t StandardTypes::
1154nativeType(eDataType sd) const
1155{
1156 switch (sd) {
1157 case DT_Byte:
1158 return nativeType(Byte());
1159 case DT_Real:
1160 return nativeType(Real());
1161 case DT_Real2:
1162 return nativeType(Real2());
1163 case DT_Real2x2:
1164 return nativeType(Real2x2());
1165 case DT_Real3:
1166 return nativeType(Real3());
1167 case DT_Real3x3:
1168 return nativeType(Real3x3());
1169 case DT_Int8:
1170 return nativeType(Int8());
1171 case DT_Int16:
1172 return nativeType(Int16());
1173 case DT_Int32:
1174 return nativeType(Int32());
1175 case DT_Int64:
1176 return nativeType(Int64());
1177 case DT_Float32:
1178 return nativeType(Float32());
1179 case DT_Float16:
1180 return nativeType(Float16());
1181 case DT_BFloat16:
1182 return nativeType(BFloat16());
1183 default:
1184 throw ArgumentException(String::format("Bad type '{0}'", sd));
1185 }
1186}
1187
1188/*---------------------------------------------------------------------------*/
1189/*---------------------------------------------------------------------------*/
1190
1191/*---------------------------------------------------------------------------*/
1192/*---------------------------------------------------------------------------*/
1193
1194StandardArray::
1195StandardArray(hid_t hfile, const String& hpath)
1196: m_hfile(hfile)
1197, m_hpath(hpath)
1198, m_ids_hpath(hpath + "_Ids")
1199, m_is_init(false)
1200{
1201}
1202
1203/*---------------------------------------------------------------------------*/
1204/*---------------------------------------------------------------------------*/
1205
1206void StandardArray::
1207readDim()
1208{
1209 if (m_is_init)
1210 return;
1211 m_is_init = true;
1212 m_hdataset.open(m_hfile, m_hpath);
1213 HSpace hspace(m_hdataset.getSpace());
1214 {
1215 const int max_dim = 256; // Nombre maxi de dimensions des tableaux HDF
1216 hsize_t hdf_dims[max_dim];
1217 hsize_t max_dims[max_dim];
1218 int nb_dim = -1;
1219 {
1220 ARCANE_HDF5_MUTEX;
1221 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1222 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1223 }
1224 for (Integer i = 0; i < nb_dim; ++i) {
1225 //cerr << "** DIM i=" << i << " hdim=" << hdf_dims[i]
1226 // << " max=" << max_dims[i] << '\n';
1227 m_dimensions.add((Int64)hdf_dims[i]);
1228 }
1229 }
1230 // Vérifie s'il existe une variable suffixée '_Ids' contenant les numéros
1231 // uniques des entités
1232 m_ids_dataset.openIfExists(m_hfile, m_ids_hpath);
1233 //cout << "TRY OPEN ID DATASET path=" << m_ids_hpath << " r=" << m_ids_dataset.id()>0 << '\n';
1234}
1235
1236/*---------------------------------------------------------------------------*/
1237/*---------------------------------------------------------------------------*/
1238
1240setIdsPath(const String& ids_path)
1241{
1242 m_ids_hpath = ids_path;
1243}
1244
1245/*---------------------------------------------------------------------------*/
1246/*---------------------------------------------------------------------------*/
1247
1248void StandardArray::
1249_write(const void* buffer, Integer nb_element, hid_t save_type, hid_t native_type)
1250{
1251 if (!m_is_init) {
1252 hsize_t dims[1];
1253 dims[0] = nb_element;
1254
1255 HSpace hspace;
1256 hspace.createSimple(1, dims);
1257 if (hspace.isBad())
1258 ARCANE_THROW(IOException, "Can not create space");
1259
1260 m_dimensions.clear();
1261 m_dimensions.add(nb_element);
1262
1263 m_hdataset.recursiveCreate(m_hfile, m_hpath, save_type, hspace, H5P_DEFAULT);
1264 if (m_hdataset.isBad())
1265 ARCANE_THROW(IOException, "Can not create dataset");
1266
1267 m_is_init = true;
1268 }
1269
1270 m_hdataset.write(native_type, buffer);
1271}
1272
1273/*---------------------------------------------------------------------------*/
1274/*---------------------------------------------------------------------------*/
1275
1276bool StandardArray::
1277exists() const
1278{
1279 HDataset dataset;
1280 dataset.openIfExists(m_hfile, m_hpath);
1281 return dataset.id() > 0;
1282}
1283
1284/*---------------------------------------------------------------------------*/
1285/*---------------------------------------------------------------------------*/
1286
1287template <typename DataType> StandardArrayT<DataType>::
1288StandardArrayT(hid_t hfile, const String& hpath)
1289: StandardArray(hfile, hpath)
1290{
1291}
1292
1293/*---------------------------------------------------------------------------*/
1294/*---------------------------------------------------------------------------*/
1295
1296template <typename DataType> void StandardArrayT<DataType>::
1298{
1299 m_hdataset.readWithException(st.nativeType(DataType()), buffer.data());
1300}
1301
1302/*---------------------------------------------------------------------------*/
1303/*---------------------------------------------------------------------------*/
1304
1305template <typename DataType> void StandardArrayT<DataType>::
1307{
1308 readDim();
1309 buffer.resize(m_dimensions[0]);
1310 read(st, buffer);
1311}
1312
1313/*---------------------------------------------------------------------------*/
1314/*---------------------------------------------------------------------------*/
1315
1316template <typename DataType> void StandardArrayT<DataType>::
1318{
1319 bool is_master = pm->isMasterIO();
1320 Integer master_rank = pm->masterIORank();
1321 bool has_ids = false;
1322 if (is_master) {
1323 read(st, buffer);
1324 Integer buf_size = buffer.size();
1325 if (m_ids_dataset.id() > 0) {
1326 has_ids = true;
1327 m_ids_dataset.read(st.nativeType(Int64()), unique_ids.data());
1328 }
1329 Integer infos[2];
1330 infos[0] = buf_size;
1331 infos[1] = has_ids ? 1 : 0;
1332 IntegerArrayView iav(2, infos);
1333 pm->broadcast(iav, master_rank);
1334 pm->broadcast(buffer, master_rank);
1335 pm->broadcast(unique_ids, master_rank);
1336 }
1337 else {
1338 Integer infos[2];
1339 IntegerArrayView iav(2, infos);
1340 pm->broadcast(iav, master_rank);
1341 Integer buf_size = infos[0];
1342 has_ids = infos[1] != 0;
1343 buffer.resize(buf_size);
1344 unique_ids.resize(buf_size);
1345 pm->broadcast(buffer, master_rank);
1346 pm->broadcast(unique_ids, master_rank);
1347 }
1348 if (!has_ids) {
1349 for (Integer i = 0, is = unique_ids.size(); i < is; ++i)
1350 unique_ids[i] = i;
1351 }
1352}
1353
1354/*---------------------------------------------------------------------------*/
1355/*---------------------------------------------------------------------------*/
1356
1357template <typename DataType> void StandardArrayT<DataType>::
1358write(StandardTypes& st, ConstArrayView<DataType> buffer)
1359{
1360 Integer nb_element = buffer.size();
1361 _write(buffer.data(), nb_element, st.saveType(DataType()), st.nativeType(DataType()));
1362}
1363
1364/*---------------------------------------------------------------------------*/
1365/*---------------------------------------------------------------------------*/
1366
1367template <typename DataType> void StandardArrayT<DataType>::
1368_writeSortedValues(ITraceMng* tm, StandardTypes& st,
1369 ConstArrayView<DataType> buffer,
1370 Int64ConstArrayView unique_ids)
1371{
1372 ARCANE_UNUSED(tm);
1373
1374 Integer total_size = buffer.size();
1375 Integer nb_element = unique_ids.size();
1376 Integer dim2_size = 1;
1377 if (nb_element != total_size) {
1378 if (nb_element == 0)
1379 ARCANE_THROW(ArgumentException, "unique_ids size is zero but not buffer size ({0})",
1380 total_size);
1381 dim2_size = total_size / nb_element;
1382 if (dim2_size * nb_element != total_size)
1383 ARCANE_THROW(ArgumentException, "buffer size ({0}) is not a multiple of unique_ids size ({1})",
1384 total_size, nb_element);
1385 }
1386
1387 UniqueArray<ValueWithUid> values_to_sort(nb_element);
1388 UniqueArray<DataType> out_buffer(total_size);
1389 //tm->info() << " WRITE total_size=" << total_size
1390 //<< " uid_size=" << unique_ids.size();
1391 for (Integer i = 0; i < nb_element; ++i) {
1392 values_to_sort[i].m_uid = unique_ids[i];
1393 values_to_sort[i].m_index = i;
1394 //values_to_sort[i].m_value = buffer[i];
1395 //tm->info() << "BEFORE SORT i=" << i << " uid=" << unique_ids[i];
1396 }
1397 std::sort(std::begin(values_to_sort), std::end(values_to_sort));
1398 for (Integer i = 0; i < nb_element; ++i) {
1399 Integer old_index = values_to_sort[i].m_index;
1400 for (Integer j = 0; j < dim2_size; ++j) {
1401 Integer pos = (i * dim2_size) + j;
1402 out_buffer[pos] = buffer[(old_index * dim2_size) + j];
1403 //tm->info() << "AFTER SORT i=" << i << " uid=" << values_to_sort[i].m_uid
1404 // << " j=" << j << " pos=" << pos
1405 // << " value=" << out_buffer[pos];
1406 }
1407 }
1408 write(st, out_buffer);
1409}
1410
1411/*---------------------------------------------------------------------------*/
1412/*---------------------------------------------------------------------------*/
1413
1414template <typename DataType> void StandardArrayT<DataType>::
1415parallelWrite(IParallelMng* pm, StandardTypes& st,
1416 ConstArrayView<DataType> buffer, Int64ConstArrayView unique_ids)
1417{
1418 //TODO:
1419 // Pour l'instant, seul le proc maitre ecrit.
1420 // Il recupère toutes les valeurs, les trie par uniqueId croissant
1421 // et les écrit.
1422 // Il est important que tout soit trié par ordre croissant car
1423 // cela permet de garder le même ordre d'écriture même en présence
1424 // de repartitionnement du maillage. La relecture considère
1425 // que cette contrainte est respectée et ne relit les informations
1426 // des uniqueId qu'au démarrage du cas.
1427 bool is_parallel = pm->isParallel();
1428 ITraceMng* tm = pm->traceMng();
1429
1430 if (!is_parallel) {
1431 _writeSortedValues(tm, st, buffer, unique_ids);
1432 return;
1433 }
1434
1435 bool is_master = pm->isMasterIO();
1436 Integer master_rank = pm->masterIORank();
1437 Integer nb_rank = pm->commSize();
1438 Integer buf_size = buffer.size();
1439 Integer unique_id_size = unique_ids.size();
1440 IntegerUniqueArray rank_sizes(2 * nb_rank);
1441 // Le sous-domaine maitre récupère les infos de tous les autres.
1442 // Si un sous-domaine n'a pas d'éléments à envoyer, il ne fait rien
1443 // (on n'envoie pas de buffers vides)
1444 if (is_master) {
1445 Integer buf[2];
1446 buf[0] = buf_size;
1447 buf[1] = unique_id_size;
1448 IntegerArrayView iav(2, buf);
1449 pm->allGather(iav, rank_sizes);
1450
1451 Integer buffer_total_size = 0;
1452 Integer unique_id_total_size = 0;
1453 IntegerUniqueArray buffer_rank_index(nb_rank);
1454 IntegerUniqueArray unique_id_rank_index(nb_rank);
1455
1456 for (Integer i = 0; i < nb_rank; ++i) {
1457 buffer_rank_index[i] = buffer_total_size;
1458 buffer_total_size += rank_sizes[(i * 2)];
1459 unique_id_rank_index[i] = unique_id_total_size;
1460 unique_id_total_size += rank_sizes[(i * 2) + 1];
1461 }
1462
1463 UniqueArray<DataType> full_buffer(buffer_total_size);
1464 Int64UniqueArray full_unique_ids(unique_id_total_size);
1465
1466 for (Integer i = 0; i < nb_rank; ++i) {
1467 // Ne recoit pas de valeurs des processus n'ayant pas de valeurs
1468 if (rank_sizes[(i * 2)] == 0)
1469 continue;
1470 ArrayView<DataType> local_buf(rank_sizes[(i * 2)], &full_buffer[buffer_rank_index[i]]);
1471 Int64ArrayView local_unique_ids(rank_sizes[(i * 2) + 1], &full_unique_ids[unique_id_rank_index[i]]);
1472 if (i == master_rank) {
1473 local_buf.copy(buffer);
1474 local_unique_ids.copy(unique_ids);
1475 }
1476 else {
1477 pm->recv(local_buf, i);
1478 pm->recv(local_unique_ids, i);
1479 }
1480 }
1481 tm->info(5) << "PARALLEL WRITE path=" << m_hpath << " total_size=" << full_buffer.size();
1482 _writeSortedValues(tm, st, full_buffer, full_unique_ids);
1483 }
1484 else {
1485 Integer buf[2];
1486 buf[0] = buf_size;
1487 buf[1] = unique_id_size;
1488 IntegerArrayView iav(2, buf);
1489 pm->allGather(iav, rank_sizes);
1490 // Pas la peine d'envoyer des buffers vides
1491 if (buffer.size() > 0) {
1492 pm->send(buffer, master_rank);
1493 pm->send(unique_ids, master_rank);
1494 }
1495 }
1496}
1497
1498/*---------------------------------------------------------------------------*/
1499/*---------------------------------------------------------------------------*/
1500
1501template class StandardArrayT<Real>;
1502template class StandardArrayT<Real3>;
1503template class StandardArrayT<Real3x3>;
1504template class StandardArrayT<Real2>;
1505template class StandardArrayT<Real2x2>;
1506template class StandardArrayT<Int16>;
1507template class StandardArrayT<Int32>;
1508template class StandardArrayT<Int64>;
1509template class StandardArrayT<Byte>;
1510template class StandardArrayT<Int8>;
1511template class StandardArrayT<Float32>;
1512// NOTE: on ne peut pas encore instantier ces types car ils nécessitent
1513// de pouvoir faire des send/receive via le IParallelMng et cela n'est pas
1514// encore implémenté.
1515//template class StandardArrayT<Float16>;
1516//template class StandardArrayT<BFloat16>;
1517
1518/*---------------------------------------------------------------------------*/
1519/*---------------------------------------------------------------------------*/
1520
1521template <typename DataType> DataType
1524{
1525 Hdf5Utils::HDataset m_hdataset;
1526 m_hdataset.open(m_hfile, m_hpath);
1527 Hdf5Utils::HSpace hspace(m_hdataset.getSpace());
1528 {
1529 const int max_dim = 256; // Nombre maxi de dimensions des tableaux HDF
1530 hsize_t hdf_dims[max_dim];
1531 hsize_t max_dims[max_dim];
1532 int nb_dim = -1;
1533 {
1534 ARCANE_HDF5_MUTEX;
1535 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1536 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1537 }
1538 if (nb_dim != 1 || hdf_dims[0] != 1)
1539 ARCANE_THROW(IOException, "Cannot read non scalar");
1540 }
1541
1542 DataType dummy;
1543 m_hdataset.read(st.nativeType(DataType()), &dummy);
1544 return dummy;
1545}
1546
1547/*---------------------------------------------------------------------------*/
1548
1549template <> String
1552{
1553 ByteUniqueArray utf8_bytes;
1554
1555 Hdf5Utils::HDataset m_hdataset;
1556 m_hdataset.open(m_hfile, m_hpath);
1557 Hdf5Utils::HSpace hspace(m_hdataset.getSpace());
1558 {
1559 const int max_dim = 256; // Nombre maxi de dimensions des tableaux HDF
1560 hsize_t hdf_dims[max_dim];
1561 hsize_t max_dims[max_dim];
1562 int nb_dim = -1;
1563 {
1564 ARCANE_HDF5_MUTEX;
1565 nb_dim = H5Sget_simple_extent_ndims(hspace.id());
1566 H5Sget_simple_extent_dims(hspace.id(), hdf_dims, max_dims);
1567 }
1568
1569 if (nb_dim != 1)
1570 ARCANE_THROW(IOException, "Cannot read multidim string");
1571 utf8_bytes.resize(hdf_dims[0]);
1572 }
1573
1574 m_hdataset.read(st.nativeType(Byte()), utf8_bytes.data());
1575 return String(utf8_bytes);
1576}
1577
1578/*---------------------------------------------------------------------------*/
1579
1580template <typename DataType> void
1582write(Hdf5Utils::StandardTypes& st, const DataType& t)
1583{
1584 hsize_t dims[1] = { 1 };
1585 Hdf5Utils::HSpace hspace;
1586 hspace.createSimple(1, dims);
1587 if (hspace.isBad())
1588 ARCANE_THROW(IOException, "Can not create space");
1589
1590 Hdf5Utils::HDataset m_hdataset;
1591 m_hdataset.recursiveCreate(m_hfile, m_hpath, st.saveType(DataType()), hspace, H5P_DEFAULT);
1592 if (m_hdataset.isBad())
1593 ARCANE_THROW(IOException, "Can not create dataset");
1594
1595 herr_t herr = m_hdataset.write(st.nativeType(DataType()), &t);
1596 if (herr < 0)
1597 ARCANE_THROW(IOException, "Cannot write data");
1598}
1599
1600/*---------------------------------------------------------------------------*/
1601
1602template <> void
1605{
1606 ByteConstArrayView utf8_bytes = s.utf8();
1607
1608 hsize_t dims[1];
1609 dims[0] = utf8_bytes.size() + 1;
1610
1611 Hdf5Utils::HSpace hspace;
1612 hspace.createSimple(1, dims);
1613 if (hspace.isBad())
1614 ARCANE_THROW(IOException, "Can not create space");
1615
1616 Hdf5Utils::HDataset m_hdataset;
1617 m_hdataset.recursiveCreate(m_hfile, m_hpath, st.saveType(Byte()), hspace, H5P_DEFAULT);
1618 if (m_hdataset.isBad())
1619 ARCANE_THROW(IOException, "Can not create dataset");
1620
1621 herr_t herr = m_hdataset.write(st.nativeType(Byte()), utf8_bytes.data());
1622 if (herr < 0)
1623 ARCANE_THROW(IOException, "Cannot write data");
1624}
1625
1626/*---------------------------------------------------------------------------*/
1627
1628template class StandardScalarT<String>;
1629template class StandardScalarT<Real>;
1630template class StandardScalarT<Real3>;
1631template class StandardScalarT<Real3x3>;
1632template class StandardScalarT<Real2>;
1633template class StandardScalarT<Real2x2>;
1634template class StandardScalarT<Int16>;
1635template class StandardScalarT<Int32>;
1636template class StandardScalarT<Int64>;
1637template class StandardScalarT<Byte>;
1638template class StandardScalarT<Int8>;
1639template class StandardScalarT<Float16>;
1640template class StandardScalarT<BFloat16>;
1641template class StandardScalarT<Float32>;
1642
1643/*---------------------------------------------------------------------------*/
1644/*---------------------------------------------------------------------------*/
1645
1646} // namespace Arcane::Hdf5Utils
1647
1648/*---------------------------------------------------------------------------*/
1649/*---------------------------------------------------------------------------*/
#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.
HType m_llong_id
Identifiant HDF des entiers long long signés.
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_ullong_id
Identifiant HDF des entiers long long non 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 Float32.
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.