suanPan
🧮 An Open Source, Parallel and Heterogeneous Finite Element Analysis Framework
Loading...
Searching...
No Matches
suanPan.h
Go to the documentation of this file.
1/*******************************************************************************
2 * Copyright (C) 2017-2026 Theodore Chang
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17
18#ifndef SUANPAN_H
19#define SUANPAN_H
20
21// SUANPAN_DEBUG
22// _DEBUG --> MSVC
23// DEBUG --> GCC
24#if defined(_DEBUG) || defined(DEBUG) || !defined(NDEBUG)
25#define SUANPAN_DEBUG
26#define SUANPAN_EXTRA_DEBUG
27#else
28#define ARMA_NO_DEBUG
29#endif
30
31#ifdef SUANPAN_MKL
32#define MKL_DIRECT_CALL
33#endif
34
35#ifdef SUANPAN_MAGMA
36#ifndef SUANPAN_CUDA
37#undef SUANPAN_MAGMA
38#endif
39#endif
40
41// SUANPAN_WIN
42// WIN32 _WIN32 __WIN32 __WIN32__ --> MSVC GCC
43#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__)
44#ifndef SUANPAN_WIN
45#define SUANPAN_WIN
46#endif
47#endif
48
49// SUANPAN_WIN
50#if defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__)
51#ifndef SUANPAN_WIN
52#define SUANPAN_WIN
53#endif
54#endif
55
56#ifdef SUANPAN_WIN
57#ifndef NOMINMAX
58#define NOMINMAX
59#endif
60#endif
61
62// SUANPAN_UNIX
63#if defined(unix) || defined(__unix__) || defined(__linux__) || defined(linux)
64#ifndef SUANPAN_UNIX
65#define SUANPAN_UNIX
66#endif
67#endif
68
69#ifdef SUANPAN_VERSION
70#undef SUANPAN_VERSION
71#endif
72#ifdef SUANPAN_COMPILER
73#undef SUANPAN_COMPILER
74#endif
75
76// SUANPAN_VERSION SUANPAN_COMPILER
77#ifdef __clang__
78// __clang__ --> clang
79#ifdef SUANPAN_VERSION
80#undef SUANPAN_VERSION
81#endif
82#define SUANPAN_VERSION __VERSION__
83#ifdef SUANPAN_COMPILER
84#undef SUANPAN_COMPILER
85#endif
86#define SUANPAN_COMPILER "CLANG"
87#define SUANPAN_CLANG
88#elif defined(__GNUG__)
89// __GNUG__ --> GCC
90#define SUANPAN_VERSION __VERSION__
91#define SUANPAN_COMPILER "GCC"
92#define SUANPAN_GCC
93#elif defined(_MSC_BUILD)
94// _MSC_BUILD --> MSVC
95#define SUANPAN_VERSION _MSC_FULL_VER
96#define SUANPAN_COMPILER "MSVC"
97#define SUANPAN_MSVC
98// unknown pragma 'GCC'
99#pragma warning(disable : 4068)
100// cuda unused local function
101#pragma warning(disable : 4505)
102// conditional expression is constant
103#pragma warning(disable : 4127)
104#elif defined(__ICC)
105// __ICC --> Intel C++
106#define SUANPAN_VERSION __ICC
107#define SUANPAN_COMPILER "INTEL"
108#define SUANPAN_INTEL
109#ifdef SUANPAN_WIN
110#undef SUANPAN_WIN
111#endif
112#ifndef SUANPAN_UNIX
113#define SUANPAN_UNIX
114#endif
115#elif defined(__ICL)
116// __ICL --> Intel C++
117#define SUANPAN_VERSION __ICL
118#define SUANPAN_COMPILER "INTEL"
119#define SUANPAN_INTEL
120#ifdef SUANPAN_UNIX
121#undef SUANPAN_UNIX
122#endif
123#ifndef SUANPAN_WIN
124#define SUANPAN_WIN
125#endif
126#endif
127
128// _USRDLL --> MSVC
129#ifdef _USRDLL
130#ifndef SUANPAN_DLL
131#define SUANPAN_DLL
132#endif
133#endif
134
135#ifdef SUANPAN_WIN
136// WIN MSVC GCC IMPORT
137#define SUANPAN_IMPORT extern "C" __declspec(dllimport)
138// WIN MSVC GCC EXPORT
139#define SUANPAN_EXPORT extern "C" __declspec(dllexport)
140#elif defined(SUANPAN_UNIX)
141// UNIX GCC IMPORT
142#define SUANPAN_IMPORT extern "C"
143// UNIX GCC EXPORT
144#define SUANPAN_EXPORT extern "C"
145#else
146// EMPTY
147#define SUANPAN_IMPORT extern "C"
148#define SUANPAN_EXPORT extern "C"
149#endif
150
151#ifdef SUANPAN_DLL
157#else
163#endif
164
165constexpr auto SUANPAN_EXIT = 1;
166constexpr auto SUANPAN_SUCCESS = 0;
167constexpr auto SUANPAN_FAIL = -1;
168
169// TWO IMPLEMENTATIONS
170#ifndef SUANPAN_WIN
171#define _strcmpi strcasecmp
172#endif
173
174#ifdef SUANPAN_MT
175#include <oneapi/tbb/parallel_for_each.h>
176#include <oneapi/tbb/parallel_sort.h>
177#define suanpan_sort tbb::parallel_sort
178#define suanpan_for_each tbb::parallel_for_each
179#else
180#define suanpan_sort std::sort
181#define suanpan_for_each std::for_each
182#endif
183
184#include <iostream>
185inline auto& SUANPAN_COUT = std::cout;
186inline auto& SUANPAN_CWRN = std::cout;
187inline auto& SUANPAN_CERR = std::cout;
188inline auto& SUANPAN_CFTL = std::cout;
189
190#define ARMA_COUT_STREAM SUANPAN_COUT
191#define ARMA_CERR_STREAM SUANPAN_COUT
192
193#include <armadillo/arma>
194using namespace arma;
195
196#include <filesystem>
197namespace fs = std::filesystem;
198
199#ifdef SUANPAN_DISTRIBUTED
200#include <mpl/mpl.hpp>
201
202inline auto& comm_world{mpl::environment::comm_world()};
203inline const auto comm_rank{comm_world.rank()};
204inline const auto comm_size{comm_world.size()};
205
206template<typename T> concept mpl_floating_t = std::is_same_v<T, float> || std::is_same_v<T, double>;
207template<typename T> concept mpl_complex_t = std::is_same_v<T, std::complex<typename T::value_type>> && mpl_floating_t<typename T::value_type>;
208template<typename T> concept mpl_data_t = mpl_floating_t<T> || mpl_complex_t<T>;
209
210template<typename T> requires std::is_arithmetic_v<T> auto bcast_from_root(T object) {
211 comm_world.bcast(0, object);
212 return object;
213}
214
215template<mpl_data_t T> auto& bcast_from_root(const Mat<T>& object) {
216 comm_world.bcast(0, const_cast<T*>(object.memptr()), mpl::contiguous_layout<T>{object.n_elem});
217 return object;
218}
219
220template<typename T> requires std::is_arithmetic_v<T> auto allreduce(T object) {
221 comm_world.allreduce(mpl::plus<T>(), object);
222 return object;
223}
224
225template<mpl_data_t T> auto& allreduce(const Mat<T>& object) {
226 comm_world.allreduce(mpl::plus<T>(), const_cast<T*>(object.memptr()), mpl::contiguous_layout<T>{object.n_elem});
227 return object;
228}
229
230template<mpl_data_t T> auto& reduce(const Mat<T>& object) {
231 comm_world.reduce(mpl::plus<T>(), 0, const_cast<T*>(object.memptr()), mpl::contiguous_layout<T>{object.n_elem});
232 return object;
233}
234#else
235inline constexpr auto comm_rank{0};
236inline constexpr auto comm_size{1};
237
238template<typename T> auto bcast_from_root(T&& object) { return std::forward<T>(object); }
239
240template<typename T> auto allreduce(T&& object) { return std::forward<T>(object); }
241
242template<typename T> auto reduce(T&& object) { return std::forward<T>(object); }
243#endif
244
245#include <fmt/color.h>
246#include <mutex>
247
248namespace suanpan {
249 inline std::mutex print_mutex;
250
251 inline std::string pattern(const std::string_view header, const std::string_view file_path, const std::string_view format) {
252 std::string pattern;
253
254 // ReSharper disable once CppIfCanBeReplacedByConstexprIf
255 // ReSharper disable once CppDFAConstantConditions
256 // ReSharper disable once CppDFAUnreachableCode
257 if(comm_size > 1) pattern.append(fmt::format("[P{}] ", comm_rank));
258
259 const auto pos = file_path.find_last_of("/\\");
260 pattern.append(fmt::format("[{}] {}:{{}} ~> {}", header, pos == std::string_view::npos ? file_path : file_path.substr(pos + 1), format));
261
262 return pattern;
263 }
264
265 template<typename... T> void debug(const std::string_view file_name, const int line, const std::string_view format_str, const T&... args) {
266 if(!SUANPAN_VERBOSE || !SUANPAN_PRINT) return;
267 const std::scoped_lock lock(print_mutex);
268 if(SUANPAN_COLOR) SUANPAN_COUT << fmt::vformat(fg(fmt::color::coral), pattern("DEBUG", file_name, format_str), fmt::make_format_args(line, args...));
269 else SUANPAN_COUT << fmt::vformat(pattern("DEBUG", file_name, format_str), fmt::make_format_args(line, args...));
270 }
271
272 template<typename... T> void warning(const std::string_view file_name, const int line, const std::string_view format_str, const T&... args) {
274 if(!SUANPAN_PRINT) return;
275 const std::scoped_lock lock(print_mutex);
276 if(SUANPAN_COLOR) SUANPAN_CWRN << fmt::vformat(fg(fmt::color::slate_blue), pattern("WARNING", file_name, format_str), fmt::make_format_args(line, args...));
277 else SUANPAN_CWRN << fmt::vformat(pattern("WARNING", file_name, format_str), fmt::make_format_args(line, args...));
278 }
279
280 template<typename... T> void error(const std::string_view file_name, const int line, const std::string_view format_str, const T&... args) {
282 if(!SUANPAN_PRINT) return;
283 const std::scoped_lock lock(print_mutex);
284 if(SUANPAN_COLOR) SUANPAN_CERR << fmt::vformat(fg(fmt::color::orange), pattern("ERROR", file_name, format_str), fmt::make_format_args(line, args...));
285 else SUANPAN_CERR << fmt::vformat(pattern("ERROR", file_name, format_str), fmt::make_format_args(line, args...));
286 }
287
288 template<typename... T> void fatal(const std::string_view file_name, const int line, const std::string_view format_str, const T&... args) {
289 if(!SUANPAN_PRINT) return;
290 const std::scoped_lock lock(print_mutex);
291 if(SUANPAN_COLOR) SUANPAN_CFTL << fmt::vformat(fg(fmt::color::violet), pattern("FATAL", file_name, format_str), fmt::make_format_args(line, args...));
292 else SUANPAN_CFTL << fmt::vformat(pattern("FATAL", file_name, format_str), fmt::make_format_args(line, args...));
293 }
294
295 template<typename... T> void info(const std::string_view format_sv, const T&... args) {
296 if(!SUANPAN_PRINT) return;
297 const std::scoped_lock lock(print_mutex);
298 if(SUANPAN_COLOR) SUANPAN_COUT << fmt::vformat(fg(fmt::color::green_yellow), format_sv, fmt::make_format_args(args...));
299 else SUANPAN_COUT << fmt::vformat(format_sv, fmt::make_format_args(args...));
300 }
301
302 template<typename... T> std::string format(const std::string_view format_str, const T&... args) { return fmt::vformat(format_str, fmt::make_format_args(args...)); }
303
304 template<typename T> std::string format(const Col<T>& in_vec) {
305 std::string output;
306 if(std::is_floating_point_v<T>)
307 for(const auto I : in_vec) output.append(format(" {: 1.4e}", I));
308 else
309 for(const auto I : in_vec) output.append(format(" {:6d}", I));
310 output.push_back('\n');
311 return output;
312 }
313
314 template<typename T> void info(const Col<T>& in_vec) {
315 if(!SUANPAN_PRINT) return;
316 const std::scoped_lock lock(print_mutex);
317 if(SUANPAN_COLOR) SUANPAN_COUT << fmt::format(fg(fmt::color::green_yellow), "{}", format(in_vec));
318 else SUANPAN_COUT << format(in_vec);
319 }
320
321 template<typename T> void info(const std::string_view format_sv, const Col<T>& in_vec) {
322 if(!SUANPAN_PRINT) return;
323 std::string output{format(format_sv)};
324 if(format_sv.back() != '\t' && format_sv.back() != '\n') output += '\n';
325 output += format(in_vec);
326 const std::scoped_lock lock(print_mutex);
327 if(SUANPAN_COLOR) SUANPAN_COUT << fmt::format(fg(fmt::color::green_yellow), "{}", output);
328 else SUANPAN_COUT << output;
329 }
330
331 template<typename... T> void highlight(const std::string_view format_sv, const T&... args) {
332 if(!SUANPAN_PRINT) return;
333 const std::scoped_lock lock(print_mutex);
334 if(SUANPAN_COLOR) SUANPAN_COUT << fmt::vformat(fg(fmt::color::crimson), format_sv, fmt::make_format_args(args...));
335 else SUANPAN_COUT << fmt::vformat(format_sv, fmt::make_format_args(args...));
336 }
337} // namespace suanpan
338
339template<std::invocable F> auto suanpan_assert([[maybe_unused]] F&& handler) {
340#ifdef SUANPAN_DEBUG
341 std::forward<F>(handler)();
342#endif
343}
344
345#define suanpan_info suanpan::info
346#define suanpan_highlight suanpan::highlight
347#define suanpan_debug(...) suanpan::debug(__FILE__, __LINE__, ##__VA_ARGS__)
348#define suanpan_warning(...) suanpan::warning(__FILE__, __LINE__, ##__VA_ARGS__)
349#define suanpan_error(...) suanpan::error(__FILE__, __LINE__, ##__VA_ARGS__)
350#define suanpan_fatal(...) suanpan::fatal(__FILE__, __LINE__, ##__VA_ARGS__)
351
352#include <memory>
353
354using std::shared_ptr;
355using std::unique_ptr;
356
357template<class T> concept sp_d = std::is_same_v<T, float> || std::is_same_v<T, double>;
358template<class T> concept sp_i = std::is_integral_v<T>;
359
360template<typename T, typename U> concept is_arma_mat = sp_d<T> && (std::is_convertible_v<std::remove_cvref_t<U>, Mat<T>> || std::is_convertible_v<std::remove_cvref_t<U>, SpMat<T>>);
361
362namespace suanpan {
363 template<class Container, class Handler> requires requires(Container& x) { x.begin(); x.end(); } void for_all(Container& target, Handler&& func) {
364 suanpan_for_each(target.begin(), target.end(), std::forward<Handler>(func));
365 }
366
367 template<typename T> std::vector<T>& append_to(std::vector<T>& a, std::vector<T>&& b) {
368 a.reserve(a.size() + b.size());
369 a.insert(a.end(), std::make_move_iterator(b.begin()), std::make_move_iterator(b.end()));
370 return a;
371 }
372
373 template<typename T1> [[nodiscard]] typename enable_if2<is_arma_type<T1>::value, typename T1::pod_type>::result inf_norm(const T1& X) { return arma::norm(X, "inf"); }
374} // namespace suanpan
375
376#if defined(SUANPAN_CLANG) && !defined(__cpp_lib_ranges)
377// as of clang 13, ranges support is not complete
378namespace std::ranges {
379 template<class IN, class OUT, class FN> OUT transform(IN& from, OUT to, FN&& func) { return std::transform(from.begin(), from.end(), to, std::forward<FN>(func)); }
380
381 template<class IN, class FN> FN for_each(IN& from, FN&& func) { return std::for_each(from.begin(), from.end(), std::forward<FN>(func)); }
382
383 template<class IN, class FN> bool any_of(const IN& from, FN&& func) { return std::any_of(from.cbegin(), from.cend(), std::forward<FN>(func)); }
384
385 template<class IN, class T> constexpr auto fill(IN& from, T value) { return std::fill(from.begin(), from.end(), value); }
386
387 template<class IN> constexpr auto max_element(const IN& from) { return std::max_element(from.cbegin(), from.cend()); }
388
389 template<class IN> constexpr auto min_element(const IN& from) { return std::min_element(from.cbegin(), from.cend()); }
390} // namespace std::ranges
391#endif
392
393#endif
Definition suanPan.h:360
Definition suanPan.h:357
Definition suanPan.h:358
void object(unique_ptr< T > &new_object, const shared_ptr< DomainBase > &domain, const std::string &id, std::istringstream &command)
Definition ExternalModule.h:79
Definition SparseMatMAGMA.hpp:43
auto any_of(Container &target, Handler &&func)
Definition utility.h:75
void for_all(Container &target, Handler &&func)
Definition suanPan.h:363
void info(const std::string_view format_sv, const T &... args)
Definition suanPan.h:295
std::string pattern(const std::string_view header, const std::string_view file_path, const std::string_view format)
Definition suanPan.h:251
void error(const std::string_view file_name, const int line, const std::string_view format_str, const T &... args)
Definition suanPan.h:280
void debug(const std::string_view file_name, const int line, const std::string_view format_str, const T &... args)
Definition suanPan.h:265
std::string format(const std::string_view format_str, const T &... args)
Definition suanPan.h:302
void warning(const std::string_view file_name, const int line, const std::string_view format_str, const T &... args)
Definition suanPan.h:272
std::vector< T > & append_to(std::vector< T > &a, std::vector< T > &&b)
Definition suanPan.h:367
constexpr T max_element(T start, T end)
Definition utility.h:42
std::mutex print_mutex
Definition suanPan.h:249
void for_each(const IT start, const IT end, F &&FN)
Definition utility.h:31
void fatal(const std::string_view file_name, const int line, const std::string_view format_str, const T &... args)
Definition suanPan.h:288
enable_if2< is_arma_type< T1 >::value, typenameT1::pod_type >::result inf_norm(const T1 &X)
Definition suanPan.h:373
void highlight(const std::string_view format_sv, const T &... args)
Definition suanPan.h:331
Definition tensor.h:120
auto allreduce(T &&object)
Definition suanPan.h:240
constexpr auto comm_rank
Definition suanPan.h:235
auto suanpan_assert(F &&handler)
Definition suanPan.h:339
constexpr auto SUANPAN_SUCCESS
Definition suanPan.h:166
auto & SUANPAN_COUT
Definition suanPan.h:185
#define suanpan_for_each
Definition suanPan.h:181
SUANPAN_EXPORT bool SUANPAN_COLOR
Definition suanPan.h:160
#define SUANPAN_EXPORT
Definition suanPan.h:148
constexpr auto SUANPAN_EXIT
Definition suanPan.h:165
constexpr auto comm_size
Definition suanPan.h:236
auto & SUANPAN_CWRN
Definition suanPan.h:186
auto & SUANPAN_CFTL
Definition suanPan.h:188
SUANPAN_EXPORT bool SUANPAN_PRINT
Definition suanPan.h:158
constexpr auto SUANPAN_FAIL
Definition suanPan.h:167
SUANPAN_EXPORT unsigned SUANPAN_ERROR_COUNT
Definition suanPan.h:162
auto reduce(T &&object)
Definition suanPan.h:242
#define SUANPAN_IMPORT
Definition suanPan.h:147
SUANPAN_EXPORT bool SUANPAN_VERBOSE
Definition suanPan.h:159
SUANPAN_EXPORT unsigned SUANPAN_WARNING_COUNT
Definition suanPan.h:161
auto bcast_from_root(T &&object)
Definition suanPan.h:238
auto & SUANPAN_CERR
Definition suanPan.h:187