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