Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
Hdf5VariableWriter.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/* Hdf5VariableWriter.cc (C) 2000-2023 */
9/* */
10/* Writing variables in HDF5 format. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/ScopedPtr.h"
17#include "arcane/utils/Array.h"
18#include "arcane/utils/StringBuilder.h"
19#include "arcane/utils/NotImplementedException.h"
20#include "arcane/utils/StringBuilder.h"
21
22#include "arcane/core/AbstractService.h"
23#include "arcane/core/IRessourceMng.h"
24#include "arcane/core/BasicTimeLoopService.h"
25#include "arcane/core/IVariableWriter.h"
26#include "arcane/core/IXmlDocumentHolder.h"
27#include "arcane/core/IIOMng.h"
28#include "arcane/core/IMesh.h"
29#include "arcane/core/PostProcessorWriterBase.h"
30#include "arcane/core/IDataWriter.h"
31#include "arcane/core/IParallelMng.h"
32#include "arcane/core/Directory.h"
33#include "arcane/core/VariableCollection.h"
34#include "arcane/core/IMeshMng.h"
35
36#include "arcane/utils/Collection.h"
37
38#include "arcane/hdf5/Hdf5VariableWriter_axl.h"
39#include "arcane/hdf5/Hdf5VariableInfoBase.h"
40
41#include <set>
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
46namespace Arcane
47{
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
52using namespace Hdf5Utils;
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
57class Hdf5VariableWriterHelper
58: public TraceAccessor
59{
60 public:
61
62 Hdf5VariableWriterHelper(IMesh* mesh, const String& xml_filename)
63 : TraceAccessor(mesh->traceMng())
64 , m_mesh(mesh)
65 , m_xml_file_name(xml_filename)
66 {
67 }
68 virtual ~Hdf5VariableWriterHelper() {}
69
70 public:
71
72 virtual void open();
73 virtual void notifyRestore() {}
74 virtual void writeOnExit();
75
76 private:
77
78 IMesh* m_mesh;
79 String m_xml_file_name;
80 String m_hdf5_file_name;
83 ScopedPtrT<IXmlDocumentHolder> m_xml_document_holder;
85};
86
87/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89
90void Hdf5VariableWriterHelper::
91open()
92{
93 IIOMng* io_mng = m_mesh->parallelMng()->ioMng();
94 m_xml_document_holder = io_mng->parseXmlFile(m_xml_file_name);
95 if (!m_xml_document_holder.get())
96 fatal() << "Can not read file '" << m_xml_file_name << "'";
97
98 XmlNode root_element = m_xml_document_holder->documentNode().documentElement();
99 m_hdf5_file_name = root_element.attrValue("file-name", true);
100
101 // Reading variables for final outputs
102 {
103 XmlNodeList variables_elem = root_element.children("exit-variable");
104 for (XmlNode elem : variables_elem) {
105 String var_name = elem.attrValue("name", true);
106 String var_family = elem.attrValue("family", true);
107 String var_path = elem.attrValue("path", true);
108 info() << "VARIABLE: name=" << var_name << " path=" << var_path
109 << " family=" << var_family;
110 Hdf5VariableInfoBase* var_info = Hdf5VariableInfoBase::create(m_mesh, var_name, var_family);
111 var_info->setPath(var_path);
112 m_exit_variables.add(var_info);
113 }
114 }
115}
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
120void Hdf5VariableWriterHelper::
121writeOnExit()
122{
123 //TODO throw exception in case of error.
124 HFile hfile;
125
126 if (m_mesh->parallelMng()->isMasterIO()) {
127 hfile.openTruncate(m_hdf5_file_name);
128 }
129
130 std::set<ItemGroup> groups_to_write;
131 for (Integer iz = 0, izs = m_exit_variables.size(); iz < izs; ++iz) {
132 Hdf5VariableInfoBase* vi = m_exit_variables[iz];
133 groups_to_write.insert(vi->variable()->itemGroup());
134 vi->writeVariable(hfile, m_types);
135 }
136}
137
138/*---------------------------------------------------------------------------*/
139/*---------------------------------------------------------------------------*/
143class Hdf5VariableWriter
145{
146 public:
147
148 Hdf5VariableWriter(const ServiceBuildInfo& sbi);
149 ~Hdf5VariableWriter();
150
151 public:
152
153 void build() override {}
154 void onTimeLoopStartInit() override
155 {
156 IMeshMng* mm = subDomain()->meshMng();
157 for (Integer i = 0, is = options()->write.size(); i < is; ++i) {
158 String file_name = options()->write[i]->fileName();
159 String mesh_name = options()->write[i]->meshName();
160 info() << "Hdf5VariableWriter: FILE_INFO: mesh=" << mesh_name << " file_name=" << file_name;
161 {
162 MeshHandle mesh_handle = mm->findMeshHandle(mesh_name);
163 Hdf5VariableWriterHelper* sd = new Hdf5VariableWriterHelper(mesh_handle.mesh(), file_name);
164 m_writers.add(sd);
165 }
166 }
167 info() << "Hdf5VariableWriter: Nb writer =" << m_writers.size();
168 for (Integer i = 0, is = m_writers.size(); i < is; ++i) {
169 m_writers[i]->open();
170 }
171 }
172 void onTimeLoopExit() override
173 {
174 info() << "Hdf5VariableWriter: End loop";
175 for (Integer i = 0, is = m_writers.size(); i < is; ++i) {
176 m_writers[i]->writeOnExit();
177 }
178 }
179 void onTimeLoopRestore() override
180 {
181 for (Integer i = 0, is = m_writers.size(); i < is; ++i) {
182 m_writers[i]->notifyRestore();
183 }
184 }
185 void onTimeLoopBeginLoop() override {}
186
187 private:
188
189 UniqueArray<Hdf5VariableWriterHelper*> m_writers;
190};
191
192/*---------------------------------------------------------------------------*/
193/*---------------------------------------------------------------------------*/
194
195Hdf5VariableWriter::
196Hdf5VariableWriter(const ServiceBuildInfo& sbi)
198{
199}
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203
204Hdf5VariableWriter::
205~Hdf5VariableWriter()
206{
207 for (Integer i = 0, is = m_writers.size(); i < is; ++i)
208 delete m_writers[i];
209 m_writers.clear();
210}
211
212/*---------------------------------------------------------------------------*/
213/*---------------------------------------------------------------------------*/
214
215class ManualHdf5DataWriter
216: public TraceAccessor
217, public IDataWriter
218{
219 typedef std::set<ItemGroup> ItemGroupSet;
220
221 public:
222
223 ManualHdf5DataWriter(IParallelMng* pm, Integer index, const String& directory_name,
224 const String& file_name)
225 : TraceAccessor(pm->traceMng())
226 , m_parallel_mng(pm)
227 , m_index(index)
228 , m_directory_name(directory_name)
229 , m_file_name(file_name)
230 {
231 }
232
233 public:
234
235 virtual void beginWrite(const VariableCollection& vars)
236 {
237 info(4) << "BEGIN WRITE N=" << vars.count() << " INDEX=" << m_index << " directory=" << m_directory_name;
238 Directory out_dir(m_directory_name);
239 String full_filename = out_dir.file(m_file_name);
240 info(4) << "OUT FILE_NAME=" << full_filename;
241 if (m_parallel_mng->isMasterIO()) {
242 if (m_index <= 1) {
243 m_hdf_file.openTruncate(full_filename);
244 }
245 else
246 m_hdf_file.openAppend(full_filename);
247 }
248 m_saved_groups.clear();
249 }
250 virtual void endWrite()
251 {
252 }
253 virtual void setMetaData(const String& meta_data)
254 {
255 ARCANE_UNUSED(meta_data);
256 }
257 virtual void write(IVariable* var, IData* data)
258 {
259 ARCANE_UNUSED(data);
260 info(4) << "WRITE VAR name=" << var->fullName();
261 String index_path = String("Index") + m_index;
262 StringBuilder path = index_path;
263 path += "/Variables/";
264 path += var->fullName();
265
266 ScopedPtrT<Hdf5VariableInfoBase> var_info(Hdf5VariableInfoBase::create(var));
267 var_info->setPath(path);
268 var_info->writeVariable(m_hdf_file, m_hdf5_types);
269 if (m_index == 1) {
270 // HACK: for now, only save group info during the first protection
271 // Normally, this should be specified by the API.
272 ItemGroup group = var->itemGroup();
273 if (!group.null() && m_saved_groups.find(group) == m_saved_groups.end()) {
274 Integer save_type = Hdf5VariableInfoBase::SAVE_IDS + Hdf5VariableInfoBase::SAVE_COORDS;
275 String group_path = index_path + "/Groups/" + group.name();
276 var_info->writeGroup(m_hdf_file, m_hdf5_types, group_path, save_type);
277 }
278 m_saved_groups.insert(group);
279 }
280 }
281
282 void writeInfos(ByteConstArrayView bytes)
283 {
284 Hdf5Utils::StandardArrayT<Byte> v(m_hdf_file.id(), "Infos");
285 v.write(m_hdf5_types, bytes);
286 }
287
288 private:
289
290 Hdf5Utils::StandardTypes m_hdf5_types;
291 IParallelMng* m_parallel_mng;
292 Integer m_index;
293 String m_directory_name;
294 String m_file_name;
295 HFile m_hdf_file;
296 std::set<ItemGroup> m_saved_groups;
297};
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
304class ManualHdf5VariableWriter
305: public PostProcessorWriterBase
306{
307 public:
308
309 ManualHdf5VariableWriter(const ServiceBuildInfo& sbi);
310 ~ManualHdf5VariableWriter();
311
312 public:
313
314 virtual void build()
315 {
316 }
317
319 virtual IDataWriter* dataWriter() { return m_writer; }
320
322 virtual void notifyBeginWrite()
323 {
324 _setFileName();
326 Integer index = times().size();
327 info() << "Hdf5VariableWriter: nb_vars=" << variables.count() << " index=" << index;
328 m_writer = new ManualHdf5DataWriter(subDomain()->parallelMng(), index, baseDirectoryName(), m_file_name);
329 }
330
332 virtual void notifyEndWrite()
333 {
334 // Writes the XML file containing time and variable information
335 bool is_master = subDomain()->parallelMng()->isMasterIO();
336 if (is_master) {
337 IApplication* app = subDomain()->application();
339 XmlNode doc = info_doc->documentNode();
340 XmlElement root_element = XmlElement(doc, "hdf5");
341 root_element.setAttrValue("file-name", m_file_name);
343 RealConstArrayView my_times = times();
344 for (VariableCollection::Enumerator ivar(variables); ++ivar;) {
345 IVariable* var = *ivar;
346 // Only handles variables on mesh entities.
347 if (var->itemKind() == IK_Unknown)
348 continue;
349 XmlNode x = root_element.createAndAppendElement("time-variable");
350 x.setAttrValue("name", var->name());
351 x.setAttrValue("family", var->itemFamilyName());
352 for (Integer i = 0, n = my_times.size(); i < n; ++i) {
353 XmlNode tx = x.createAndAppendElement("time-value");
354 String index_path = String::format("Index{0}/Variables/{1}", i + 1, var->fullName());
355 tx.setAttrValue("path", index_path);
356 tx.setAttrValue("global-time", String::fromNumber(my_times[i]));
357 }
358 }
359 ByteUniqueArray xml_bytes;
360 info_doc->save(xml_bytes);
361 if (m_writer)
362 m_writer->writeInfos(xml_bytes);
363 app->ioMng()->writeXmlFile(info_doc.get(), "toto.xml");
364 // The XML file must be written into the hdf5 file.
365 }
366 delete m_writer;
367 m_writer = 0;
368 }
369
371 virtual void close() {}
372
373 private:
374
375 ManualHdf5DataWriter* m_writer;
376 String m_file_name;
377
378 private:
379
380 void _setFileName()
381 {
382 String base_file_name = baseFileName();
383 if (base_file_name.null())
384 base_file_name = "data";
385 m_file_name = base_file_name + ".h5";
386 }
387};
388
389/*---------------------------------------------------------------------------*/
390/*---------------------------------------------------------------------------*/
391
392ManualHdf5VariableWriter::
393ManualHdf5VariableWriter(const ServiceBuildInfo& sbi)
395, m_writer(0)
396{
397}
398
399/*---------------------------------------------------------------------------*/
400/*---------------------------------------------------------------------------*/
401
402ManualHdf5VariableWriter::
403~ManualHdf5VariableWriter()
404{
405 delete m_writer;
406}
407
408/*---------------------------------------------------------------------------*/
409/*---------------------------------------------------------------------------*/
410
411ARCANE_REGISTER_SERVICE_HDF5VARIABLEWRITER(Hdf5VariableWriter,
413
417
418/*---------------------------------------------------------------------------*/
419/*---------------------------------------------------------------------------*/
420
421} // namespace Arcane
422
423/*---------------------------------------------------------------------------*/
424/*---------------------------------------------------------------------------*/
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Registers a factory service for the class aclass.
Generation de la classe de base du Service.
CaseOptionsHdf5VariableWriter * options() const
Options du jeu de données du service.
ArcaneHdf5VariableWriterObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
constexpr Integer size() const noexcept
Number of elements in the array.
Class managing a directory.
Definition Directory.h:36
String file(const String &file_name) const override
Returns the full path of the file file_name in the directory.
Definition Directory.cc:120
Encapsulates a hid_t for a file.
Encapsulates a simple dataset from an HDF5 file that represents an array.
Definition of standard Arcane types for hdf5.
Base class for reading or writing a variable.
void setPath(const String &path)
Sets the path in the Hdf5 file containing the variable value.
HFile m_file_id
HDF file identifier.
Writing variables in HDF5 format.
void build() override
Build-level construction of the service.
Application interface.
virtual IIOMng * ioMng()=0
Input/output manager.
virtual IRessourceMng * ressourceMng() const =0
Resource manager.
Interface for writing variable data.
Definition IDataWriter.h:45
Interface of a data item.
Definition IData.h:34
Interface of the input/output manager.
Definition IIOMng.h:37
virtual bool writeXmlFile(IXmlDocumentHolder *doc, const String &filename, const bool indented=false)=0
Writes the XML tree of the document doc to the file filename.
virtual IXmlDocumentHolder * parseXmlFile(const String &filename, const String &schemaname=String{})=0
Reads and parses the XML file filename.
Mesh manager interface.
Definition IMeshMng.h:41
virtual MeshHandle * findMeshHandle(const String &name, bool throw_exception)=0
Searches for the mesh with name name.
virtual IParallelMng * parallelMng()=0
Parallelism manager.
Interface of the parallelism manager for a subdomain.
virtual ITraceMng * traceMng() const =0
Trace manager.
virtual IIOMng * ioMng() const =0
I/O manager.
Interface for a writer for post-processing information.
virtual IXmlDocumentHolder * createXmlDocument()=0
Creates an XML document node.
virtual IMeshMng * meshMng() const =0
Returns the mesh manager.
Interface of a variable.
Definition IVariable.h:40
virtual String itemFamilyName() const =0
Name of the associated family (null if none).
virtual String fullName() const =0
Full variable name (with family prefix).
virtual eItemKind itemKind() const =0
Kind of mesh entities on which the variable is based.
virtual ItemGroup itemGroup() const =0
Associated mesh group.
virtual String name() const =0
Variable name.
Mesh entity group.
Definition ItemGroup.h:51
const String & name() const
Group name.
Definition ItemGroup.h:81
bool null() const
true means the group is the null group
Definition ItemGroup.h:75
virtual void setMetaData(const String &meta_data)
Sets the metadata information.
virtual void write(IVariable *var, IData *data)
Writes the data data of the variable var.
Writing variables in HDF5 format.
virtual void notifyEndWrite()
Notifies that an output has just been performed.
virtual void close()
Closes the writer. After closing, it can no longer be used.
virtual void notifyBeginWrite()
Notifies that an output will be performed with the current parameters.
virtual void build()
Build-level construction of the service.
virtual IDataWriter * dataWriter()
Returns the writer associated with this post-processor.
Handle on a mesh.
Definition MeshHandle.h:48
IMesh * mesh() const
Associated mesh.
Base class for a writer service for post-processing information.
VariableCollection variables() override
List of variables to save.
ConstArrayView< Real > times() override
List of saved times.
const String & baseDirectoryName() override
Name of the output directory for files.
const String & baseFileName() override
Name of the file containing the outputs.
T * get() const
Returns the object referenced by the instance.
Definition Ptr.h:122
Encapsulation of an automatically destructing pointer.
Definition ScopedPtr.h:44
Structure containing the information to create a service.
Unicode character string constructor.
bool null() const
Returns true if the string is null.
Definition String.cc:306
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage fatal() const
Flow for a fatal error message.
TraceMessage info() const
Flow for an information message.
1D data vector with value semantics (STL style).
Element of a DOM tree.
Definition XmlNode.h:406
List of nodes of a DOM tree.
Definition XmlNodeList.h:36
Node of a DOM tree.
Definition XmlNode.h:51
String attrValue(const String &name, bool throw_exception=false) const
Value of attribute name.
Definition XmlNode.cc:234
XmlNodeList children(const String &name) const
Set of child nodes of this node having the name name.
Definition XmlNode.cc:102
void setAttrValue(const String &name, const String &value)
Sets the attribute name to the value value.
Definition XmlNode.cc:248
Utility functions for Hdf5.
Definition Hdf5Utils.cc:34
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:335
@ IK_Unknown
Unknown or uninitialized mesh entity.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476
ConstArrayView< Real > RealConstArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:488