diff --git a/src/asgard.cpp b/src/asgard.cpp index b30753f36..184d659ee 100644 --- a/src/asgard.cpp +++ b/src/asgard.cpp @@ -8,6 +8,12 @@ void simulate(parser const &cli_input, std::unique_ptr> &pde) { options const opts(cli_input); + if (cli_input.show_libinfo()) + { + print_info(); + return; + } + node_out() << "Branch: " << GIT_BRANCH << '\n'; node_out() << "Commit Summary: " << GIT_COMMIT_HASH << GIT_COMMIT_SUMMARY << '\n'; @@ -395,4 +401,49 @@ template void simulate(parser const &cli_input, std::unique_ptr> &pd template void simulate(parser const &cli_input, std::unique_ptr> &pde); #endif +void print_info(std::ostream &os) +{ + os << "\nASGarD v" << ASGARD_VERSION << " git-hash: " << GIT_COMMIT_HASH << "\n"; + os << "git-branch (" << GIT_BRANCH << ")\n"; +#ifdef KRON_MODE_GLOBAL +#ifdef KRON_MODE_GLOBAL_BLOCK + os << "Kronmult method Block-Global\n"; +#else + os << "Kronmult method Global\n"; +#endif +#else + os << "Kronmult method Local\n"; +#endif +#ifdef ASGARD_USE_CUDA + os << "GPU Acceleration CUDA\n"; +#else + os << "GPU Acceleration Disabled\n"; +#endif +#ifdef ASGARD_USE_OPENMP + os << "OpenMP multithreading Enablded\n"; +#else + os << "OpenMP multithreading Disabled\n"; +#endif +#ifdef ASGARD_USE_MPI + os << "MPI distributed grid Enabled\n"; +#else + os << "MPI distributed grid Disabled\n"; +#endif +#ifdef ASGARD_IO_HIGHFIVE + os << "HDF5 - HighFive I/O Enabled\n"; +#else + os << "HDF5 - HighFive I/O Disabled\n"; +#endif +#ifdef ASGARD_ENABLE_DOUBLE +#ifdef ASGARD_ENABLE_FLOAT + os << "Available precisions double/float\n"; +#else + os << "Available precision double\n"; +#endif +#else + os << "Available precision float\n"; +#endif + os << '\n'; +} + } // namespace asgard diff --git a/src/asgard.hpp b/src/asgard.hpp index 3178e877a..16185e9e1 100644 --- a/src/asgard.hpp +++ b/src/asgard.hpp @@ -1,11 +1,6 @@ #pragma once -#include "batch.hpp" - -#include "asgard_tools.hpp" #include "coefficients.hpp" -#include "distribution.hpp" -#include "elements.hpp" #ifdef ASGARD_IO_HIGHFIVE #include "io.hpp" @@ -19,12 +14,7 @@ #include "matlab_plot.hpp" #endif -#include "asgard_vector.hpp" -#include "pde.hpp" -#include "program_options.hpp" #include "time_advance.hpp" -#include "transformations.hpp" -#include namespace asgard { @@ -40,4 +30,6 @@ void simulate(parser const &cli_input) simulate(cli_input, pde); } +void print_info(std::ostream &os = std::cout); + } diff --git a/src/asgard_interpolation.hpp b/src/asgard_interpolation.hpp index eb6430e82..b87826394 100644 --- a/src/asgard_interpolation.hpp +++ b/src/asgard_interpolation.hpp @@ -19,7 +19,7 @@ class interpolation { public: //! constructs and empty interpolation class - interpolation() : num_dimenisons_(0), block_size(0), workspace_(nullptr) + interpolation() {} //! convert to true if the class has been initialized operator bool() const { return (num_dimenisons_ > 0); } @@ -158,14 +158,14 @@ class interpolation } private: - int num_dimenisons_; + int num_dimenisons_ = 0; static constexpr int pterms = 2; // remove static later - int64_t block_size; + int64_t block_size = 0; kronmult::permutes perms; wavelet_interp1d<1, precision> wav1d; - mutable kronmult::block_global_workspace *workspace_; + mutable kronmult::block_global_workspace *workspace_ = nullptr; }; #endif diff --git a/src/asgard_interpolation1d.hpp b/src/asgard_interpolation1d.hpp index 0bd8162e9..41fac54e9 100644 --- a/src/asgard_interpolation1d.hpp +++ b/src/asgard_interpolation1d.hpp @@ -28,7 +28,7 @@ class wavelet_interp1d static constexpr int matsize = pterms * pterms; //! null constructor - wavelet_interp1d() : conn(nullptr) + wavelet_interp1d() {} //! cache interpolation points and transformation matrices wavelet_interp1d(connect_1d const *conn_in) : conn(conn_in) @@ -94,7 +94,7 @@ class wavelet_interp1d precision mat[]); private: - connect_1d const *conn; + connect_1d const *conn = nullptr; std::vector nodes_; std::vector proj2node_; std::vector node2hier_; diff --git a/src/asgard_kronmult_matrix.hpp b/src/asgard_kronmult_matrix.hpp index f9cc8aeb9..59f5c14ee 100644 --- a/src/asgard_kronmult_matrix.hpp +++ b/src/asgard_kronmult_matrix.hpp @@ -652,13 +652,13 @@ class local_kronmult_matrix flops_ *= int64_t{tensor_size_} * kron_size_; } - int num_dimensions_; - int kron_size_; // i.e., n - size of the matrices - int num_rows_; - int num_cols_; - int num_terms_; - int64_t tensor_size_; - int64_t flops_; + int num_dimensions_ = 0; + int kron_size_ = 0; // i.e., n - size of the matrices + int num_rows_ = 0; + int num_cols_ = 0; + int num_terms_ = 0; + int64_t tensor_size_ = 0; + int64_t flops_ = 0; #ifdef ASGARD_USE_CUDA // indicates that the input vectors for single-call-mode will be on the GPU @@ -704,7 +704,9 @@ class local_kronmult_matrix std::vector> terms_; fk::vector term_pntr_; fk::vector elem_; - int row_offset_, col_offset_, num_1d_blocks_; + int row_offset_ = 0; + int col_offset_ = 0; + int num_1d_blocks_ = 0; // preconditioner std::vector pre_con_; @@ -1007,9 +1009,9 @@ class global_kron_matrix private: // description of the multi-indexes and the sparsity pattern // global case data - int num_dimensions_; - int64_t num_active_; - int64_t num_padded_; + int num_dimensions_ = 0; + int64_t num_active_ = 0; + int64_t num_padded_ = 0; std::vector perms_; std::array flops_; // data for the 1D tensors @@ -1020,7 +1022,7 @@ class global_kron_matrix std::vector> gvals_; // collections of terms std::array, 3> term_groups; - int porder_; + int porder_ = 0; // preconditioner std::vector pre_con_; #ifdef ASGARD_USE_CUDA @@ -1154,9 +1156,7 @@ template class block_global_kron_matrix { public: - block_global_kron_matrix() - : num_active_(0), num_padded_(0), num_dimensions_(0), blockn_(0), block_size_(0), - conn_volumes_(nullptr), conn_full_(nullptr), workspace_(nullptr) {} + block_global_kron_matrix() {} block_global_kron_matrix(int64_t num_active, int64_t num_padded, int num_dimensions, int blockn, int64_t block_size, @@ -1261,20 +1261,22 @@ class block_global_kron_matrix block_global_kron_matrix &mat); private: - int64_t num_active_, num_padded_; - int num_dimensions_, blockn_; - int64_t block_size_; + int64_t num_active_ = 0; + int64_t num_padded_ = 0; + int num_dimensions_ = 0; + int blockn_ = 0; + int64_t block_size_ = 0; vector2d ilist_; dimension_sort dsort_; std::vector perms_; std::vector flux_dir_; - connect_1d const *conn_volumes_; - connect_1d const *conn_full_; + connect_1d const *conn_volumes_ = nullptr; + connect_1d const *conn_full_ = nullptr; std::vector> gvals_; std::array, 3> term_groups_; - mutable kronmult::block_global_workspace *workspace_; + mutable kronmult::block_global_workspace *workspace_ = nullptr; mutable std::array flops_; diff --git a/src/asgard_reconstruct.hpp b/src/asgard_reconstruct.hpp index de64e3266..fc2692c7a 100644 --- a/src/asgard_reconstruct.hpp +++ b/src/asgard_reconstruct.hpp @@ -1,7 +1,6 @@ #pragma once #include "asgard_interpolation.hpp" -#include "elements.hpp" namespace asgard { diff --git a/src/asgard_tools.cpp b/src/asgard_tools.cpp index 582e97e6b..003afc613 100644 --- a/src/asgard_tools.cpp +++ b/src/asgard_tools.cpp @@ -110,6 +110,4 @@ void simple_timer::get_timing_stats( } } -simple_timer timer; - } // namespace asgard::tools diff --git a/src/asgard_tools.hpp b/src/asgard_tools.hpp index 00206fde9..bdce9b3cd 100644 --- a/src/asgard_tools.hpp +++ b/src/asgard_tools.hpp @@ -143,7 +143,7 @@ class simple_timer id_to_start_; }; -extern simple_timer timer; +inline simple_timer timer; /*! * Allows for RAII style of timing for blocks of code. @@ -170,3 +170,105 @@ struct time_event }; } // namespace asgard::tools + +namespace asgard +{ +/*! + * \brief Iterator/generator for a sequence of integers + * + * This is needed for the indexof template + * + * Technically satisfies the requirements for legacy iterator + * but do not use directly, will be used internally in indexof + */ +template +struct index_iterator +{ + using iterator_category = std::random_access_iterator_tag; + + using value_type = idx_type; + using difference_type = idx_type; + using reference = idx_type &; + using pointer = idx_type *; + + idx_type &operator*() { return value_; } + idx_type const &operator*() const { return value_; } + bool operator!=(index_iterator const &other) const { return value_ != other.value_; } + index_iterator &operator++() + { + ++value_; + return *this; + } + index_iterator &operator++(int) { return index_iterator{value_++}; } + index_iterator &operator--() + { + --value_; + return *this; + } + index_iterator &operator--(int) { return index_iterator{value_--}; } + + idx_type value_; +}; + +/*! + * \brief Allows for range for-loops but using indexes + * + * There is a repeated pattern in coding when cross-referencing entries + * between different vectors: + * \code + * for (size_t i = 0; i < u.size(); i++) + * u[i] = std::sqrt(x[i]); + * \endcode + * The operation can be done with a std::transform but it leads to a messy + * lambda capture and potential shadow. The index can be used to cross + * reference more complex structures where iterators would be messy and + * non-trivial, e.g., rows/columns of a matrix, sparse grid indexes, or + * entries in a vector2d. The index also helps keep a more expressive + * mathematical notation. + * + * On the other hand, the pattern is tedious to write over and over. + * + * This template provides an alternative and allows for syntax like: + * \code + * for (auto i : indexof(u)) // i is int64_t + * u[i] = std::sqrt(x[i]); + * + * for (auto i : indexof(u)) // i is int + * u[i] = std::sqrt(x[i]); + * + * for (auto i : indexof(1, num_dimensions)) // i is size_t + * u[i] = std::sqrt(x[i]); + * \endcode + * + * At -O3 Godbolt compiler profile yields the same code as for the constructs + * for-indexof and the regular for-loop. + */ +template +struct indexof +{ + template + indexof(vector_type const &f) + : beg_(0), end_(static_cast(f.size())) + {} + indexof(int num) + : beg_(0), end_(static_cast(num)) + {} + indexof(int64_t num) + : beg_(0), end_(static_cast(num)) + {} + indexof(size_t num) + : beg_(0), end_(static_cast(num)) + {} + template + indexof(cidx_type b, cidx_type e) + : beg_(b), end_(e) + {} + + index_iterator begin() const { return index_iterator{beg_}; } + index_iterator end() const { return index_iterator{end_}; } + + idx_type beg_; + idx_type end_; +}; + +} // namespace asgard diff --git a/src/asgard_tools_tests.cpp b/src/asgard_tools_tests.cpp index 2dd1df630..0fcb1bb48 100644 --- a/src/asgard_tools_tests.cpp +++ b/src/asgard_tools_tests.cpp @@ -122,3 +122,40 @@ TEMPLATE_TEST_CASE("test timer", "[timing test]", time_event_tag, SECTION("count") { REQUIRE(calls == static_cast(times.size())); } } + +TEST_CASE("for-indexof testing", "[indexing testing]") +{ + std::vector x(10); + std::vector r; + r.reserve(x.size()); + + for (auto i : indexof(x)) + { + static_assert(std::is_same_v); + r.push_back(i); + } + + REQUIRE(r.size() == x.size()); + for (int64_t i = 0; i < 10; i++) + REQUIRE(r[i] == i); + + std::vector ir; + ir.reserve(8); + + for (auto i : indexof(1, 6)) + { + static_assert(std::is_same_v); + ir.push_back(i); + } + + for (int i = 1; i < 6; i++) + REQUIRE(ir[i - 1] == i); + + size_t s = 0; + for (auto i : indexof(x.size())) + { + static_assert(std::is_same_v); + s += i; + } + REQUIRE(s == 45); +} diff --git a/src/build_info.hpp.in b/src/build_info.hpp.in index 63ad9bb0a..35b973957 100644 --- a/src/build_info.hpp.in +++ b/src/build_info.hpp.in @@ -1,5 +1,10 @@ #pragma once +#define ASGARD_VERSION_MAJOR @asgard_VERSION_MAJOR@ +#define ASGARD_VERSION_MINOR @asgard_VERSION_MINOR@ +#define ASGARD_VERSION_PATCH @asgard_VERSION_PATCH@ +#define ASGARD_VERSION "@asgard_VERSION@" + #define GIT_BRANCH "@GIT_BRANCH@" #define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@" #define GIT_COMMIT_SUMMARY "@GIT_COMMIT_SUMMARY@" diff --git a/src/program_options.cpp b/src/program_options.cpp index 44bd9c4f3..608618299 100644 --- a/src/program_options.cpp +++ b/src/program_options.cpp @@ -1,5 +1,4 @@ #include "program_options.hpp" -#include "build_info.hpp" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #include "clara.hpp" @@ -42,6 +41,8 @@ parser::parser(int argc, char const *const *argv) clara::detail::Opt(max_level, "integer >= all starting levels")["-m"]["--max_level"]( "Maximum hierarchical levels (resolution) for adaptivity") | + clara::detail::Opt(libinfo)["-v"]["--version"]( + "Show information about this build.") | clara::detail::Opt(mixed_grid_group, "integer < num dimensions")["--mixed_grid_group"]( "Dimension group size for first sparse grid in the mixed " diff --git a/src/program_options.hpp b/src/program_options.hpp index e1a37d1a9..3550dc256 100644 --- a/src/program_options.hpp +++ b/src/program_options.hpp @@ -219,6 +219,7 @@ class parser static auto constexpr DEFAULT_USE_LINF_NRM = false; static auto constexpr DEFAULT_DO_POISSON = false; static auto constexpr DEFAULT_DO_ADAPT = false; + static auto constexpr DEFAULT_SHOW_INFO = false; static auto constexpr DEFAULT_PDE_STR = "custom"; static auto constexpr DEFAULT_PDE_OPT = PDE_opts::custom; static auto constexpr DEFAULT_SOLVER = solve_opts::direct; @@ -348,6 +349,8 @@ class parser bool is_valid() const; + bool show_libinfo() const { return libinfo; } + fk::vector get_max_adapt_levels() const; private: @@ -427,6 +430,8 @@ class parser // is the threshold for refining elements double adapt_threshold = DEFAULT_ADAPT_THRESH; + bool libinfo = DEFAULT_SHOW_INFO; + // default std::string pde_str = DEFAULT_PDE_STR; // pde to construct/evaluate diff --git a/src/sparse.hpp b/src/sparse.hpp index 828f5ad37..03a648e23 100644 --- a/src/sparse.hpp +++ b/src/sparse.hpp @@ -1,5 +1,4 @@ #pragma once -#include "build_info.hpp" #ifdef ASGARD_USE_CUDA #include