Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
CPRDynamicRowSum.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/preprocessor/seq/for_each.hpp>
23
24#if defined(SOLVER_BACKEND_CUDA)
25# include "arccore/alina/CudaBackend.h"
26# include "arccore/alina/relaxation_cusparse_ilu0.h"
28#else
29# ifndef SOLVER_BACKEND_BUILTIN
30# define SOLVER_BACKEND_BUILTIN
31# endif
32#include "arccore/alina/BuiltinBackend.h"
34#endif
35
36#if defined(SOLVER_BACKEND_BUILTIN)
37#include "arccore/alina/StaticMatrix.h"
38#include "arccore/alina/Adapters.h"
39#endif
40
41#include "arccore/alina/PreconditionedSolver.h"
42#include "arccore/alina/AMG.h"
43#include "arccore/alina/SolverRuntime.h"
44#include "arccore/alina/CoarseningRuntime.h"
45#include "arccore/alina/RelaxationRuntime.h"
46#include "arccore/alina/Relaxation.h"
47#include "arccore/alina/CPRDynamicRowSumPreconditioner.h"
48#include "arccore/alina/Adapters.h"
49#include "arccore/alina/IO.h"
50#include "arccore/alina/Profiler.h"
51
52#include "arccore/common/internal/ProgramOptions.h"
53
54using namespace Arcane;
55
56using Alina::precondition;
57
58//---------------------------------------------------------------------------
59template <class Matrix>
60void solve_cpr(const Alina::AlinaContext& context,
61 const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
62{
63 auto& prof = Alina::Profiler::globalProfiler();
64 Backend::params bprm;
65
66#if defined(SOLVER_BACKEND_VEXCL)
67 vex::Context ctx(vex::Filter::Env);
68 std::cout << ctx << std::endl;
69 bprm.q = ctx;
70#elif defined(SOLVER_BACKEND_VIENNACL)
71 std::cout
72 << viennacl::ocl::current_device().name()
73 << " (" << viennacl::ocl::current_device().vendor() << ")\n\n";
74#elif defined(SOLVER_BACKEND_CUDA)
75 cusparseCreate(&bprm.cusparse_handle);
76 {
77 int dev;
78 cudaGetDevice(&dev);
79
80 cudaDeviceProp prop;
81 cudaGetDeviceProperties(&prop, dev);
82 std::cout << prop.name << std::endl
83 << std::endl;
84 }
85#endif
86
87 auto t1 = prof.scoped_tic("CPR");
88
90 PPrecond;
91
93
94 prof.tic("setup");
98 solve(context, K, prm, bprm);
99 prof.toc("setup");
100
101 std::cout << solve.precond() << std::endl;
102
103 auto f = Backend::copy_vector(rhs, bprm);
104 auto x = Backend::create_vector(rhs.size(), bprm);
105 Alina::backend::clear(*x);
106
107 prof.tic("solve");
108 Alina::SolverResult r = solve(*f, *x);
109 prof.toc("solve");
110
111 std::cout << "Iterations: " << r.nbIteration() << std::endl
112 << "Error: " << r.residual() << std::endl;
113}
114
115#if defined(SOLVER_BACKEND_BUILTIN)
116//---------------------------------------------------------------------------
117template <int B, class Matrix>
118void solve_block_cpr(const Alina::AlinaContext& context, const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
119{
120 auto& prof = Alina::Profiler::globalProfiler();
121 auto t1 = prof.scoped_tic("CPR");
122
123 typedef Alina::StaticMatrix<double, B, B> val_type;
124 typedef Alina::StaticMatrix<double, B, 1> rhs_type;
125
126 typedef Alina::BuiltinBackend<val_type> SBackend;
127 typedef Alina::BuiltinBackend<double> PBackend;
128
131
132 typename SBackend::params bprm;
133
134 prof.tic("setup");
138 solve(context, Alina::adapter::block_matrix<val_type>(K), prm, bprm);
139 prof.toc("setup");
140
141 std::cout << solve.precond() << std::endl;
142
143 size_t n = Alina::backend::nbRow(K) / B;
144 auto rhs_ptr = reinterpret_cast<const rhs_type*>(rhs.data());
145
146 SmallSpan<const rhs_type> f(rhs_ptr, n);
147
148 auto x = SBackend::create_vector(n, bprm);
149 Alina::backend::clear(*x);
150
151 prof.tic("solve");
152 Alina::SolverResult r = solve(f, *x);
153 prof.toc("solve");
154
155 std::cout << "Iterations: " << r.nbIteration() << std::endl
156 << "Error: " << r.residual() << std::endl;
157}
158#endif
159
160//---------------------------------------------------------------------------
161int main(int argc, char* argv[])
162{
163 auto& prof = Alina::Profiler::globalProfiler();
164 using Alina::precondition;
165 using std::string;
166 using std::vector;
167
168 Alina::AlinaContext context;
169
170 namespace po = Arcane::ProgramOptions;
171 namespace io = Alina::IO;
172
173 po::options_description desc("Options");
174
175 desc.add_options()("help,h", "show help");
176 desc.add_options()("binary,B",
177 po::bool_switch()->default_value(false),
178 "When specified, treat input files as binary instead of as MatrixMarket. "
179 "It is assumed the files were converted to binary format with mm2bin utility. ");
180 desc.add_options()("matrix,A",
181 po::value<string>()->required(),
182 "The system matrix in MatrixMarket format");
183 desc.add_options()("rhs,f",
184 po::value<string>(),
185 "The right-hand side in MatrixMarket format");
186 desc.add_options()("weights,w",
187 po::value<string>(),
188 "Equation weights in MatrixMarket format");
189 desc.add_options()("runtime-block-size,b",
190 po::value<int>(),
191 "The block size of the system matrix set at runtime");
192 desc.add_options()("static-block-size,c",
193 po::value<int>()->default_value(1),
194 "The block size of the system matrix set at compiletime");
195 desc.add_options()("params,P",
196 po::value<string>(),
197 "parameter file in json format");
198 desc.add_options()("prm,p",
199 po::value<vector<string>>()->multitoken(),
200 "Parameters specified as name=value pairs. "
201 "May be provided multiple times. Examples:\n"
202 " -p solver.tol=1e-3\n"
203 " -p precond.coarse_enough=300");
204
206 po::store(po::parse_command_line(argc, argv, desc), vm);
207
208 if (vm.count("help")) {
209 std::cout << desc << std::endl;
210 return 0;
211 }
212
213 po::notify(vm);
214
216 if (vm.count("params"))
217 prm.read_json(vm["params"].as<string>());
218
219 if (vm.count("prm")) {
220 for (const string& v : vm["prm"].as<vector<string>>()) {
221 prm.putKeyValue(v);
222 }
223 }
224
225 int cb = vm["static-block-size"].as<int>();
226
227 if (vm.count("runtime-block-size"))
228 prm.put("precond.block_size", vm["runtime-block-size"].as<int>());
229 else
230 prm.put("precond.block_size", cb);
231
232 size_t rows;
233 vector<ptrdiff_t> ptr, col;
234 vector<double> val, rhs, wgt;
235 std::vector<char> pm;
236
237 {
238 auto t = prof.scoped_tic("reading");
239
240 string Afile = vm["matrix"].as<string>();
241 bool binary = vm["binary"].as<bool>();
242
243 if (binary) {
244 io::read_crs(Afile, rows, ptr, col, val);
245 }
246 else {
247 size_t cols;
248 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
249 precondition(rows == cols, "Non-square system matrix");
250 }
251
252 if (vm.count("rhs")) {
253 string bfile = vm["rhs"].as<string>();
254
255 size_t n, m;
256
257 if (binary) {
258 io::read_dense(bfile, n, m, rhs);
259 }
260 else {
261 std::tie(n, m) = io::mm_reader(bfile)(rhs);
262 }
263
264 precondition(n == rows && m == 1, "The RHS vector has wrong size");
265 }
266 else {
267 rhs.resize(rows, 1.0);
268 }
269
270 if (vm.count("weights")) {
271 string wfile = vm["weights"].as<string>();
272
273 size_t n, m;
274
275 if (binary) {
276 io::read_dense(wfile, n, m, wgt);
277 }
278 else {
279 std::tie(n, m) = io::mm_reader(wfile)(wgt);
280 }
281
282 prm.put("precond.weights", &wgt[0]);
283 prm.put("precond.weights_size", wgt.size());
284 }
285 }
286
287#define CALL_BLOCK_SOLVER(z, data, B) \
288 case B: \
289 solve_block_cpr<B>(context, std::tie(rows, ptr, col, val), rhs, prm); \
290 break;
291
292 switch (cb) {
293 case 1:
294 solve_cpr(context, std::tie(rows, ptr, col, val), rhs, prm);
295 break;
296
297#if defined(SOLVER_BACKEND_BUILTIN) || defined(SOLVER_BACKEND_VEXCL)
298 BOOST_PP_SEQ_FOR_EACH(CALL_BLOCK_SOLVER, ~, ARCCORE_ALINA_BLOCK_SIZES)
299#endif
300
301 default:
302 precondition(false, "Unsupported block size");
303 break;
304 }
305
306 std::cout << prof << std::endl;
307}
Algebraic multigrid method.
Definition AMG.h:71
Convenience class that bundles together a preconditioner and an iterative solver.
Class to store parameters as a hierarchical key/value tree.
Definition AlinaUtils.h:113
Allows to use an AMG smoother as standalone preconditioner.
Definition Relaxation.h:144
Result of a solution.
Definition AlinaUtils.h:56
CPR preconditioner with Dynamic Row Sum modification.
Matrix class, to be used by user.
Describes a set of command-line options.
Stores parsed option values.
View of an array of elements of type T.
Definition Span.h:803
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Runtime-configurable wrappers around iterative solvers.