20#pragma GCC diagnostic ignored "-Wdeprecated-copy"
21#pragma GCC diagnostic ignored "-Wint-in-bool-context"
31#include <boost/range/iterator_range.hpp>
32#include <boost/scope_exit.hpp>
34#if defined(SOLVER_BACKEND_CUDA)
35# include "arccore/alina/CudaBackend.h"
36# include "arccore/alina/relaxation_cusparse_ilu0.h"
39# ifndef SOLVER_BACKEND_BUILTIN
40# define SOLVER_BACKEND_BUILTIN
42#include "arccore/alina/BuiltinBackend.h"
46#include "arccore/alina/IO.h"
47#include "arccore/alina/Adapters.h"
48#include "arccore/alina/AMG.h"
49#include "arccore/alina/CoarseningRuntime.h"
50#include "arccore/alina/RelaxationRuntime.h"
51#include "arccore/alina/DistributedPreconditionedSolver.h"
52#include "arccore/alina/DistributedSchurPressureCorrection.h"
53#include "arccore/alina/DistributedPreconditioner.h"
54#include "arccore/alina/DistributedSubDomainDeflation.h"
55#include "arccore/alina/DistributedSolverRuntime.h"
56#include "arccore/alina/DistributedDirectSolverRuntime.h"
57#include "arccore/alina/Profiler.h"
59#include "arccore/common/internal/ProgramOptions.h"
62using namespace Arcane::Alina;
64using Alina::precondition;
69 const std::string& A_file,
70 const std::string& rhs_file,
71 const std::string& part_file,
72 std::vector<ptrdiff_t>& ptr,
73 std::vector<ptrdiff_t>& col,
74 std::vector<double>& val,
75 std::vector<double>& rhs)
79 std::vector<ptrdiff_t> domain(world.size + 1, 0);
80 std::vector<int> part;
85 precondition(p < world.size,
"MPI world does not correspond to partition");
87 std::partial_sum(domain.begin(), domain.end(), domain.begin());
89 ptrdiff_t chunk_beg = domain[world.rank];
90 ptrdiff_t chunk_end = domain[world.rank + 1];
91 ptrdiff_t chunk = chunk_end - chunk_beg;
94 std::vector<ptrdiff_t> order(n);
95 for (ptrdiff_t i = 0; i < n; ++i)
96 order[i] = domain[part[i]]++;
98 std::rotate(domain.begin(), domain.end() - 1, domain.end());
103 using namespace Arcane::Alina::IO;
105 std::ifstream A(A_file.c_str(), std::ios::binary);
106 precondition(A,
"Failed to open matrix file (" + A_file +
")");
108 std::ifstream b(rhs_file.c_str(), std::ios::binary);
109 precondition(b,
"Failed to open rhs file (" + rhs_file +
")");
112 precondition(read(A, rows),
"File I/O error");
113 precondition(rows == n,
"Matrix and partition have incompatible sizes");
116 ptr.reserve(chunk + 1);
119 std::vector<ptrdiff_t> gptr(n + 1);
120 precondition(read(A, gptr),
"File I/O error");
122 size_t col_beg =
sizeof(rows) +
sizeof(gptr[0]) * (n + 1);
123 size_t val_beg = col_beg +
sizeof(col[0]) * gptr.back();
124 size_t rhs_beg = 2 *
sizeof(ptrdiff_t);
127 for (ptrdiff_t i = 0; i < n; ++i)
128 if (part[i] == world.rank)
129 ptr.push_back(gptr[i + 1] - gptr[i]);
131 std::partial_sum(ptr.begin(), ptr.end(), ptr.begin());
134 col.reserve(ptr.back());
136 val.reserve(ptr.back());
141 for (ptrdiff_t i = 0; i < n; ++i) {
142 if (part[i] != world.rank)
146 A.seekg(col_beg + gptr[i] *
sizeof(c));
147 for (ptrdiff_t j = gptr[i], e = gptr[i + 1]; j < e; ++j) {
148 precondition(read(A, c),
"File I/O error (1)");
149 col.push_back(order[c]);
153 for (ptrdiff_t i = 0; i < n; ++i) {
154 if (part[i] != world.rank)
158 A.seekg(val_beg + gptr[i] *
sizeof(v));
159 for (ptrdiff_t j = gptr[i], e = gptr[i + 1]; j < e; ++j) {
160 precondition(read(A, v),
"File I/O error (2)");
165 for (ptrdiff_t i = 0; i < n; ++i) {
166 if (part[i] != world.rank)
170 b.seekg(rhs_beg + i *
sizeof(f));
171 precondition(read(b, f),
"File I/O error (3)");
180int main(
int argc,
char* argv[])
182 auto& prof = Alina::Profiler::globalProfiler();
185 MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
186 BOOST_SCOPE_EXIT(
void)
195 std::cout <<
"World size: " << world.size << std::endl;
198 namespace po = Arcane::ProgramOptions;
202 desc.add_options()(
"help,h",
"show help")(
204 po::value<string>()->required(),
205 "The system matrix in binary format")(
208 "The right-hand side in binary format")(
210 po::value<string>()->required(),
211 "Partitioning of the problem in MatrixMarket format")(
214 "The pressure mask in binary format. Or, if the parameter has "
215 "the form '%n:m', then each (n+i*m)-th variable is treated as pressure.")(
218 "parameter file in json format")(
220 po::value<std::vector<string>>()->multitoken(),
221 "Parameters specified as name=value pairs. "
222 "May be provided multiple times. Examples:\n"
223 " -p solver.tol=1e-3\n"
224 " -p precond.coarse_enough=300");
227 po::store(po::parse_command_line(argc, argv, desc), vm);
229 if (vm.count(
"help")) {
231 std::cout << desc << std::endl;
238 if (vm.count(
"params"))
239 prm.read_json(vm[
"params"].as<string>());
241 if (vm.count(
"prm")) {
242 for (
const string& v : vm[
"prm"].as<std::vector<string>>()) {
247 prof.tic(
"read problem");
248 std::vector<ptrdiff_t> ptr;
249 std::vector<ptrdiff_t> col;
250 std::vector<double> val;
251 std::vector<double> rhs;
253 std::vector<ptrdiff_t> domain = read_problem(
255 vm[
"matrix"].as<string>(), vm[
"rhs"].as<string>(), vm[
"part"].as<string>(),
258 ptrdiff_t chunk = domain[world.rank + 1] - domain[world.rank];
259 prof.toc(
"read problem");
261 std::vector<char> pm;
262 if (vm.count(
"pmask")) {
263 std::string pmask = vm[
"pmask"].as<
string>();
264 prm.put(
"precond.pmask_size", chunk);
270 prm.put(
"precond.pmask_pattern", pmask);
273 precondition(
false,
"Pressure mask may only be set with a pattern");
278 prm.put(
"precond.psolver.num_def_vec", 1);
279 prm.put(
"precond.psolver.def_vec", &dv);
283#if defined(SOLVER_BACKEND_VEXCL)
284 vex::Context ctx(vex::Filter::Env);
285 std::cout << ctx << std::endl;
287#elif defined(SOLVER_BACKEND_CUDA)
288 cusparseCreate(&bprm.cusparse_handle);
291 auto f = Backend::copy_vector(rhs, bprm);
292 auto x = Backend::create_vector(chunk, bprm);
294 Alina::backend::clear(*x);
312 Solver solve(world, std::tie(chunk, ptr, col, val), prm, bprm);
313 double tm_setup = prof.toc(
"setup");
317 double tm_solve = prof.toc(
"solve");
319 if (world.rank == 0) {
320 std::cout <<
"Iters: " << r.nbIteration() << std::endl
321 <<
"Error: " << r.residual() << std::endl
322 << prof << std::endl;
Algebraic multigrid method.
Distributed block preconditioner.
Runtime wrapper for distributed direct solvers.
Iterative solver wrapper for distributed linear systems.
Distributed Schur complement pressure correction preconditioner.
Distributed solver based on subdomain deflation.
Allows to use an AMG smoother as standalone preconditioner.
Describes a set of command-line options.
Stores parsed option values.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Alina::detail::empty_params params
Pointwise constant deflation vectors.
Convenience wrapper around MPI_Comm.