Arcane  4.2.1.0
Developer documentation
Loading...
Searching...
No Matches
TestSolverCommon.h
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#ifndef TESTS_TEST_SOLVER_HPP
20#define TESTS_TEST_SOLVER_HPP
21
22#include "arccore/alina/AMG.h"
23#include "arccore/alina/SolverRuntime.h"
24#include "arccore/alina/CoarseningRuntime.h"
25#include "arccore/alina/RelaxationRuntime.h"
26#include "arccore/alina/Relaxation.h"
27#include "arccore/alina/PreconditionedSolver.h"
28#include "arccore/alina/Adapters.h"
29#include "arccore/alina/Profiler.h"
30
31#include "SampleProblemCommon.h"
32
33using namespace Arcane;
34
35namespace
36{
38}
39
40//---------------------------------------------------------------------------
41
42template <class Backend, class Matrix>
43void test_solver(const Matrix& A,
44 std::shared_ptr<typename Backend::vector> const& f,
45 std::shared_ptr<typename Backend::vector>& x,
46 Alina::eSolverType solver,
47 Alina::eRelaxationType relaxation,
48 Alina::eCoarserningType coarsening,
49 typename Backend::params const& bprm,
50 bool test_null_space = false)
51{
53 prm.put("precond.coarse_enough", 500);
54 prm.put("precond.coarsening.type", coarsening);
55 prm.put("precond.relax.type", relaxation);
56 prm.put("solver.type", solver);
57
58 typedef typename Backend::value_type value_type;
59 std::vector<double> null;
60
61 if (test_null_space && Alina::math::static_rows<value_type>::value == 1) {
62 Int64 n = Alina::backend::nbRow(*A);
63 null.resize(n, 1.0);
64
65 prm.put("precond.coarsening.nullspace.cols", 1);
66 prm.put("precond.coarsening.nullspace.rows", n);
67 prm.put("precond.coarsening.nullspace.B", &null[0]);
68 }
69
72 solve(A, prm, bprm);
73
74 std::cout << solve.precond() << std::endl;
75
76 Alina::backend::clear(*x);
77
78 Alina::SolverResult r = solve(*f, *x);
79
80 std::cout << "Iterations: " << r.nbIteration() << std::endl
81 << "Error: " << r.residual() << std::endl
82 << std::endl;
83
84 ASSERT_NEAR(r.residual(), 0.0, 1e-4);
85}
86
87//---------------------------------------------------------------------------
88template <class Backend, class Matrix>
89void test_rap(const Matrix& A,
90 std::shared_ptr<typename Backend::vector> const& f,
91 std::shared_ptr<typename Backend::vector>& x,
92 Alina::eSolverType solver,
93 Alina::eRelaxationType relaxation,
94 typename Backend::params const& bprm)
95{
97 prm.put("precond.type", relaxation);
98 prm.put("solver.type", solver);
99
102 solve(A, prm, bprm);
103
104 std::cout << "Using " << relaxation << " as preconditioner" << std::endl;
105
106 Alina::backend::clear(*x);
107
108 Alina::SolverResult r = solve(*f, *x);
109
110 std::cout << "Iterations: " << r.nbIteration() << std::endl
111 << "Error: " << r.residual() << std::endl;
112
113 ASSERT_NEAR(r.residual(), 0.0, 1e-4);
114}
115
116template <class Backend, class value_type, class col_type, class ptr_type, class rhs_type>
117void test_problem(size_t n,
118 std::vector<ptr_type> ptr,
119 std::vector<col_type> col,
120 std::vector<value_type> val,
121 std::vector<rhs_type> rhs,
122 typename Backend::params const& bprm)
123{
124 Alina::eCoarserningType coarsening[] = {
125 Alina::eCoarserningType::aggregation,
126 Alina::eCoarserningType::smoothed_aggregation,
127 Alina::eCoarserningType::smoothed_aggr_emin,
128 Alina::eCoarserningType::ruge_stuben
129 };
130
131 Alina::eRelaxationType relaxation[] = {
132 Alina::eRelaxationType::spai0,
133 Alina::eRelaxationType::spai1,
134 Alina::eRelaxationType::damped_jacobi,
135 Alina::eRelaxationType::gauss_seidel,
136 Alina::eRelaxationType::ilu0,
137 Alina::eRelaxationType::iluk,
138 Alina::eRelaxationType::ilup,
139 Alina::eRelaxationType::ilut,
140 Alina::eRelaxationType::chebyshev
141 };
142
143 Alina::eSolverType solver[] = {
144 Alina::eSolverType::cg,
145 Alina::eSolverType::bicgstab,
146 Alina::eSolverType::bicgstabl,
147 Alina::eSolverType::gmres,
148 Alina::eSolverType::lgmres,
149 Alina::eSolverType::fgmres,
150 Alina::eSolverType::idrs
151 };
152
153 typename Backend::params prm;
154
155 auto y = Backend::copy_vector(rhs, prm);
156 auto x = Backend::create_vector(n, prm);
157
158 // Test solvers
159 for (Alina::eSolverType s : solver) {
160 std::cout << "Solver: " << s << std::endl;
161 try {
162 test_solver<Backend>(Alina::adapter::zero_copy_direct(n, ptr.data(), col.data(), val.data()),
163 y, x, s, relaxation[0], coarsening[0], bprm);
164 }
165 catch (const std::logic_error&) {
166 }
167 }
168
169 // Test smoothers
170 for (Alina::eRelaxationType r : relaxation) {
171 std::cout << "Relaxation: " << r << std::endl;
172 try {
173 test_solver<Backend>(Alina::adapter::zero_copy_direct(n, ptr.data(), col.data(), val.data()),
174 y, x, solver[0], r, coarsening[0], bprm);
175 }
176 catch (const std::logic_error&) {
177 }
178
179 try {
180 std::cout << "Relaxation as preconditioner: " << r << std::endl;
181
182 test_rap<Backend>(Alina::adapter::zero_copy_direct(n, ptr.data(), col.data(), val.data()),
183 y, x, solver[0], r, bprm);
184 }
185 catch (const std::logic_error&) {
186 }
187 }
188
189 // Test coarsening
190 for (Alina::eCoarserningType c : coarsening) {
191 std::cout << "Coarsening: " << c << std::endl;
192
193 try {
194 test_solver<Backend>(Alina::adapter::zero_copy_direct(n, ptr.data(), col.data(), val.data()),
195 y, x, solver[0], relaxation[0], c, bprm);
196 }
197 catch (const std::logic_error&) {
198 }
199
200 switch (c) {
201 case Alina::eCoarserningType::aggregation:
202 case Alina::eCoarserningType::smoothed_aggregation:
203 case Alina::eCoarserningType::smoothed_aggr_emin:
204 test_solver<Backend>(Alina::adapter::zero_copy_direct(n, ptr.data(), col.data(), val.data()),
205 y, x, solver[0], relaxation[0], c, bprm, /*test_null_space*/ true);
206 break;
207 default:
208 break;
209 }
210 }
211}
212
213template <class Backend>
214void test_backend(typename Backend::params const& bprm = typename Backend::params())
215{
216 typedef typename Backend::value_type value_type;
217 typedef typename Backend::col_type col_type;
218 typedef typename Backend::ptr_type ptr_type;
219 typedef typename Alina::math::rhs_of<value_type>::type rhs_type;
220
221 // Poisson 3D
222 {
223 std::vector<ptr_type> ptr;
224 std::vector<col_type> col;
225 std::vector<value_type> val;
226 std::vector<rhs_type> rhs;
227
228 size_t n = sample_problem(24, val, col, ptr, rhs);
229
230 test_problem<Backend>(n, ptr, col, val, rhs, bprm);
231 }
232
233 // Trivial problem
234 {
235 std::vector<ptr_type> ptr;
236 std::vector<col_type> col;
237 std::vector<value_type> val;
238 std::vector<rhs_type> rhs;
239
240 val.push_back(Alina::math::identity<value_type>());
241 val.push_back(Alina::math::identity<value_type>());
242 col.push_back(0);
243 col.push_back(1);
244 ptr.push_back(0);
245 ptr.push_back(1);
246 ptr.push_back(2);
247 rhs.push_back(Alina::math::constant<rhs_type>(1.0));
248 rhs.push_back(Alina::math::zero<rhs_type>());
249
250 size_t n = rhs.size();
251
252 test_problem<Backend>(n, ptr, col, val, rhs, bprm);
253 }
254}
255
256/*---------------------------------------------------------------------------*/
257/*---------------------------------------------------------------------------*/
258
259#if defined(ARCCORE_HAS_ACCELERATOR_THREAD)
260#define ARCCORE_ALINA_TEST_DO_TEST_TASK(name1, name2, func) \
261 TEST(name1, name2##_task4) \
262 { \
263 func(false, 4); \
264 }
265#else
266#define ARCCORE_ALINA_TEST_DO_TEST_TASK(name1, name2, func)
267#endif
268
269#define ARCCORE_ALINA_TEST_DO_TEST_SEQUENTIAL(name1, name2, func) \
270 TEST(name1, name2) \
271 { \
272 func(false, 0); \
273 }
274
276#define ARCCORE_ALINA_TEST_DO_TEST_ACCELERATOR(name1, name2, func) \
277 ARCCORE_ALINA_TEST_DO_TEST_TASK(name1, name2, func); \
278 ARCCORE_ALINA_TEST_DO_TEST_SEQUENTIAL(name1, name2, func);
279
280/*---------------------------------------------------------------------------*/
281/*---------------------------------------------------------------------------*/
282
283#endif
Convenience class that bundles together a preconditioner and an iterative solver.
Profiler class.
Definition Profiler.h:50
Result of a solution.
Definition AlinaUtils.h:53
Matrix class, to be used by user.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Runtime-configurable wrappers around iterative solvers.
Number of rows for statically sized matrix types.