Arcane  4.1.11.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
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.
Classe de base des vecteurs 1D de données.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void clear()
Supprime les éléments du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
const T * data() const
Accès à la racine du tableau hors toute protection.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Classe template pour convertir un type.
Encapsule un hid_t pour un dataset.
Definition Hdf5Utils.h:446
Classe d'aide pour rechercher un groupe.
Definition Hdf5Utils.h:324
static void useMutex(bool is_active, IParallelMng *pm)
Fonction permettant d'activer ou de désactiver les verrous à chaque appel à HDF5.
Definition Hdf5Utils.cc:90
Encapsule un hid_t pour une propriété (H5P*).
Definition Hdf5Utils.h:193
void createDatasetTransfertCollectiveMPIIO()
Créé une propriété de dataset pour MPIIO.
Definition Hdf5Utils.cc:898
void createFilePropertyMPIIO(IParallelMng *pm)
Créé une propriété de fichier pour MPIIO.
Definition Hdf5Utils.cc:877
void createDatasetTransfertIndependentMPIIO()
Créé une propriété de dataset pour MPIIO.
Definition Hdf5Utils.cc:917
Encapsule un hid_t pour un dataspace.
Definition Hdf5Utils.h:403
Encapsule un hid_t.
Definition Hdf5Utils.h:154
Encapsule un dataset simple d'un fichier HDF5 qui représente un tableau.
Definition Hdf5Utils.h:820
void read(StandardTypes &st, ArrayView< DataType > buffer)
Lit le dataset d'un tableau 1D. Cette opération n'est valide qu'après un appel à readDim()....
void directRead(StandardTypes &st, Array< DataType > &buffer)
Lit le dataset d'un tableau 1D.
Encapsule un dataset simple d'un fichier HDF5 qui représente un tableau.
Definition Hdf5Utils.h:777
void setIdsPath(const String &ids_path)
En lecture, positionne le chemin dans hfile du dataset contenant les unique_ids.
Encapsule un dataset simple d'un fichier HDF5 qui représente un scalaire (éventuellement String).
Definition Hdf5Utils.h:866
DataType read(Hdf5Utils::StandardTypes &st)
Lit une donnée.
void write(Hdf5Utils::StandardTypes &st, const DataType &t)
Ecrit une donnée.
Définition des types standards Arcane pour hdf5.
Definition Hdf5Utils.h:592
HType m_bfloat16_id
Identifiant HDF pour les BFloat16.
Definition Hdf5Utils.h:762
HType m_real2x2_id
Identifiant HDF pour les Real2x2.
Definition Hdf5Utils.h:759
StandardTypes()
Créé une instance en initialisant les types.
Definition Hdf5Utils.cc:939
HType m_long_id
Identifiant HDF des entiers long signés.
Definition Hdf5Utils.h:753
HType m_int_id
Identifiant HDF des entiers signés.
Definition Hdf5Utils.h:752
HType m_short_id
Identifiant HDF des entiers signés.
Definition Hdf5Utils.h:750
HType m_real3x3_id
Identifiant HDF pour les Real3x3.
Definition Hdf5Utils.h:760
HType m_real_id
Identifiant HDF des réels.
Definition Hdf5Utils.h:756
HType m_ushort_id
Identifiant HDF des entiers long signés.
Definition Hdf5Utils.h:751
HType m_ulong_id
Identifiant HDF des entiers long non signés.
Definition Hdf5Utils.h:755
HType m_schar_id
Identifiant HDF des caractères signés.
Definition Hdf5Utils.h:749
HType m_uchar_id
Identifiant HDF des caractères non-signés.
Definition Hdf5Utils.h:748
HType m_real2_id
Identifiant HDF pour les Real2.
Definition Hdf5Utils.h:757
HType m_float32_id
Identifiant HDF pour les Float16.
Definition Hdf5Utils.h:763
HType m_float16_id
Identifiant HDF pour les Float16.
Definition Hdf5Utils.h:761
HType m_char_id
Identifiant HDF des charactères.
Definition Hdf5Utils.h:747
void initialize()
Initialise les types.
Definition Hdf5Utils.cc:958
HType m_uint_id
Identifiant HDF des entiers non signés.
Definition Hdf5Utils.h:754
HType m_real3_id
Identifiant HDF pour les Real3.
Definition Hdf5Utils.h:758
Exception lorsqu'une erreur d'entrée/sortie est détectée.
Definition IOException.h:32
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual bool isMasterIO() const =0
true si l'instance est un gestionnaire maître des entrées/sorties.
virtual Integer masterIORank() const =0
Rang de l'instance gérant les entrées/sorties (pour laquelle isMasterIO() est vrai)
virtual void * getMPICommunicator()=0
Adresse du communicateur MPI associé à ce gestionnaire.
Chaîne de caractères unicode.
ByteConstArrayView utf8() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:276
Integer len(const char *s)
Retourne la longueur de la chaîne s.
Fonctions utilitaires pour Hdf5.
Definition Hdf5Utils.cc: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