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