Arcane  v4.1.7.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
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.
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:424
Classe d'aide pour rechercher un groupe.
Definition Hdf5Utils.h:302
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*).
Definition Hdf5Utils.h:186
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.
Definition Hdf5Utils.h:381
Encapsule un hid_t.
Definition Hdf5Utils.h:147
Encapsule un dataset simple d'un fichier HDF5 qui représente un tableau.
Definition Hdf5Utils.h:798
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:755
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:844
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:570
HType m_bfloat16_id
Identifiant HDF pour les BFloat16.
Definition Hdf5Utils.h:740
HType m_real2x2_id
Identifiant HDF pour les Real2x2.
Definition Hdf5Utils.h:737
StandardTypes()
Créé une instance en initialisant les types.
Definition Hdf5Utils.cc:928
HType m_long_id
Identifiant HDF des entiers long signés.
Definition Hdf5Utils.h:731
HType m_int_id
Identifiant HDF des entiers signés.
Definition Hdf5Utils.h:730
HType m_short_id
Identifiant HDF des entiers signés.
Definition Hdf5Utils.h:728
HType m_real3x3_id
Identifiant HDF pour les Real3x3.
Definition Hdf5Utils.h:738
HType m_real_id
Identifiant HDF des réels.
Definition Hdf5Utils.h:734
HType m_ushort_id
Identifiant HDF des entiers long signés.
Definition Hdf5Utils.h:729
HType m_ulong_id
Identifiant HDF des entiers long non signés.
Definition Hdf5Utils.h:733
HType m_schar_id
Identifiant HDF des caractères signés.
Definition Hdf5Utils.h:727
HType m_uchar_id
Identifiant HDF des caractères non-signés.
Definition Hdf5Utils.h:726
HType m_real2_id
Identifiant HDF pour les Real2.
Definition Hdf5Utils.h:735
HType m_float32_id
Identifiant HDF pour les Float16.
Definition Hdf5Utils.h:741
HType m_float16_id
Identifiant HDF pour les Float16.
Definition Hdf5Utils.h:739
HType m_char_id
Identifiant HDF des charactères.
Definition Hdf5Utils.h:725
void initialize()
Initialise les types.
Definition Hdf5Utils.cc:947
HType m_uint_id
Identifiant HDF des entiers non signés.
Definition Hdf5Utils.h:732
HType m_real3_id
Identifiant HDF pour les Real3.
Definition Hdf5Utils.h:736
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: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