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