Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
CPR.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#include "arccore/alina/BuiltinBackend.h"
25#include "arccore/alina/StaticMatrix.h"
26#include "arccore/alina/PreconditionedSolver.h"
27#include "arccore/alina/AMG.h"
28#include "arccore/alina/SolverRuntime.h"
29#include "arccore/alina/CoarseningRuntime.h"
30#include "arccore/alina/RelaxationRuntime.h"
31#include "arccore/alina/Relaxation.h"
32#include "arccore/alina/CPRPreconditioner.h"
33#include "arccore/alina/Adapters.h"
34#include "arccore/alina/IO.h"
35#include "arccore/alina/Profiler.h"
36
37#include "arccore/common/internal/ProgramOptions.h"
38
39using namespace Arcane;
40
41using Alina::precondition;
42
43//---------------------------------------------------------------------------
44template <class Matrix>
45void solve_cpr(const Alina::AlinaContext& context, const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
46{
47 auto& prof = Alina::Profiler::globalProfiler();
48
49 auto t1 = prof.scoped_tic("CPR");
50
51 using Backend = Alina::BuiltinBackend<double>;
54
55 prof.tic("setup");
58 solve(context, K, prm);
59 prof.toc("setup");
60
61 std::cout << solve.precond() << std::endl;
62
63 std::vector<double> x(rhs.size(), 0.0);
64
65 prof.tic("setup");
66 Alina::SolverResult r = solve(rhs, x);
67 prof.toc("setup");
68
69 std::cout << "Iterations: " << r.nbIteration() << std::endl
70 << "Error: " << r.residual() << std::endl;
71}
72
73//---------------------------------------------------------------------------
74template <int B, class Matrix>
75void solve_block_cpr(const Alina::AlinaContext& context, const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
76{
77 auto& prof = Alina::Profiler::globalProfiler();
78 auto t1 = prof.scoped_tic("CPR");
79
80 typedef Alina::StaticMatrix<double, B, B> val_type;
81 typedef Alina::StaticMatrix<double, B, 1> rhs_type;
82 typedef Alina::BuiltinBackend<val_type> SBackend;
83 typedef Alina::BuiltinBackend<double> PBackend;
84
87
88 prof.tic("setup");
92 solve(context, Alina::adapter::block_matrix<val_type>(K), prm);
93 prof.toc("setup");
94
95 std::cout << solve.precond() << std::endl;
96
97 std::vector<rhs_type> x(rhs.size(), Alina::math::zero<rhs_type>());
98
99 auto rhs_ptr = reinterpret_cast<const rhs_type*>(rhs.data());
100 size_t n = Alina::backend::nbRow(K) / B;
101
102 prof.tic("solve");
103 Alina::SolverResult r = solve(SmallSpan<const rhs_type>(rhs_ptr, n), x);
104 prof.toc("solve");
105
106 std::cout << "Iterations: " << r.nbIteration() << std::endl
107 << "Error: " << r.residual() << std::endl;
108}
109
110//---------------------------------------------------------------------------
111int main(int argc, char* argv[])
112{
113 auto& prof = Alina::Profiler::globalProfiler();
114 using Alina::precondition;
115 using std::string;
116 using std::vector;
117
118 namespace po = Arcane::ProgramOptions;
119 namespace io = Alina::IO;
120
121 Alina::AlinaContext context;
122
123 po::options_description desc("Options");
124
125 desc.add_options()("help,h", "show help")(
126 "binary,B",
127 po::bool_switch()->default_value(false),
128 "When specified, treat input files as binary instead of as MatrixMarket. "
129 "It is assumed the files were converted to binary format with mm2bin utility. ")(
130 "matrix,A",
131 po::value<string>()->required(),
132 "The system matrix in MatrixMarket format")(
133 "rhs,f",
134 po::value<string>(),
135 "The right-hand side in MatrixMarket format")(
136 "runtime-block-size,b",
137 po::value<int>(),
138 "The block size of the system matrix set at runtime")(
139 "static-block-size,c",
140 po::value<int>()->default_value(1),
141 "The block size of the system matrix set at compiletime")(
142 "params,P",
143 po::value<string>(),
144 "parameter file in json format")(
145 "prm,p",
146 po::value<vector<string>>()->multitoken(),
147 "Parameters specified as name=value pairs. "
148 "May be provided multiple times. Examples:\n"
149 " -p solver.tol=1e-3\n"
150 " -p precond.coarse_enough=300");
151
153 po::store(po::parse_command_line(argc, argv, desc), vm);
154
155 if (vm.count("help")) {
156 std::cout << desc << std::endl;
157 return 0;
158 }
159
160 po::notify(vm);
161
163 if (vm.count("params"))
164 prm.read_json(vm["params"].as<string>());
165
166 if (vm.count("prm")) {
167 for (const string& v : vm["prm"].as<vector<string>>()) {
168 prm.putKeyValue(v);
169 }
170 }
171
172 int cb = vm["static-block-size"].as<int>();
173
174 if (vm.count("runtime-block-size"))
175 prm.put("precond.block_size", vm["runtime-block-size"].as<int>());
176 else
177 prm.put("precond.block_size", cb);
178
179 size_t rows;
180 vector<ptrdiff_t> ptr, col;
181 vector<double> val, rhs;
182 std::vector<char> pm;
183
184 {
185 auto t = prof.scoped_tic("reading");
186
187 string Afile = vm["matrix"].as<string>();
188 bool binary = vm["binary"].as<bool>();
189
190 if (binary) {
191 io::read_crs(Afile, rows, ptr, col, val);
192 }
193 else {
194 size_t cols;
195 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
196 precondition(rows == cols, "Non-square system matrix");
197 }
198
199 if (vm.count("rhs")) {
200 string bfile = vm["rhs"].as<string>();
201
202 size_t n, m;
203
204 if (binary) {
205 io::read_dense(bfile, n, m, rhs);
206 }
207 else {
208 std::tie(n, m) = io::mm_reader(bfile)(rhs);
209 }
210
211 precondition(n == rows && m == 1, "The RHS vector has wrong size");
212 }
213 else {
214 rhs.resize(rows, 1.0);
215 }
216 }
217
218#define CALL_BLOCK_SOLVER(z, data, B) \
219 case B: \
220 solve_block_cpr<B>(context, std::tie(rows, ptr, col, val), rhs, prm); \
221 break;
222
223 switch (cb) {
224 case 1:
225 solve_cpr(context, std::tie(rows, ptr, col, val), rhs, prm);
226 break;
227
228 BOOST_PP_SEQ_FOR_EACH(CALL_BLOCK_SOLVER, ~, ARCCORE_ALINA_BLOCK_SIZES)
229
230 default:
231 precondition(false, "Unsupported block size");
232 break;
233 }
234
235 std::cout << prof << std::endl;
236}
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
Two stage preconditioner of the Constrained Pressure Residual type.
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.