3#include <sll/matrix_batch.hpp>
4#include <sll/matrix_utils.hpp>
6#include <ginkgo/extensions/kokkos.hpp>
7#include <ginkgo/ginkgo.hpp>
9#include <Kokkos_Core.hpp>
18enum class MatrixBatchCsrSolver { CG, BICGSTAB, BATCH_CG, BATCH_BICGSTAB };
34template <
class ExecSpace, MatrixBatchCsrSolver Solver = MatrixBatchCsrSolver::BICGSTAB>
43 using batch_sparse_type = gko::batch::matrix::Csr<double, int>;
44 using solver_type = std::conditional_t<
45 Solver == MatrixBatchCsrSolver::CG,
46 gko::solver::Cg<double>,
48 Solver == MatrixBatchCsrSolver::BICGSTAB,
49 gko::solver::Bicgstab<double>,
51 Solver == MatrixBatchCsrSolver::BATCH_CG,
52 gko::batch::solver::Cg<double>,
53 gko::batch::solver::Bicgstab<double>>>>;
55 std::shared_ptr<batch_sparse_type> m_batch_matrix_csr;
57 Solver == MatrixBatchCsrSolver::CG || Solver == MatrixBatchCsrSolver::BICGSTAB,
58 std::vector<std::shared_ptr<solver_type>>,
59 std::shared_ptr<solver_type>>
64 unsigned int m_preconditionner_max_block_size;
82 const int nnz_per_system,
83 std::optional<int> max_iter = std::nullopt,
84 std::optional<double> res_tol = std::nullopt,
85 std::optional<bool> logger = std::nullopt,
86 std::optional<int> preconditionner_max_block_size = 1u)
88 , m_max_iter(max_iter.value_or(1000))
89 , m_tol(res_tol.value_or(1e-15))
90 , m_with_logger(logger.value_or(false))
91 , m_preconditionner_max_block_size(preconditionner_max_block_size.value_or(
92 default_preconditionner_max_block_size<ExecSpace>()))
94 std::shared_ptr
const gko_exec = gko::ext::kokkos::create_executor(ExecSpace());
95 m_batch_matrix_csr = gko::share(
98 gko::batch_dim<2>(
batch_size, gko::dim<2>(mat_size, mat_size)),
120 Kokkos::View<double**, Kokkos::LayoutRight, ExecSpace> batch_values,
121 Kokkos::View<int*, Kokkos::LayoutRight, ExecSpace> cols_idx,
122 Kokkos::View<int*, Kokkos::LayoutRight, ExecSpace> nnz_per_row,
123 std::optional<int> max_iter = std::nullopt,
124 std::optional<double> res_tol = std::nullopt,
125 std::optional<bool> logger = std::nullopt,
126 std::optional<int> preconditionner_max_block_size = 1u)
127 :
MatrixBatch<ExecSpace>(batch_values.extent(0), nnz_per_row.
size() - 1)
128 , m_max_iter(max_iter.value_or(1000))
129 , m_tol(res_tol.value_or(1e-15))
130 , m_with_logger(logger.value_or(false))
131 , m_preconditionner_max_block_size(preconditionner_max_block_size.value_or(
132 default_preconditionner_max_block_size<ExecSpace>()))
134 std::shared_ptr
const gko_exec = gko::ext::kokkos::create_executor(ExecSpace());
135 m_batch_matrix_csr = gko::share(
139 std::move(gko::array<double>::
142 batch_values.data())),
143 std::move(gko::array<
144 int>::view(gko_exec, cols_idx.span(), cols_idx.data())),
145 std::move(gko::array<int>::
148 nnz_per_row.data()))));
160 Kokkos::View<double**, Kokkos::LayoutRight, ExecSpace>,
161 Kokkos::View<int*, Kokkos::LayoutRight, ExecSpace>,
162 Kokkos::View<int*, Kokkos::LayoutRight, ExecSpace>>
165 int* idx_buffer = m_batch_matrix_csr->get_col_idxs();
166 int* nnz_per_row_buffer = m_batch_matrix_csr->get_row_ptrs();
167 double* vals_buffer = m_batch_matrix_csr->get_values();
169 Kokkos::View<int*, Kokkos::LayoutRight, ExecSpace>
170 col_idx_view_buffer(idx_buffer, m_batch_matrix_csr->get_num_elements_per_item());
171 Kokkos::View<int*, Kokkos::LayoutRight, ExecSpace>
172 nnz_per_row_view_buffer(nnz_per_row_buffer,
size() + 1);
173 Kokkos::View<double**, Kokkos::LayoutRight, ExecSpace> vals_view_buffer(
176 m_batch_matrix_csr->get_num_elements_per_item());
178 return {vals_view_buffer, col_idx_view_buffer, nnz_per_row_view_buffer};
191 std::shared_ptr
const gko_exec = m_batch_matrix_csr->get_executor();
195 std::unique_ptr<gko::matrix::Csr<double, int>> tmp_matrix
196 = m_batch_matrix_csr->create_view_for_item(i);
197 if (!tmp_matrix->is_sorted_by_column_index()) {
198 tmp_matrix->sort_by_column_index();
202 Solver == MatrixBatchCsrSolver::CG || Solver == MatrixBatchCsrSolver::BICGSTAB) {
204 std::shared_ptr
const residual_criterion
205 = gko::stop::ResidualNorm<double>::build().with_reduction_factor(m_tol).on(
208 std::shared_ptr
const iterations_criterion
209 = gko::stop::Iteration::build().with_max_iters(m_max_iter).on(gko_exec);
211 std::shared_ptr
const preconditioner
212 = gko::preconditioner::Jacobi<double>::build()
213 .with_max_block_size(m_preconditionner_max_block_size)
216 std::unique_ptr
const solver_factory
217 = solver_type::build()
218 .with_preconditioner(preconditioner)
219 .with_criteria(residual_criterion, iterations_criterion)
224 m_solver.emplace_back(solver_factory->generate(
225 m_batch_matrix_csr->create_const_view_for_item(i)));
229 std::shared_ptr
const preconditioner
230 = gko::batch::preconditioner::Jacobi<double, int>::build()
231 .with_max_block_size(m_preconditionner_max_block_size)
234 std::shared_ptr solver_factory = solver_type::build()
235 .with_max_iterations(m_max_iter)
236 .with_tolerance(m_tol)
237 .with_preconditioner(preconditioner)
241 m_solver = solver_factory->generate(m_batch_matrix_csr);
243 gko_exec->synchronize();
254 Kokkos::deep_copy(x_view, b);
256 Kokkos::deep_copy(b, x_view);
269 Solver == MatrixBatchCsrSolver::CG || Solver == MatrixBatchCsrSolver::BICGSTAB) {
271 std::shared_ptr
const gko_exec = m_solver[i]->get_executor();
274 std::shared_ptr
const logger = gko::log::Convergence<double>::create();
277 m_solver[i]->add_logger(logger);
279 ->apply(to_gko_multivector(gko_exec, b)->create_const_view_for_item(i),
280 to_gko_multivector(gko_exec, x)->create_view_for_item(i));
281 m_solver[i]->remove_logger(logger);
284 std::fstream log_file(
"csr_log.txt", std::ios::out | std::ios::app);
288 m_batch_matrix_csr->create_const_view_for_item(i),
289 Kokkos::subview(x, i, Kokkos::ALL),
290 Kokkos::subview(b, i, Kokkos::ALL),
296 if (!logger->has_converged()) {
297 throw std::runtime_error(
"Ginkgo did not converge in MatrixBatchCsr");
301 std::shared_ptr
const gko_exec = m_solver->get_executor();
304 std::shared_ptr
const logger = gko::batch::log::BatchConvergence<double>::create();
307 m_solver->add_logger(logger);
308 m_solver->apply(to_gko_multivector(gko_exec, b), to_gko_multivector(gko_exec, x));
309 m_solver->remove_logger(logger);
313 std::fstream log_file(
"csr_log.txt", std::ios::out | std::ios::app);
314 save_logger(log_file, m_batch_matrix_csr, x, b, logger, m_tol);
318 check_conv(
batch_size(), m_tol, gko_exec, logger);
327 double norm(
int batch_idx)
const
329 int const tmp_mat_size =
size();
332 double* vals_proxy = m_batch_matrix_csr->get_values();
333 int* row_ptr_proxy = m_batch_matrix_csr->get_row_ptrs();
334 Kokkos::View<double**, Kokkos::LayoutRight, typename ExecSpace::memory_space> vals_view(
337 m_batch_matrix_csr->get_num_elements_per_item());
338 Kokkos::View<int*, Kokkos::LayoutRight, typename ExecSpace::memory_space>
339 row_ptr_view(row_ptr_proxy, tmp_mat_size + 1);
341 Kokkos::parallel_reduce(
343 Kokkos::RangePolicy<ExecSpace>(0, tmp_mat_size),
344 KOKKOS_LAMBDA(
int const i,
double& res) {
346 for (
int k = row_ptr_view[i]; k < row_ptr_view[i + 1]; k++) {
347 row_sum += Kokkos::abs(vals_view(batch_idx, k));
353 Kokkos::Max<double>(result));
368template <MatrixBatchCsrSolver Solver = MatrixBatchCsrSolver::BICGSTAB>
369void convert_coo_to_csr(
371 Kokkos::View<double*, Kokkos::LayoutRight, Kokkos::DefaultHostExecutionSpace> vals_coo_host,
372 Kokkos::View<int*, Kokkos::LayoutRight, Kokkos::DefaultHostExecutionSpace> row_coo_host,
373 Kokkos::View<int*, Kokkos::LayoutRight, Kokkos::DefaultHostExecutionSpace> col_coo_host)
375 int const mat_size = matrix->size();
376 int const batch_size = matrix->batch_size();
377 int const non_zero_per_system = vals_coo_host.extent(0) / batch_size;
379 Kokkos::View<double**, Kokkos::LayoutRight, Kokkos::DefaultHostExecutionSpace>
380 values_view_host(
"", batch_size, non_zero_per_system);
381 Kokkos::View<int*, Kokkos::LayoutRight, Kokkos::DefaultHostExecutionSpace>
382 idx_view_host(
"", non_zero_per_system);
383 Kokkos::View<int*, Kokkos::LayoutRight, Kokkos::DefaultHostExecutionSpace>
384 nnz_per_row_view_host(
"", mat_size + 1);
385 nnz_per_row_view_host(0) = 0;
386 nnz_per_row_view_host(mat_size) = non_zero_per_system;
388 for (
int i = 0; i < mat_size; i++) {
389 int n_non_zero_in_row = 0;
390 for (
int k = 0; k < non_zero_per_system; k++) {
391 if (row_coo_host(k) == i) {
392 int const idx = nnz_per_row_view_host(i) + n_non_zero_in_row;
393 idx_view_host(idx) = col_coo_host(k);
394 values_view_host(0, idx) = vals_coo_host(k);
398 nnz_per_row_view_host(i + 1) = nnz_per_row_view_host(i) + n_non_zero_in_row;
400 for (
int batch_idx = 1; batch_idx < batch_size; batch_idx++) {
401 for (
int idx = 0; idx < non_zero_per_system; idx++) {
402 values_view_host(batch_idx, idx) = vals_coo_host(batch_idx * non_zero_per_system + idx);
405 auto [values, col_idx, nnz_per_row] = matrix->get_batch_csr();
406 Kokkos::deep_copy(values, values_view_host);
407 Kokkos::deep_copy(col_idx, idx_view_host);
408 Kokkos::deep_copy(nnz_per_row, nnz_per_row_view_host);
Matrix class which is able to manage and solve a batch of sparse linear systems.
Definition matrix_batch_csr.hpp:36
std::tuple< Kokkos::View< double **, Kokkos::LayoutRight, ExecSpace >, Kokkos::View< int *, Kokkos::LayoutRight, ExecSpace >, Kokkos::View< int *, Kokkos::LayoutRight, ExecSpace > > get_batch_csr()
A function to update information about values,indices and the number of non-zero per row for the whol...
Definition matrix_batch_csr.hpp:163
MatrixBatchCsr(const int batch_size, const int mat_size, const int nnz_per_system, std::optional< int > max_iter=std::nullopt, std::optional< double > res_tol=std::nullopt, std::optional< bool > logger=std::nullopt, std::optional< int > preconditionner_max_block_size=1u)
The constructor for MatrixBatchCsr class.
Definition matrix_batch_csr.hpp:79
void solve(BatchedRHS const x, BatchedRHS const b) const
Solve the batched linear problem Ax=b.
Definition matrix_batch_csr.hpp:266
void solve(BatchedRHS const b) const final
Solve the batched linear problem Ax=b.
Definition matrix_batch_csr.hpp:251
double norm(int batch_idx) const
A function returning the norm of a matrix located at batch_idx.
Definition matrix_batch_csr.hpp:327
void setup_solver() final
Perform a pre-process operation on the solver.
Definition matrix_batch_csr.hpp:189
MatrixBatchCsr(Kokkos::View< double **, Kokkos::LayoutRight, ExecSpace > batch_values, Kokkos::View< int *, Kokkos::LayoutRight, ExecSpace > cols_idx, Kokkos::View< int *, Kokkos::LayoutRight, ExecSpace > nnz_per_row, std::optional< int > max_iter=std::nullopt, std::optional< double > res_tol=std::nullopt, std::optional< bool > logger=std::nullopt, std::optional< int > preconditionner_max_block_size=1u)
Constructor for MatrixBatchCsr class.
Definition matrix_batch_csr.hpp:119
MatrixBatch superclass for managing a collection of linear systems.
Definition matrix_batch.hpp:23
std::size_t batch_size() const
Get the batch size of the linear problem.
Definition matrix_batch.hpp:76
std::size_t size() const
Get the size of the square matrix corresponding to a single batch in one of its dimensions.
Definition matrix_batch.hpp:66
Kokkos::View< double **, Kokkos::LayoutRight, ExecSpace > BatchedRHS
The type of a Kokkos::View storing batched right-hand sides. Second dimenion is batch dimension.
Definition matrix_batch.hpp:26