Arcane  4.2.1.0
Developer documentation
Loading...
Searching...
No Matches
ArcaneCurveWriter.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/* ArcaneCurveWriter.cc (C) 2000-2026 */
9/* */
10/* Writing curves in Arcane format. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArrayView.h"
15#include "arcane/utils/ScopedPtr.h"
16#include "arcane/utils/CheckedConvert.h"
17
18#include "arcane/core/ITimeHistoryCurveWriter2.h"
19#include "arcane/core/BasicService.h"
20#include "arcane/core/FactoryService.h"
21#include "arcane/core/IApplication.h"
22#include "arcane/core/IRessourceMng.h"
23#include "arcane/core/IXmlDocumentHolder.h"
24#include "arcane/core/XmlNode.h"
25
26#include <fstream>
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31namespace Arcane
32{
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
41class ArcaneCurveWriter
42: public BasicService
44{
45 public:
46
47 class Impl : TraceAccessor
48 {
49 public:
50
51 Impl(IApplication* app, ITraceMng* tm, const String& path);
52
53 public:
54
55 String m_file_name;
56 std::ofstream m_stream;
58 XmlNode m_root_element;
59 };
60
61 public:
62
63 ArcaneCurveWriter(const ServiceBuildInfo& sbi)
64 : BasicService(sbi)
65 , m_version(2)
66 {}
68
69 public:
70
71 virtual void build() {}
72 virtual void beginWrite(const TimeHistoryCurveWriterInfo& infos);
73 virtual void endWrite();
74 virtual void writeCurve(const TimeHistoryCurveInfo& infos);
75 virtual String name() const { return "ArcaneCurveWriter"; }
76 virtual void setOutputPath(const String& path) { m_output_path = path; }
77 virtual String outputPath() const { return m_output_path; }
78
79 private:
80
82 Int32 m_version;
83 String m_output_path;
84
85 private:
86
87 void _writeHeader();
88 template <typename T>
89 Int64 _write(ConstArrayView<T> values)
90 {
91 Int64 offset = m_p->m_stream.tellp();
92 m_p->m_stream.write((const char*)values.data(), values.size() * sizeof(T));
93 //info() << "OFFSET offset=" << offset;
94 return offset;
95 }
96};
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
101ArcaneCurveWriter::Impl::
102Impl(IApplication* app, ITraceMng* tm, const String& path)
103: TraceAccessor(tm)
104, m_file_name("curves")
105{
106 String full_path = path + "/" + m_file_name + ".acv";
107 info() << "Begin write curves full_path=" << full_path;
108 m_stream.open(full_path.localstr(), std::ios::trunc);
109 if (!m_stream)
110 warning() << "Can not open file '" << full_path << "' for writing curves";
111 m_curves_doc = app->ressourceMng()->createXmlDocument();
112 XmlNode doc = m_curves_doc->documentNode();
113 m_root_element = XmlElement(doc, "curves");
114}
115
116/*---------------------------------------------------------------------------*/
117/*---------------------------------------------------------------------------*/
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
124{
125 String path = infos.path();
126 // m_output_path overrides the infos argument if not empty.
127 // TODO: check if the directory needs to be created
128 if (!m_output_path.empty())
129 m_output_path = path;
130
131 info() << A_FUNCNAME << "Begin write curves path=" << path;
132 m_p = new Impl(subDomain()->application(), traceMng(), path);
133
134 _writeHeader();
135 Int64 time_offset = _write(infos.times());
136 m_p->m_root_element.setAttrValue("times-offset", String::fromNumber(time_offset));
137 m_p->m_root_element.setAttrValue("times-size", String::fromNumber(infos.times().size()));
138 m_p->m_root_element.setAttrValue("x", "iteration");
139}
140
141/*---------------------------------------------------------------------------*/
142/*---------------------------------------------------------------------------*/
143
144void ArcaneCurveWriter::
145_writeHeader()
146{
147 Byte header[12];
148 // First 4 bytes to indicate that it is a curve file
149 // arcane
150 header[0] = 'A';
151 header[1] = 'C';
152 header[2] = 'V';
153 header[3] = (Byte)122;
154 // Next 4 bytes for the version
155 // Currently version 1 or 2. Version 1 only supports 32-bit sized files. The only difference in version 2 is that
156 // the offsets and lengths stored at the end of the file are 64-bit instead of 32.
157 header[4] = (Byte)m_version;
158 header[5] = 0;
159 header[6] = 0;
160 header[7] = 0;
161 // Next 4 bytes to indicate the endianness.
162 Int32 v = 0x01020304;
163 Byte* ptr = (Byte*)(&v);
164 for (Integer i = 0; i < 4; ++i)
165 header[8 + i] = ptr[i];
166 m_p->m_stream.write((const char*)header, 12);
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
173endWrite()
174{
175 ByteUniqueArray bytes;
176 m_p->m_curves_doc->save(bytes);
177 if (m_version == 2) {
178 Int64 write_info[2];
179 write_info[0] = _write(bytes.constView());
180 write_info[1] = bytes.largeSize();
181 // Must always be the last write in the file
182 _write(Int64ConstArrayView(2, write_info));
183 }
184 else if (m_version == 1) {
185 Int32 write_info[2];
186 write_info[0] = CheckedConvert::toInt32(_write(bytes.constView()));
187 write_info[1] = bytes.size();
188 // Must always be the last write in the file
189 _write(Int32ConstArrayView(2, write_info));
190 }
191 else
192 ARCANE_FATAL("Invalid version {0} (valid values are '1' or '2')", m_version);
193
194 info(4) << "End writing curves";
195
196 // Release the pointer
197 m_p = 0;
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
205{
206 //info() << "Writing curve name=" << infos.m_name;
207 Int64 values_offset = _write(infos.values());
208
209 Int32ConstArrayView iterations(infos.iterations());
210 Integer nb_val = iterations.size();
211 Int32 range_iterations[2];
212 // Check if the iterations are contiguous, in which case
213 // we only save the first and the last to
214 // save space.
215 if (nb_val > 3) {
216 Int32 first_iter = iterations[0];
217 Int32 last_iter = iterations[nb_val - 1];
218 Int32 diff = 1 + last_iter - first_iter;
219 //info() << "NB_VAL=" << nb_val << " first=" << first_iter
220 // << " last=" << last_iter << " diff=" << diff << " IS_CONTIGOUS=" << (diff==nb_val);
221 if (diff == nb_val) {
222 range_iterations[0] = first_iter;
223 range_iterations[1] = last_iter;
224 iterations = Int32ConstArrayView(2, range_iterations);
225 }
226 }
227 Int64 iteration_offset = _write(iterations);
228
229 XmlNode node = m_p->m_root_element.createAndAppendElement("curve");
230
231 String name(infos.name().clone());
232
233 if (infos.subDomain() != NULL_SUB_DOMAIN_ID) {
234 name = "SD" + String::fromNumber(infos.subDomain()) + "_" + name;
235 }
236 if (infos.hasSupport()) {
237 name = infos.support() + "_" + name;
238 }
239
240 node.setAttrValue("name", name);
241 node.setAttrValue("iterations-offset", String::fromNumber(iteration_offset));
242 node.setAttrValue("iterations-size", String::fromNumber(iterations.size()));
243 node.setAttrValue("values-offset", String::fromNumber(values_offset));
244 node.setAttrValue("values-size", String::fromNumber(infos.values().size()));
245 node.setAttrValue("sub-size", String::fromNumber(infos.subSize()));
246 node.setAttrValue("base-name", infos.name());
247 if (infos.hasSupport()) {
248 node.setAttrValue("support", infos.support());
249 }
250 if (infos.subDomain() != NULL_SUB_DOMAIN_ID) {
251 node.setAttrValue("sub-domain", String::fromNumber(infos.subDomain()));
252 }
253}
254
255/*---------------------------------------------------------------------------*/
256/*---------------------------------------------------------------------------*/
257
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265} // End namespace Arcane
266
267/*---------------------------------------------------------------------------*/
268/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Registers a factory service for the class aclass.
Writing curves in the specific Arcane format.
virtual void setOutputPath(const String &path)
Base directory where curves will be written.
virtual String name() const
Writer name.
virtual String outputPath() const
Base directory where curves will be written.
virtual void endWrite()
Notify the end of writing.
virtual void build()
Build-level construction of the service.
virtual void beginWrite(const TimeHistoryCurveWriterInfo &infos)
Notify the start of writing.
virtual void writeCurve(const TimeHistoryCurveInfo &infos)
Write a curve.
Constant view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
Application interface.
Encapsulation of an automatically destructing pointer.
Definition ScopedPtr.h:44
Structure containing the information to create a service.
String clone() const
Clones this string.
Definition String.cc:414
Information for writing a curve.
Int32ConstArrayView iterations() const
List of iterations.
const String & name() const
Curve name.
RealConstArrayView values() const
List of curve values.
Integer subSize() const
Number of values per time step.
Information about writing curves.
String path() const
Path to write the data (unless specifically overridden by the service via ITimeHistoryCurveWriter2::s...
RealConstArrayView times() const
List of times.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
TraceMessage warning() const
Flow for a warning message.
ITraceMng * traceMng() const
Trace manager.
Node of a DOM tree.
Definition XmlNode.h:51
void setAttrValue(const String &name, const String &value)
Sets the attribute name to the value value.
Definition XmlNode.cc:248
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:476
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:474
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:329
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:42
std::int32_t Int32
Signed integer type of 32 bits.