Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
AlinaUtils.h
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/* AlinaUtils.h (C) 2000-2026 */
9/* */
10/* Various utilities. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13#ifndef ARCCORE_ALINA_ALINAUTILS_H
14#define ARCCORE_ALINA_ALINAUTILS_H
15/*---------------------------------------------------------------------------*/
16/*---------------------------------------------------------------------------*/
17/*
18 * This file is based on the work on AMGCL library (version march 2026)
19 * which can be found at https://github.com/ddemidov/amgcl.
20 *
21 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
22 * SPDX-License-Identifier: MIT
23 */
24/*---------------------------------------------------------------------------*/
25/*---------------------------------------------------------------------------*/
26
27#pragma GCC diagnostic ignored "-Wconversion"
28#pragma GCC diagnostic ignored "-Wsign-compare"
29
30#include "arccore/alina/AlinaGlobal.h"
31
32#include "arccore/base/Ref.h"
33#include "arccore/base/FatalErrorException.h"
34#include "arccore/base/ForLoopRunInfo.h"
35#include "arccore/concurrency/ParallelFor.h"
36
37#include <set>
38#include <complex>
39#include <cstddef>
40#include <tuple>
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
45namespace Arcane::Alina
46{
47namespace detail
48{
50}
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
55class ARCCORE_ALINA_EXPORT SolverResult
56{
57 public:
58
59 SolverResult() = default;
60 SolverResult(const std::tuple<size_t, double>& v)
61 : m_nb_iteration(get<0>(v))
62 , m_residual(get<1>(v))
63 {}
64 SolverResult(const std::tuple<size_t, float>& v)
65 : m_nb_iteration(get<0>(v))
66 , m_residual(get<1>(v))
67 {}
68 SolverResult(size_t nb_iteration, double residual)
69 : m_nb_iteration(nb_iteration)
70 , m_residual(residual)
71 {}
72
73 operator std::tuple<size_t, double>() const { return { m_nb_iteration, m_residual }; }
74
75 public:
76
77 constexpr Int32 nbIteration() const { return static_cast<Int32>(m_nb_iteration); }
78 constexpr double residual() const { return m_residual; }
79
80 private:
81
82 size_t m_nb_iteration = 0;
83 double m_residual = 0.0;
84};
85
86/*---------------------------------------------------------------------------*/
87/*---------------------------------------------------------------------------*/
88
89namespace detail
90{
91 class PropertyWrapper;
93 class ARCCORE_ALINA_EXPORT empty_params
94 {
95 public:
96
97 empty_params() {}
98
99 empty_params(const PropertyTree& ap);
100 void get(PropertyTree&, const std::string&) const {}
101 };
102
103} // namespace detail
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
112class ARCCORE_ALINA_EXPORT PropertyTree
113{
114 public:
115
118
119 protected:
120
121 PropertyTree(detail::PropertyTreeImpl* p,bool is_own);
122
123 public:
124
125 PropertyTree();
126 PropertyTree(const PropertyTree& rhs);
127 PropertyTree& operator=(const PropertyTree& rhs);
128 ~PropertyTree();
129
130 public:
131
132 Int32 get(const char* param_type, Int32 default_value) const;
133 Int64 get(const char* param_type, Int64 default_value) const;
134 size_t get(const char* param_type, size_t default_value) const
135 {
136 return get(param_type, static_cast<Int64>(default_value));
137 }
138 double get(const char* param_type, double default_value) const;
139 double* get(const char* param_type, double* default_value) const;
140 void* get(const char* param_type, void* default_value) const;
141 std::string get(const char* param_type, const std::string& default_value) const;
142
143 template <typename DataType> DataType
144 get(const char* param_type, const DataType& default_value) const
145 requires(std::is_enum_v<DataType>)
146 {
147 std::ostringstream default_ostr;
148 default_ostr << default_value;
149 std::string s = get(param_type, default_ostr.str());
150 std::istringstream istr(s);
151 DataType enum_value;
152 istr >> enum_value;
153 if (istr.bad())
154 ARCCORE_FATAL("Can not convert '{0}' to enumeration", s);
155 return enum_value;
156 }
157
158 void put(const std::string& path, Int32 value);
159 void put(const std::string& path, Int64 value);
160 void put(const std::string& path, size_t value)
161 {
162 put(path, static_cast<Int64>(value));
163 }
164
165 void put(const std::string& path, double value);
166 void put(const std::string& path, const std::string& value);
167 void put(const std::string& path, double* value);
168 void put(const std::string& path, void* value);
169
170 template <typename DataType> void
171 put(const std::string& path, const DataType& value)
172 requires(std::is_enum_v<DataType>)
173 {
174 // Convert enum to string.
175 std::ostringstream ostr;
176 ostr << value;
177 put(path, ostr.str());
178 }
179
180 // Put parameter in form "key=value" into the property tree
181 void putKeyValue(const std::string& param);
182
183 PropertyTree get_child_empty(const std::string& path) const;
184 bool erase(const char* name);
185 size_t count(const char* name) const;
186
187 // NOTE: Does not seems to be used.
188 void _addChild(const std::string& path, const char* name, const PropertyTree& obj);
189
190 public:
191
192 void read_json(const std::string& filename);
193
194 public:
195
196 void check_params(const std::set<std::string>& names) const;
197 void check_params(const std::set<std::string>& names, const std::set<std::string>& opt_names) const;
198 ARCCORE_ALINA_EXPORT friend std::ostream& operator<<(std::ostream& o, const PropertyTree& obj);
199
200 private:
201
202 detail::PropertyTreeImpl* m_property_tree = nullptr;
203 bool m_is_own = false;
204};
205
206} // namespace Arcane::Alina
207
208/*---------------------------------------------------------------------------*/
209/*---------------------------------------------------------------------------*/
210
211#include "arccore/alina/ScopedStreamModifier.h"
212
225#ifdef ARCCORE_ALINA_PROFILING
226#if !defined(ARCCORE_ALINA_TIC) || !defined(ARCCORE_ALINA_TOC)
227#include "arccore/alina/Profiler.h"
228#define ARCCORE_ALINA_TIC(name) ::Arcane::Alina::Profiler::globalTic(name);
229#define ARCCORE_ALINA_TOC(name) ::Arcane::Alina::Profiler::globalToc(name);
230#endif
231#endif
232
233#ifndef ARCCORE_ALINA_TIC
234#define ARCCORE_ALINA_TIC(name)
235#endif
236#ifndef ARCCORE_ALINA_TOC
237#define ARCCORE_ALINA_TOC(name)
238#endif
239
240#define ARCCORE_ALINA_DEBUG_SHOW(x) \
241 std::cout << std::setw(20) << #x << ": " \
242 << std::setw(15) << std::setprecision(8) << std::scientific \
243 << (x) << std::endl
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248namespace Arcane::Alina
249{
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
255template <class Condition, class Message>
256void precondition(const Condition& condition, const Message& message)
257{
258#ifdef _MSC_VER
259#pragma warning(push)
260#pragma warning(disable : 4800)
261#endif
262 if (!condition)
263 throw std::runtime_error(message);
264#ifdef _MSC_VER
265#pragma warning(pop)
266#endif
267}
268
269/*---------------------------------------------------------------------------*/
270/*---------------------------------------------------------------------------*/
271
272#define ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, name) \
273 name(p.get(#name, params().name))
274
275#define ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, name) \
276 name(p.get_child_empty(#name))
277
278#define ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, name) \
279 p.put(std::string(path) + #name, name)
280
281namespace detail
282{
283
284 template <typename T>
285 inline void params_export_child(PropertyTree& ap,
286 const std::string& path,
287 const char* name, const T& obj)
288 {
289 obj.get(ap, std::string(path) + name + ".");
290 }
291
292 // NOTE GG: This method is not used in the tests.
293 template <>
294 inline void params_export_child(PropertyTree& ap,
295 const std::string& path, const char* name,
296 const PropertyTree& obj)
297 {
298 ap._addChild(path, name, obj);
299 }
300
301} // namespace detail
302
303#define ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, name) \
304 ::Arcane::Alina::detail::params_export_child(p, path, #name, name)
305
306/*---------------------------------------------------------------------------*/
307/*---------------------------------------------------------------------------*/
308
309// Missing parameter action
310#ifndef ARCCORE_ALINA_PARAM_MISSING
311#define ARCCORE_ALINA_PARAM_MISSING(name) (void)0
312#endif
313
314/*---------------------------------------------------------------------------*/
315/*---------------------------------------------------------------------------*/
316
317// N-dimensional dense matrix
318template <class T, int N>
319class multi_array
320{
321 static_assert(N > 0, "Wrong number of dimensions");
322
323 public:
324
325 template <class... I>
326 multi_array(I... n)
327 {
328 static_assert(sizeof...(I) == N, "Wrong number of dimensions");
329 buf.resize(init(n...));
330 }
331
332 size_t size() const
333 {
334 return buf.size();
335 }
336
337 int stride(int i) const
338 {
339 return strides[i];
340 }
341
342 template <class... I>
343 T operator()(I... i) const
344 {
345 static_assert(sizeof...(I) == N, "Wrong number of indices");
346 return buf[index(i...)];
347 }
348
349 template <class... I>
350 T& operator()(I... i)
351 {
352 static_assert(sizeof...(I) == N, "Wrong number of indices");
353 return buf[index(i...)];
354 }
355
356 const T* data() const
357 {
358 return buf.data();
359 }
360
361 T* data()
362 {
363 return buf.data();
364 }
365
366 private:
367
368 std::array<int, N> strides;
369 std::vector<T> buf;
370
371 template <class... I>
372 int index(int i, I... tail) const
373 {
374 return strides[N - sizeof...(I) - 1] * i + index(tail...);
375 }
376
377 int index(int i) const
378 {
379 return strides[N - 1] * i;
380 }
381
382 template <class... I>
383 int init(int i, I... tail)
384 {
385 int size = init(tail...);
386 strides[N - sizeof...(I) - 1] = size;
387 return i * size;
388 }
389
390 int init(int i)
391 {
392 strides[N - 1] = 1;
393 return i;
394 }
395};
396
397template <class T>
398class circular_buffer
399{
400 public:
401
402 circular_buffer(size_t n)
403 : start(0)
404 {
405 buf.reserve(n);
406 }
407
408 size_t size() const
409 {
410 return buf.size();
411 }
412
413 void push_back(const T& v)
414 {
415 if (buf.size() < buf.capacity()) {
416 buf.push_back(v);
417 }
418 else {
419 buf[start] = v;
420 start = (start + 1) % buf.capacity();
421 }
422 }
423
424 const T& operator[](size_t i) const
425 {
426 return buf[(start + i) % buf.capacity()];
427 }
428
429 T& operator[](size_t i)
430 {
431 return buf[(start + i) % buf.capacity()];
432 }
433
434 void clear()
435 {
436 buf.clear();
437 start = 0;
438 }
439
440 private:
441
442 size_t start;
443 std::vector<T> buf;
444};
445
446namespace detail
447{
448
449 template <class T>
450 T eps(size_t n)
451 {
452 return 2 * std::numeric_limits<T>::epsilon() * n;
453 }
454
455} // namespace detail
456
457template <class T> struct is_complex : std::false_type
458{};
459template <class T> struct is_complex<std::complex<T>> : std::true_type
460{};
461
462inline std::string human_readable_memory(size_t bytes)
463{
464 static const char* suffix[] = { "B", "K", "M", "G", "T" };
465
466 int i = 0;
467 double m = static_cast<double>(bytes);
468 for (; i < 4 && m >= 1024.0; ++i, m /= 1024.0)
469 ;
470
471 std::ostringstream s;
472 s << std::fixed << std::setprecision(2) << m << " " << suffix[i];
473 return s.str();
474}
475
476namespace detail
477{
478
479 class non_copyable
480 {
481 protected:
482
483 non_copyable() = default;
484 ~non_copyable() = default;
485
486 non_copyable(non_copyable const&) = delete;
487 void operator=(non_copyable const& x) = delete;
488 };
489
493 template <typename Col, typename Val>
494 void sort_row(Col* col, Val* val, int n)
495 {
496 for (int j = 1; j < n; ++j) {
497 Col c = col[j];
498 Val v = val[j];
499
500 int i = j - 1;
501
502 while (i >= 0 && col[i] > c) {
503 col[i + 1] = col[i];
504 val[i + 1] = val[i];
505 i--;
506 }
507
508 col[i + 1] = c;
509 val[i + 1] = v;
510 }
511 }
512
513} // namespace detail
514
515namespace error
516{
517
519 {};
520
521} // namespace error
522} // namespace Arcane::Alina
523
524namespace std
525{
526
527// Read pointers from input streams.
528// This allows exchanging pointers through the property tree.
529template <class T>
530inline istream& operator>>(istream& is, T*& ptr)
531{
533
534 size_t val;
535 is >> std::hex >> val;
536
537 ptr = reinterpret_cast<T*>(val);
538
539 return is;
540}
541
542} // namespace std
543
544#endif
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Management of references to a C++ class.
Class to store parameters as a hierarchical key/value tree.
Definition AlinaUtils.h:113
Save ostream flags in constructor, restore in destructor.
Minimal hierarchical property tree with string leaf values.
Definition AlinaUtils.cc:46
Class to handle empty parameter list.
Definition AlinaUtils.h:94
std::int64_t Int64
Signed integer type of 64 bits.
std::istream & operator>>(std::istream &istr, eItemKind &item_kind)
Input operator from a stream.
std::int32_t Int32
Signed integer type of 32 bits.