22#include <boost/program_options.hpp>
24#include "arccore/alina/BuiltinBackend.h"
25#include "arccore/alina/RelaxationRuntime.h"
26#include "arccore/alina/CoarseningRuntime.h"
27#include "arccore/alina/SolverRuntime.h"
28#include "arccore/alina/PreconditionerRuntime.h"
29#include "arccore/alina/DeflatedSolver.h"
30#include "arccore/alina/AMG.h"
31#include "arccore/alina/Adapters.h"
32#include "arccore/alina/IO.h"
34#include "arccore/alina/Profiler.h"
38using Alina::precondition;
41int main(
int argc,
char* argv[])
43 auto& prof = Alina::Profiler::globalProfiler();
45 namespace po = boost::program_options;
46 namespace io = Alina::IO;
51 po::options_description desc(
"Options");
53 desc.add_options()(
"help,h",
"Show this help.")(
"prm-file,P",
55 "Parameter file in json format. ")(
57 po::value<vector<string>>()->multitoken(),
58 "Parameters specified as name=value pairs. "
59 "May be provided multiple times. Examples:\n"
60 " -p solver.tol=1e-3\n"
61 " -p precond.coarse_enough=300")(
"matrix,A",
62 po::value<string>()->required(),
63 "System matrix in the MatrixMarket format.")(
66 "The RHS vector in the MatrixMarket format. "
67 "When omitted, a vector of ones is used by default. "
68 "Should only be provided together with a system matrix. ")(
70 po::bool_switch()->default_value(
false),
71 "Scale the matrix so that the diagonal is unit. ")(
74 "Starting null-vectors in the MatrixMarket format. ")(
76 po::value<int>()->default_value(3),
77 "The number of near nullspace vectors to search for. ")(
79 po::bool_switch()->default_value(
false),
80 "When specified, treat input files as binary instead of as MatrixMarket. "
81 "It is assumed the files were converted to binary format with mm2bin utility. ")(
84 "Output the computed nullspace to the MatrixMarket file.");
86 po::positional_options_description p;
90 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
93 if (vm.count(
"help")) {
94 std::cout << desc << std::endl;
98 for (
int i = 0; i < argc; ++i) {
101 std::cout << argv[i];
103 std::cout << std::endl;
106 if (vm.count(
"prm-file")) {
107 prm.read_json(vm[
"prm-file"].as<string>());
110 if (vm.count(
"prm")) {
111 for (
const string& v : vm[
"prm"].as<vector<string>>()) {
116 ptrdiff_t rows, nv = 0, numvec = vm[
"numvec"].as<
int>();
117 vector<ptrdiff_t> ptr, col;
118 vector<double> val, rhs;
119 std::list<std::vector<double>> Z;
122 auto t = prof.scoped_tic(
"read");
124 string Afile = vm[
"matrix"].as<
string>();
125 bool binary = vm[
"binary"].as<
bool>();
128 io::read_crs(Afile, rows, ptr, col, val);
132 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
133 precondition(rows == cols,
"Non-square system matrix");
136 if (vm.count(
"rhs")) {
137 string bfile = vm[
"rhs"].as<
string>();
142 io::read_dense(bfile, n, m, rhs);
145 std::tie(n, m) = io::mm_reader(bfile)(rhs);
148 precondition(n == rows && m == 1,
"The RHS vector has wrong size");
151 rhs.resize(rows, 1.0);
154 if (vm.count(
"null")) {
155 string nfile = vm[
"null"].as<
string>();
157 std::vector<double> null;
161 io::read_dense(nfile, m, nv, null);
164 std::tie(m, nv) = io::mm_reader(nfile)(null);
167 precondition(m == rows,
"Near null-space vectors have wrong size");
169 for (ptrdiff_t i = 0; i < nv; ++i) {
170 Z.emplace_back(rows);
171 for (ptrdiff_t j = 0; j < rows; ++j) {
172 Z.back()[j] = null[j * nv + i];
178 if (vm[
"scale"].as<bool>()) {
179 auto t = prof.scoped_tic(
"scaling");
180 std::vector<double> dia(rows, 1.0);
182 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(rows); ++i) {
184 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j) {
186 d = 1 /
sqrt(val[j]);
193 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(rows); ++i) {
195 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j) {
196 val[j] *= dia[i] * dia[col[j]];
206 std::uniform_real_distribution<double> rnd(-1, 1);
207 std::vector<double> x(rows), zero(rows, 0.0);
209 auto A = std::tie(rows, ptr, col, val);
211 prm.put(
"solver.ns_search",
true);
214 for (
int k = nv; k < numvec; ++k) {
215 auto t = prof.scoped_tic(std::string(
"vector ") + std::to_string(k));
216 std::vector<double> N;
221 for (
const auto& z : Z) {
222 for (ptrdiff_t i = 0; i < rows; ++i) {
228 prm.put(
"precond.coarsening.nullspace.rows", rows);
229 prm.put(
"precond.coarsening.nullspace.cols", k);
230 prm.put(
"precond.coarsening.nullspace.B", N.data());
237 std::cout << std::endl
238 <<
"-------------------------" << std::endl
239 <<
"-- Searching for vector " << k << std::endl
240 <<
"-------------------------" << std::endl
250 std::cout <<
"Iterations: " << r.nbIteration() << std::endl
251 <<
"Error: " << r.residual() << std::endl;
254 for (
const auto& z : Z) {
255 double c = Alina::backend::inner_product(x, z) / Alina::backend::inner_product(z, z);
256 Alina::backend::axpby(-c, z, 1, x);
259 double nx =
sqrt(Alina::backend::inner_product(x, x));
267 std::vector<double> N(numvec * rows);
269 auto t = prof.scoped_tic(
"apply");
272 for (
const auto& z : Z) {
273 for (ptrdiff_t i = 0; i < rows; ++i) {
274 N[i * numvec + j] = z[i];
279 prm.put(
"precond.coarsening.nullspace.rows", rows);
280 prm.put(
"precond.coarsening.nullspace.cols", numvec);
281 prm.put(
"precond.coarsening.nullspace.B", N.data());
287 std::cout << std::endl
288 <<
"-------------------------" << std::endl
289 <<
"-- Solving the system " << std::endl
290 <<
"-------------------------" << std::endl
293 Alina::backend::clear(x);
299 std::cout <<
"Iterations: " << r.nbIteration() << std::endl
300 <<
"Error: " << r.residual() << std::endl;
303 if (vm.count(
"output")) {
304 auto t = prof.scoped_tic(
"write");
305 Alina::IO::mm_write(vm[
"output"].as<string>(), N.data(), rows, numvec);
308 std::cout << prof << std::endl;
Convenience class that bundles together a preconditioner and an iterative solver.
__host__ __device__ double sqrt(double v)
Racine carrée de v.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Runtime-configurable wrappers around iterative solvers.