Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
UdunitsPhysicalUnitSystemService.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/* UdunitsUnitSystem.h (C) 2000-2014 */
9/* */
10/* Management of physical unit system using 'udunits2'. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/NotImplementedException.h"
18#include "arcane/utils/FatalErrorException.h"
19#include "arcane/utils/ArgumentException.h"
20#include "arcane/utils/Array.h"
21#include "arcane/utils/TraceInfo.h"
22
23#include "arcane/core/FactoryService.h"
24#include "arcane/core/AbstractService.h"
25#include "arcane/core/IPhysicalUnitSystemService.h"
26#include "arcane/core/IPhysicalUnitSystem.h"
27#include "arcane/core/IPhysicalUnitConverter.h"
28#include "arcane/core/IPhysicalUnit.h"
29
30#include <udunits2.h>
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
35namespace Arcane
36{
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48class UdunitsPhysicalUnit
49: public IPhysicalUnit
50{
51 public:
52
53 friend class UdunitsPhysicalUnitSystem;
54
55 public:
56
57 UdunitsPhysicalUnit(UdunitsPhysicalUnitSystem*, ::ut_unit* unit,
58 const String& name)
59 : m_unit(unit)
60 {
61 // To ensure the string is dynamically allocated
62 m_name = String::fromUtf8(name.utf8());
63 }
64
65 UdunitsPhysicalUnit(::ut_unit* unit)
66 : m_unit(unit)
67 {
68 }
69
70 virtual ~UdunitsPhysicalUnit()
71 {
72 if (m_unit)
73 ut_free(m_unit);
74 }
75
76 virtual const String& name() const
77 {
78 return m_name;
79 }
80
81 private:
82
83 ::ut_unit* m_unit;
84 String m_name;
85};
86
87/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89
90class UdunitsPhysicalUnitConverter
92{
93 public:
94
95 UdunitsPhysicalUnitConverter(UdunitsPhysicalUnitSystem*,
96 UdunitsPhysicalUnit* from_unit,
97 UdunitsPhysicalUnit* to_unit,
98 ::cv_converter* converter)
99 : m_from_unit(from_unit)
100 , m_to_unit(to_unit)
101 , m_is_from_owned(true)
102 , m_is_to_owned(true)
103 , m_converter(converter)
104 {
105 }
106
107 ~UdunitsPhysicalUnitConverter()
108 {
109 if (m_is_from_owned)
110 delete m_from_unit;
111 if (m_is_to_owned)
112 delete m_to_unit;
113 }
114
115 public:
116
117 virtual Real convert(Real value)
118 {
119 double new_value = cv_convert_double(m_converter, value);
120 return new_value;
121 }
122
123 virtual void convert(RealConstArrayView input_values,
124 RealArrayView output_values)
125 {
126 Integer nb = input_values.size();
127 Integer nb_out = output_values.size();
128 if (nb != nb_out)
129 throw ArgumentException(A_FUNCINFO, "input and ouput arrays do not have the same number of elements");
130 cv_convert_doubles(m_converter, input_values.data(), nb, output_values.data());
131 }
132
134 {
135 return m_from_unit;
136 }
137
139 {
140 return m_to_unit;
141 }
142
143 private:
144
145 UdunitsPhysicalUnit* m_from_unit;
146 UdunitsPhysicalUnit* m_to_unit;
147 bool m_is_from_owned;
148 bool m_is_to_owned;
149 ::cv_converter* m_converter;
150};
151
152/*---------------------------------------------------------------------------*/
153/*---------------------------------------------------------------------------*/
154
155class UdunitsPhysicalUnitSystem
156: public TraceAccessor
157, public IPhysicalUnitSystem
158{
159 public:
160
161 UdunitsPhysicalUnitSystem(ITraceMng* tm)
162 : TraceAccessor(tm)
163 , m_unit_system(0)
164 {
165 }
166
167 virtual ~UdunitsPhysicalUnitSystem()
168 {
169 if (m_unit_system)
170 ut_free_system(m_unit_system);
171 }
172
174 {
175 // Normally already created.
176 _checkCreateUnitSystem();
177 UdunitsPhysicalUnit* from_unit = dynamic_cast<UdunitsPhysicalUnit*>(from);
178 UdunitsPhysicalUnit* to_unit = dynamic_cast<UdunitsPhysicalUnit*>(to);
179 if (!from_unit || !to_unit)
180 throw ArgumentException(A_FUNCINFO, "can not convert units to this system unit");
181 return _createConverter(from_unit, to_unit);
182 }
183
184 virtual IPhysicalUnitConverter* createConverter(const String& from, const String& to)
185 {
186 info() << "Create unit converter from='" << from << "' to='" << to << "'";
187 _checkCreateUnitSystem();
188 UdunitsPhysicalUnit* from_unit = _createUnit(from);
189 UdunitsPhysicalUnit* to_unit = _createUnit(to);
190 //TODO: destroy units in case of error.
191 return _createConverter(from_unit, to_unit);
192 }
193
194 private:
195
196 UdunitsPhysicalUnitConverter* _createConverter(UdunitsPhysicalUnit* from_unit, UdunitsPhysicalUnit* to_unit)
197 {
198 ::cv_converter* cv_cvt = ::ut_get_converter(from_unit->m_unit, to_unit->m_unit);
199 if (!cv_cvt)
200 throw FatalErrorException(A_FUNCINFO,
201 String::format("Can not convert from '{0}' to '{1}' because units are not convertible",
202 from_unit->name(), to_unit->name()));
203 UdunitsPhysicalUnitConverter* cvt = new UdunitsPhysicalUnitConverter(this, from_unit, to_unit, cv_cvt);
204 return cvt;
205 }
206
207 void _checkCreateUnitSystem()
208 {
209 //TODO Add lock...
210 if (!m_unit_system)
211 m_unit_system = ut_read_xml(0);
212 if (!m_unit_system)
213 throw FatalErrorException(A_FUNCINFO, "Can not load unit system");
214 }
215
216 UdunitsPhysicalUnit* _createUnit(const String& name)
217 {
218 ::ut_unit* unit = ut_parse(m_unit_system, (const char*)name.utf8().data(), UT_UTF8);
219 if (!unit)
220 throw FatalErrorException(A_FUNCINFO, String::format("Can not create unit from string '{0}'", name));
221 return new UdunitsPhysicalUnit(this, unit, name);
222 }
223
224 private:
225
226 ::ut_system* m_unit_system;
227};
228
229/*---------------------------------------------------------------------------*/
230/*---------------------------------------------------------------------------*/
231
235class UdunitsUnitSystemService
236: public AbstractService
238{
239 public:
240
241 UdunitsUnitSystemService(const ServiceBuildInfo& sbi);
242 virtual ~UdunitsUnitSystemService() {}
243
244 public:
245
246 virtual void build();
247
248 public:
249
255};
256
257/*---------------------------------------------------------------------------*/
258/*---------------------------------------------------------------------------*/
259
260/*---------------------------------------------------------------------------*/
261/*---------------------------------------------------------------------------*/
262
263/*---------------------------------------------------------------------------*/
264/*---------------------------------------------------------------------------*/
265
266UdunitsUnitSystemService::
267UdunitsUnitSystemService(const ServiceBuildInfo& sbi)
268: AbstractService(sbi)
269{
270}
271
272/*---------------------------------------------------------------------------*/
273/*---------------------------------------------------------------------------*/
274
279
280/*---------------------------------------------------------------------------*/
281/*---------------------------------------------------------------------------*/
282
285 Udunits);
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
290} // namespace Arcane
291
292/*---------------------------------------------------------------------------*/
293/*---------------------------------------------------------------------------*/
#define ARCANE_REGISTER_APPLICATION_FACTORY(aclass, ainterface, aname)
Registers a factory service for the class aclass.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
constexpr const_pointer data() const noexcept
Pointer to the start of the view.
constexpr Integer size() const noexcept
Returns the size of the array.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
Interface of a unit converter.
Interface of a service managing a unit system.
Interface of a unit system.
Structure containing the information to create a service.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
virtual IPhysicalUnit * fromUnit()
Starting unit.
virtual void convert(RealConstArrayView input_values, RealArrayView output_values)
Returns the converted values of input_values in output_values.
virtual Real convert(Real value)
Returns the converted value of value.
virtual IPhysicalUnitConverter * createConverter(const String &from, const String &to)
Creates a converter between two units. The caller must destroy the returned converter.
virtual IPhysicalUnitConverter * createConverter(IPhysicalUnit *from, IPhysicalUnit *to)
Creates a converter between two units. The caller must destroy the returned converter....
virtual const String & name() const
Unit name.
Service for managing physical unit system using 'udunits2'.
virtual void build()
Build-level construction of the service.
virtual IPhysicalUnitSystem * createStandardUnitSystem()
Creates a unit system for the International System SI.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
double Real
Type representing a real number.
ArrayView< Real > RealArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:459
ConstArrayView< Real > RealConstArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:488