Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DeflatedSolver.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/*---------------------------------------------------------------------------*/
9/*
10 * This file is based on the work on AMGCL library (version march 2026)
11 * which can be found at https://github.com/ddemidov/amgcl.
12 *
13 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
14 * SPDX-License-Identifier: MIT
15 */
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19#include <iostream>
20#include <string>
21
22#include <boost/program_options.hpp>
23
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"
33
34#include "arccore/alina/Profiler.h"
35
36using namespace Arcane;
37
38using Alina::precondition;
39
40//---------------------------------------------------------------------------
41int main(int argc, char* argv[])
42{
43 auto& prof = Alina::Profiler::globalProfiler();
44
45 namespace po = boost::program_options;
46 namespace io = Alina::IO;
47
48 using std::string;
49 using std::vector;
50
51 po::options_description desc("Options");
52
53 desc.add_options()("help,h", "Show this help.")("prm-file,P",
54 po::value<string>(),
55 "Parameter file in json format. ")(
56 "prm,p",
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.")(
64 "rhs,f",
65 po::value<string>(),
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. ")(
69 "defvec,D",
70 po::value<string>(),
71 "The near null-space vectors in the MatrixMarket format. ")(
72 "coords,C",
73 po::value<string>(),
74 "Coordinate matrix where number of rows corresponds to the number of grid nodes "
75 "and the number of columns corresponds to the problem dimensionality (2 or 3). "
76 "Will be used to construct near null-space vectors as rigid body modes. ")(
77 "binary,B",
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. ")(
81 "single-level,1",
82 po::bool_switch()->default_value(false),
83 "When specified, the AMG hierarchy is not constructed. "
84 "Instead, the problem is solved using a single-level smoother as preconditioner. ")(
85 "output,o",
86 po::value<string>(),
87 "Output file. Will be saved in the MatrixMarket format. "
88 "When omitted, the solution is not saved. ");
89
90 po::positional_options_description p;
91 p.add("prm", -1);
92
93 po::variables_map vm;
94 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
95 po::notify(vm);
96
97 if (vm.count("help")) {
98 std::cout << desc << std::endl;
99 return 0;
100 }
101
102 for (int i = 0; i < argc; ++i) {
103 if (i)
104 std::cout << " ";
105 std::cout << argv[i];
106 }
107 std::cout << std::endl;
108
110 if (vm.count("prm-file")) {
111 prm.read_json(vm["prm-file"].as<string>());
112 }
113
114 if (vm.count("prm")) {
115 for (const string& v : vm["prm"].as<vector<string>>()) {
116 prm.putKeyValue(v);
117 }
118 }
119
120 if (!vm.count("defvec") && !vm.count("coords")) {
121 std::cerr << "Either defvec or coords should be given" << std::endl;
122 return 1;
123 }
124
125 ptrdiff_t rows, nv;
126 vector<ptrdiff_t> ptr, col;
127 vector<double> val, rhs, z;
128
129 {
130 auto t = prof.scoped_tic("reading");
131
132 string Afile = vm["matrix"].as<string>();
133 bool binary = vm["binary"].as<bool>();
134
135 if (binary) {
136 io::read_crs(Afile, rows, ptr, col, val);
137 }
138 else {
139 ptrdiff_t cols;
140 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
141 precondition(rows == cols, "Non-square system matrix");
142 }
143
144 if (vm.count("rhs")) {
145 string bfile = vm["rhs"].as<string>();
146
147 ptrdiff_t n, m;
148
149 if (binary) {
150 io::read_dense(bfile, n, m, rhs);
151 }
152 else {
153 std::tie(n, m) = io::mm_reader(bfile)(rhs);
154 }
155
156 precondition(n == rows && m == 1, "The RHS vector has wrong size");
157 }
158 else {
159 rhs.resize(rows, 1.0);
160 }
161
162 if (vm.count("defvec")) {
163 string nfile = vm["defvec"].as<string>();
164 std::vector<double> N;
165
166 ptrdiff_t m;
167
168 if (binary) {
169 io::read_dense(nfile, m, nv, N);
170 }
171 else {
172 std::tie(m, nv) = io::mm_reader(nfile)(N);
173 }
174
175 precondition(m == rows, "Deflation vectors have wrong size");
176
177 z.resize(N.size());
178 for (ptrdiff_t i = 0; i < rows; ++i)
179 for (ptrdiff_t j = 0; j < nv; ++j)
180 z[i + j * rows] = N[i * nv + j];
181 }
182 else if (vm.count("coords")) {
183 string cfile = vm["coords"].as<string>();
184 std::vector<double> coo;
185
186 ptrdiff_t m, ndim;
187
188 if (binary) {
189 io::read_dense(cfile, m, ndim, coo);
190 }
191 else {
192 std::tie(m, ndim) = io::mm_reader(cfile)(coo);
193 }
194
195 precondition(m * ndim == rows && (ndim == 2 || ndim == 3), "Coordinate matrix has wrong size");
196
197 nv = Alina::rigid_body_modes(ndim, coo, z, /*transpose = */ true);
198 }
199
200 prm.put("nvec", nv);
201 prm.put("vec", z.data());
202 }
203
204 std::vector<double> x(rows, 0);
205
206 if (vm["single-level"].as<bool>())
207 prm.put("precond.class", "relaxation");
208
209 typedef Alina::BuiltinBackend<double> Backend;
212 Solver;
213
214 auto A = std::tie(rows, ptr, col, val);
215
216 prof.tic("setup");
217 Solver solve(A, prm);
218 prof.toc("setup");
219
220 prof.tic("solve");
221 Alina::SolverResult result = solve(rhs, x);
222 prof.toc("solve");
223
224 if (vm.count("output")) {
225 auto t = prof.scoped_tic("write");
226 Alina::IO::mm_write(vm["output"].as<string>(), x.data(), x.size());
227 }
228
229 std::vector<double> r(rows);
230 Alina::backend::residual(rhs, A, x, r);
231
232 std::cout << "Iterations: " << result.nbIteration() << std::endl
233 << "Error: " << result.residual() << std::endl
234 << "True error: " << sqrt(Alina::backend::inner_product(r, r)) / sqrt(Alina::backend::inner_product(rhs, rhs))
235 << prof << std::endl;
236}
Iterative preconditioned solver with deflation.
Result of a solving.
Definition AlinaUtils.h:52
__host__ __device__ double sqrt(double v)
Racine carrée de v.
Definition Math.h:135
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Runtime-configurable wrappers around iterative solvers.