Arcane  4.1.12.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-2024 */
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/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29namespace Arcane
30{
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
39class ArcaneCurveWriter
40: public BasicService
42{
43 public:
44
45 class Impl : TraceAccessor
46 {
47 public:
48
49 Impl(IApplication* app, ITraceMng* tm, const String& path);
50
51 public:
52
53 String m_file_name;
54 std::ofstream m_stream;
56 XmlNode m_root_element;
57 };
58
59 public:
60
61 ArcaneCurveWriter(const ServiceBuildInfo& sbi)
62 : BasicService(sbi)
63 , m_version(2)
64 {}
66
67 public:
68
69 virtual void build() {}
70 virtual void beginWrite(const TimeHistoryCurveWriterInfo& infos);
71 virtual void endWrite();
72 virtual void writeCurve(const TimeHistoryCurveInfo& infos);
73 virtual String name() const { return "ArcaneCurveWriter"; }
74 virtual void setOutputPath(const String& path) { m_output_path = path; }
75 virtual String outputPath() const { return m_output_path; }
76
77 private:
78
80 Int32 m_version;
81 String m_output_path;
82
83 private:
84
85 void _writeHeader();
86 template <typename T>
87 Int64 _write(ConstArrayView<T> values)
88 {
89 Int64 offset = m_p->m_stream.tellp();
90 m_p->m_stream.write((const char*)values.data(), values.size() * sizeof(T));
91 //info() << "OFFSET offset=" << offset;
92 return offset;
93 }
94};
95
96/*---------------------------------------------------------------------------*/
97/*---------------------------------------------------------------------------*/
98
99ArcaneCurveWriter::Impl::
100Impl(IApplication* app, ITraceMng* tm, const String& path)
101: TraceAccessor(tm)
102, m_file_name("curves")
103{
104 String full_path = path + "/" + m_file_name + ".acv";
105 info() << "Begin write curves full_path=" << full_path;
106 m_stream.open(full_path.localstr(), std::ios::trunc);
107 if (!m_stream)
108 warning() << "Can not open file '" << full_path << "' for writing curves";
109 m_curves_doc = app->ressourceMng()->createXmlDocument();
110 XmlNode doc = m_curves_doc->documentNode();
111 m_root_element = XmlElement(doc, "curves");
112}
113
114/*---------------------------------------------------------------------------*/
115/*---------------------------------------------------------------------------*/
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
122{
123 String path = infos.path();
124 // m_output_path overrides the infos argument if not empty.
125 // TODO: check if the directory needs to be created
126 if (!m_output_path.empty())
127 m_output_path = path;
128
129 info() << A_FUNCNAME << "Begin write curves path=" << path;
130 m_p = new Impl(subDomain()->application(), traceMng(), path);
131
132 _writeHeader();
133 Int64 time_offset = _write(infos.times());
134 m_p->m_root_element.setAttrValue("times-offset", String::fromNumber(time_offset));
135 m_p->m_root_element.setAttrValue("times-size", String::fromNumber(infos.times().size()));
136 m_p->m_root_element.setAttrValue("x", "iteration");
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141
142void ArcaneCurveWriter::
143_writeHeader()
144{
145 Byte header[12];
146 // First 4 bytes to indicate that it is a curve file
147 // arcane
148 header[0] = 'A';
149 header[1] = 'C';
150 header[2] = 'V';
151 header[3] = (Byte)122;
152 // Next 4 bytes for the version
153 // Currently version 1 or 2. Version 1 only supports 32-bit sized files. The only difference in version 2 is that
154 // the offsets and lengths stored at the end of the file are 64-bit instead of 32.
155 header[4] = (Byte)m_version;
156 header[5] = 0;
157 header[6] = 0;
158 header[7] = 0;
159 // Next 4 bytes to indicate the endianness.
160 Int32 v = 0x01020304;
161 Byte* ptr = (Byte*)(&v);
162 for (Integer i = 0; i < 4; ++i)
163 header[8 + i] = ptr[i];
164 m_p->m_stream.write((const char*)header, 12);
165}
166
167/*---------------------------------------------------------------------------*/
168/*---------------------------------------------------------------------------*/
169
171endWrite()
172{
173 ByteUniqueArray bytes;
174 m_p->m_curves_doc->save(bytes);
175 if (m_version == 2) {
176 Int64 write_info[2];
177 write_info[0] = _write(bytes.constView());
178 write_info[1] = bytes.largeSize();
179 // Must always be the last write in the file
180 _write(Int64ConstArrayView(2, write_info));
181 }
182 else if (m_version == 1) {
183 Int32 write_info[2];
184 write_info[0] = CheckedConvert::toInt32(_write(bytes.constView()));
185 write_info[1] = bytes.size();
186 // Must always be the last write in the file
187 _write(Int32ConstArrayView(2, write_info));
188 }
189 else
190 ARCANE_FATAL("Invalid version {0} (valid values are '1' or '2')", m_version);
191
192 info(4) << "End writing curves";
193
194 // Release the pointer
195 m_p = 0;
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
203{
204 //info() << "Writing curve name=" << infos.m_name;
205 Int64 values_offset = _write(infos.values());
206
207 Int32ConstArrayView iterations(infos.iterations());
208 Integer nb_val = iterations.size();
209 Int32 range_iterations[2];
210 // Check if the iterations are contiguous, in which case
211 // we only save the first and the last to
212 // save space.
213 if (nb_val > 3) {
214 Int32 first_iter = iterations[0];
215 Int32 last_iter = iterations[nb_val - 1];
216 Int32 diff = 1 + last_iter - first_iter;
217 //info() << "NB_VAL=" << nb_val << " first=" << first_iter
218 // << " last=" << last_iter << " diff=" << diff << " IS_CONTIGOUS=" << (diff==nb_val);
219 if (diff == nb_val) {
220 range_iterations[0] = first_iter;
221 range_iterations[1] = last_iter;
222 iterations = Int32ConstArrayView(2, range_iterations);
223 }
224 }
225 Int64 iteration_offset = _write(iterations);
226
227 XmlNode node = m_p->m_root_element.createAndAppendElement("curve");
228
229 String name(infos.name().clone());
230
231 if (infos.subDomain() != NULL_SUB_DOMAIN_ID) {
232 name = "SD" + String::fromNumber(infos.subDomain()) + "_" + name;
233 }
234 if (infos.hasSupport()) {
235 name = infos.support() + "_" + name;
236 }
237
238 node.setAttrValue("name", name);
239 node.setAttrValue("iterations-offset", String::fromNumber(iteration_offset));
240 node.setAttrValue("iterations-size", String::fromNumber(iterations.size()));
241 node.setAttrValue("values-offset", String::fromNumber(values_offset));
242 node.setAttrValue("values-size", String::fromNumber(infos.values().size()));
243 node.setAttrValue("sub-size", String::fromNumber(infos.subSize()));
244 node.setAttrValue("base-name", infos.name());
245 if (infos.hasSupport()) {
246 node.setAttrValue("support", infos.support());
247 }
248 if (infos.subDomain() != NULL_SUB_DOMAIN_ID) {
249 node.setAttrValue("sub-domain", String::fromNumber(infos.subDomain()));
250 }
251}
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
259
260/*---------------------------------------------------------------------------*/
261/*---------------------------------------------------------------------------*/
262
263} // End namespace Arcane
264
265/*---------------------------------------------------------------------------*/
266/*---------------------------------------------------------------------------*/
#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:482
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:335
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:43
std::int32_t Int32
Signed integer type of 32 bits.