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