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