19#include "arccore/alina/BuiltinBackend.h"
20#include "arccore/alina/RelaxationRuntime.h"
21#include "arccore/alina/CoarseningRuntime.h"
22#include "arccore/alina/SolverRuntime.h"
23#include "arccore/alina/PreconditionerRuntime.h"
24#include "arccore/alina/DeflatedSolver.h"
25#include "arccore/alina/AMG.h"
26#include "arccore/alina/Adapters.h"
27#include "arccore/alina/IO.h"
28#include "arccore/alina/Profiler.h"
30#include "arccore/common/internal/ProgramOptions.h"
37using Alina::precondition;
40int main(
int argc,
char* argv[])
42 auto& prof = Alina::Profiler::globalProfiler();
44 namespace po = Arcane::ProgramOptions;
45 namespace io = Alina::IO;
52 desc.add_options()(
"help,h",
"Show this help.")(
"prm-file,P",
54 "Parameter file in json format. ")(
56 po::value<vector<string>>()->multitoken(),
57 "Parameters specified as name=value pairs. "
58 "May be provided multiple times. Examples:\n"
59 " -p solver.tol=1e-3\n"
60 " -p precond.coarse_enough=300")(
"matrix,A",
61 po::value<string>()->required(),
62 "System matrix in the MatrixMarket format.")(
65 "The RHS vector in the MatrixMarket format. "
66 "When omitted, a vector of ones is used by default. "
67 "Should only be provided together with a system matrix. ")(
69 po::bool_switch()->default_value(
false),
70 "Scale the matrix so that the diagonal is unit. ")(
73 "Starting null-vectors in the MatrixMarket format. ")(
75 po::value<int>()->default_value(3),
76 "The number of near nullspace vectors to search for. ")(
78 po::bool_switch()->default_value(
false),
79 "When specified, treat input files as binary instead of as MatrixMarket. "
80 "It is assumed the files were converted to binary format with mm2bin utility. ")(
83 "Output the computed nullspace to the MatrixMarket file.");
92 if (vm.count(
"help")) {
93 std::cout << desc << std::endl;
97 for (
int i = 0; i < argc; ++i) {
100 std::cout << argv[i];
102 std::cout << std::endl;
105 if (vm.count(
"prm-file")) {
106 prm.read_json(vm[
"prm-file"].as<string>());
109 if (vm.count(
"prm")) {
110 for (
const string& v : vm[
"prm"].as<vector<string>>()) {
115 ptrdiff_t rows, nv = 0, numvec = vm[
"numvec"].as<
int>();
116 vector<ptrdiff_t> ptr, col;
117 vector<double> val, rhs;
118 std::list<std::vector<double>> Z;
121 auto t = prof.scoped_tic(
"read");
123 string Afile = vm[
"matrix"].as<
string>();
124 bool binary = vm[
"binary"].as<
bool>();
127 io::read_crs(Afile, rows, ptr, col, val);
131 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
132 precondition(rows == cols,
"Non-square system matrix");
135 if (vm.count(
"rhs")) {
136 string bfile = vm[
"rhs"].as<
string>();
141 io::read_dense(bfile, n, m, rhs);
144 std::tie(n, m) = io::mm_reader(bfile)(rhs);
147 precondition(n == rows && m == 1,
"The RHS vector has wrong size");
150 rhs.resize(rows, 1.0);
153 if (vm.count(
"null")) {
154 string nfile = vm[
"null"].as<
string>();
156 std::vector<double> null;
160 io::read_dense(nfile, m, nv, null);
163 std::tie(m, nv) = io::mm_reader(nfile)(null);
166 precondition(m == rows,
"Near null-space vectors have wrong size");
168 for (ptrdiff_t i = 0; i < nv; ++i) {
169 Z.emplace_back(rows);
170 for (ptrdiff_t j = 0; j < rows; ++j) {
171 Z.back()[j] = null[j * nv + i];
177 if (vm[
"scale"].as<bool>()) {
178 auto t = prof.scoped_tic(
"scaling");
179 std::vector<double> dia(rows, 1.0);
181 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(rows); ++i) {
183 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j) {
185 d = 1 /
sqrt(val[j]);
192 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(rows); ++i) {
194 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j) {
195 val[j] *= dia[i] * dia[col[j]];
205 std::uniform_real_distribution<double> rnd(-1, 1);
206 std::vector<double> x(rows), zero(rows, 0.0);
208 auto A = std::tie(rows, ptr, col, val);
210 prm.put(
"solver.ns_search",
true);
213 for (
int k = nv; k < numvec; ++k) {
214 auto t = prof.scoped_tic(std::string(
"vector ") + std::to_string(k));
215 std::vector<double> N;
220 for (
const auto& z : Z) {
221 for (ptrdiff_t i = 0; i < rows; ++i) {
227 prm.put(
"precond.coarsening.nullspace.rows", rows);
228 prm.put(
"precond.coarsening.nullspace.cols", k);
229 prm.put(
"precond.coarsening.nullspace.B", N.data());
236 std::cout << std::endl
237 <<
"-------------------------" << std::endl
238 <<
"-- Searching for vector " << k << std::endl
239 <<
"-------------------------" << std::endl
249 std::cout <<
"Iterations: " << r.nbIteration() << std::endl
250 <<
"Error: " << r.residual() << std::endl;
253 for (
const auto& z : Z) {
254 double c = Alina::backend::inner_product(x, z) / Alina::backend::inner_product(z, z);
255 Alina::backend::axpby(-c, z, 1, x);
258 double nx =
sqrt(Alina::backend::inner_product(x, x));
266 std::vector<double> N(numvec * rows);
268 auto t = prof.scoped_tic(
"apply");
271 for (
const auto& z : Z) {
272 for (ptrdiff_t i = 0; i < rows; ++i) {
273 N[i * numvec + j] = z[i];
278 prm.put(
"precond.coarsening.nullspace.rows", rows);
279 prm.put(
"precond.coarsening.nullspace.cols", numvec);
280 prm.put(
"precond.coarsening.nullspace.B", N.data());
286 std::cout << std::endl
287 <<
"-------------------------" << std::endl
288 <<
"-- Solving the system " << std::endl
289 <<
"-------------------------" << std::endl
292 Alina::backend::clear(x);
298 std::cout <<
"Iterations: " << r.nbIteration() << std::endl
299 <<
"Error: " << r.residual() << std::endl;
302 if (vm.count(
"output")) {
303 auto t = prof.scoped_tic(
"write");
304 Alina::IO::mm_write(vm[
"output"].as<string>(), N.data(), rows, numvec);
307 std::cout << prof << std::endl;
Convenience class that bundles together a preconditioner and an iterative solver.
Fluent command-line parser builder.
Describes a set of command-line options.
Describes positional (non-option) arguments.
Stores parsed option values.
apfloat sqrt(apfloat v)
Square root of v.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Runtime-configurable wrappers around iterative solvers.