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