Arcane  4.2.3.0
Documentation utilisateur
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.
Classe de base des vecteurs 1D de données.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void clear()
Supprime les éléments du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
const T * data() const
Accès à la racine du tableau hors toute protection.
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.
Definition Hdf5Utils.h:446
Classe d'aide pour rechercher un groupe.
Definition Hdf5Utils.h:324
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*).
Definition Hdf5Utils.h:193
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.
Definition Hdf5Utils.h:403
Encapsule un hid_t.
Definition Hdf5Utils.h:154
Encapsule un dataset simple d'un fichier HDF5 qui représente un tableau.
Definition Hdf5Utils.h:822
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.
Definition Hdf5Utils.h:779
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).
Definition Hdf5Utils.h:868
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.
Definition Hdf5Utils.h:592
HType m_bfloat16_id
Identifiant HDF pour les BFloat16.
Definition Hdf5Utils.h:764
HType m_real2x2_id
Identifiant HDF pour les Real2x2.
Definition Hdf5Utils.h:761
HType m_llong_id
Identifiant HDF des entiers long long signés.
Definition Hdf5Utils.h:754
StandardTypes()
Créé une instance en initialisant les types.
Definition Hdf5Utils.cc:939
HType m_long_id
Identifiant HDF des entiers long signés.
Definition Hdf5Utils.h:753
HType m_ullong_id
Identifiant HDF des entiers long long non signés.
Definition Hdf5Utils.h:757
HType m_int_id
Identifiant HDF des entiers signés.
Definition Hdf5Utils.h:752
HType m_short_id
Identifiant HDF des entiers signés.
Definition Hdf5Utils.h:750
HType m_real3x3_id
Identifiant HDF pour les Real3x3.
Definition Hdf5Utils.h:762
HType m_real_id
Identifiant HDF des réels.
Definition Hdf5Utils.h:758
HType m_ushort_id
Identifiant HDF des entiers long signés.
Definition Hdf5Utils.h:751
HType m_ulong_id
Identifiant HDF des entiers long non signés.
Definition Hdf5Utils.h:756
HType m_schar_id
Identifiant HDF des caractères signés.
Definition Hdf5Utils.h:749
HType m_uchar_id
Identifiant HDF des caractères non-signés.
Definition Hdf5Utils.h:748
HType m_real2_id
Identifiant HDF pour les Real2.
Definition Hdf5Utils.h:759
HType m_float32_id
Identifiant HDF pour les Float32.
Definition Hdf5Utils.h:765
HType m_float16_id
Identifiant HDF pour les Float16.
Definition Hdf5Utils.h:763
HType m_char_id
Identifiant HDF des charactères.
Definition Hdf5Utils.h:747
void initialize()
Initialise les types.
Definition Hdf5Utils.cc:958
HType m_uint_id
Identifiant HDF des entiers non signés.
Definition Hdf5Utils.h:755
HType m_real3_id
Identifiant HDF pour les Real3.
Definition Hdf5Utils.h:760
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.
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.