24#pragma GCC diagnostic ignored "-Wdeprecated-copy"
25#pragma GCC diagnostic ignored "-Wint-in-bool-context"
27#include <boost/range/iterator_range.hpp>
28#include <boost/preprocessor/seq/for_each.hpp>
30#if defined(SOLVER_BACKEND_CUDA)
31#include "arccore/alina/CudaBackend.h"
32#include "arccore/alina/relaxation_cusparse_ilu0.h"
34#elif defined(SOLVER_BACKEND_EIGEN)
35#include "arccore/alina/EigenBackend.h"
38#ifndef SOLVER_BACKEND_BUILTIN
39#define SOLVER_BACKEND_BUILTIN
41#include "arccore/alina/BuiltinBackend.h"
42#include "arccore/alina/StaticMatrix.h"
43#include "arccore/alina/Adapters.h"
49#include <arccore/base/PlatformUtils.h>
50#include <arccore/base/String.h>
51#include <arccore/base/Convert.h>
53#include "arccore/alina/RelaxationRuntime.h"
54#include "arccore/alina/CoarseningRuntime.h"
55#include "arccore/alina/SolverRuntime.h"
56#include "arccore/alina/PreconditionerRuntime.h"
57#include "arccore/alina/PreconditionedSolver.h"
58#include "arccore/alina/AMG.h"
59#include "arccore/alina/Adapters.h"
60#include "arccore/alina/IO.h"
61#include "arccore/alina/Profiler.h"
63#include "arccore/common/internal/ProgramOptions.h"
65#include "SampleProblemCommon.h"
67#ifndef ARCCORE_ALINA_BLOCK_SIZES
68#define ARCCORE_ALINA_BLOCK_SIZES (3)(4)
73using Alina::precondition;
75#ifdef SOLVER_BACKEND_BUILTIN
77_doHypreSolver(
int nb_row,
78 std::vector<ptrdiff_t>
const& ptr,
79 std::vector<ptrdiff_t>
const& col,
80 std::vector<double>
const& val,
81 std::vector<double>
const& rhs,
82 std::vector<double>& x,
83 int argc,
char* argv[]);
86#ifdef SOLVER_BACKEND_BUILTIN
91 std::vector<ptrdiff_t>
const& ptr,
92 std::vector<ptrdiff_t>
const& col,
93 std::vector<double>
const& val,
94 std::vector<double>
const& rhs,
95 std::vector<double>& x,
98 auto& prof = Alina::Profiler::globalProfiler();
106 auto As = std::tie(rows, ptr, col, val);
107 auto Ab = Alina::adapter::block_matrix<value_type>(As);
109 std::tuple<size_t, double> info;
117 Solver solve(perm(Ab), prm);
120 std::cout << solve << std::endl;
122 rhs_type
const* fptr =
reinterpret_cast<rhs_type const*
>(&rhs[0]);
123 rhs_type* xptr =
reinterpret_cast<rhs_type*
>(&x[0]);
132 perm.inverse(X, xptr);
136 Solver solve(Ab, prm);
139 std::cout << solve << std::endl;
141 rhs_type
const* fptr =
reinterpret_cast<rhs_type const*
>(&rhs[0]);
142 rhs_type* xptr =
reinterpret_cast<rhs_type*
>(&x[0]);
151 std::copy(X.data(), X.data() + X.size(), xptr);
162 std::vector<ptrdiff_t>
const& ptr,
163 std::vector<ptrdiff_t>
const& col,
164 std::vector<double>
const& val,
165 std::vector<double>
const& rhs,
166 std::vector<double>& x,
169 std::cout <<
"Utilisation de la résolution scalaire ptr_size=" <<
sizeof(ptrdiff_t)
170 <<
" taille_type_ptr=" <<
sizeof(Backend::ptr_type)
171 <<
" taille_type_col=" <<
sizeof(Backend::col_type)
172 <<
" taille_type_valeur=" <<
sizeof(Backend::value_type)
174 auto& prof = Alina::Profiler::globalProfiler();
177#if defined(SOLVER_BACKEND_CUDA)
178 cusparseCreate(&bprm.cusparse_handle);
184 cudaGetDeviceProperties(&prop, dev);
185 std::cout << prop.name << std::endl
200 Solver solve(perm(std::tie(rows, ptr, col, val)), prm, bprm);
203 std::cout << solve << std::endl;
205 std::vector<double> tmp(rows);
207 perm.forward(rhs, tmp);
208 auto f_b = Backend::copy_vector(tmp, bprm);
210 perm.forward(x, tmp);
211 auto x_b = Backend::copy_vector(tmp, bprm);
214 info = solve(*f_b, *x_b);
217#if defined(SOLVER_BACKEND_CUDA)
218 thrust::copy(x_b->begin(), x_b->end(), tmp.begin());
220 std::copy(&(*x_b)[0], &(*x_b)[0] + rows, &tmp[0]);
223 perm.inverse(tmp, x);
227 Solver solve(std::tie(rows, ptr, col, val), prm, bprm);
230 std::cout << solve << std::endl;
232 auto f_b = Backend::copy_vector(rhs, bprm);
233 auto x_b = Backend::copy_vector(x, bprm);
236 info = solve(*f_b, *x_b);
239#if defined(SOLVER_BACKEND_CUDA)
240 thrust::copy(x_b->begin(), x_b->end(), x.begin());
242 std::copy(&(*x_b)[0], &(*x_b)[0] + rows, &x[0]);
249#define ARCCORE_ALINA_CALL_BLOCK_SOLVER(z, data, B) \
251 return block_solve<B>(prm, rows, ptr, col, val, rhs, x, reorder);
257 std::vector<ptrdiff_t>
const& ptr,
258 std::vector<ptrdiff_t>
const& col,
259 std::vector<double>
const& val,
260 std::vector<double>
const& rhs,
261 std::vector<double>& x,
265 switch (block_size) {
267 return scalar_solve(prm, rows, ptr, col, val, rhs, x, reorder);
268#if defined(SOLVER_BACKEND_BUILTIN)
269 BOOST_PP_SEQ_FOR_EACH(ARCCORE_ALINA_CALL_BLOCK_SOLVER, ~, ARCCORE_ALINA_BLOCK_SIZES)
272 precondition(
false,
"Taille de bloc non prise en charge");
278int main(
int argc,
char* argv[])
280 auto& prof = Alina::Profiler::globalProfiler();
281 namespace po = Arcane::ProgramOptions;
282 namespace io = Alina::IO;
289 desc.add_options()(
"help,h",
"Affiche cette aide.")(
"prm-file,P",
291 "Fichier de paramètres au format json. ")(
293 po::value<vector<string>>()->multitoken(),
294 "Paramètres spécifiés sous forme de paires nom=valeur. "
295 "Peut être fourni plusieurs fois. Exemples :\n"
296 " -p solver.tol=1e-3\n"
297 " -p precond.coarse_enough=300")(
"matrix,A",
299 "Matrice du système au format MatrixMarket. "
300 "Lorsqu'elle n'est pas spécifiée, elle résout un problème de Poisson dans un cube unitaire 3D. ")(
303 "Le vecteur du membre de droite (RHS) au format MatrixMarket. "
304 "Lorsqu'il est omis, un vecteur de uns est utilisé par défaut. "
305 "Doit être fourni uniquement avec une matrice de système. ")(
307 po::bool_switch()->default_value(
false),
308 "Utiliser un vecteur RHS nul. Implique --random-initial et solver.ns_search=true")(
310 po::bool_switch()->default_value(
false),
311 "Définir RHS = Ax où x = 1")(
314 "Les vecteurs proches de l'espace nul au format MatrixMarket. "
315 "Doit être une matrice dense de taille N*M, où N est le nombre de "
316 "variables inconnues et M est le nombre de vecteurs de l'espace nul. "
317 "Doit être fourni uniquement avec une matrice de système. ")(
320 "Matrice de coordonnées où le nombre de lignes correspond au nombre de nœuds de grille "
321 "et le nombre de colonnes correspond à la dimensionnalité du problème (2 ou 3). "
322 "Sera utilisée pour construire des vecteurs proches de l'espace nul comme modes de corps rigide. "
323 "Doit être fourni uniquement avec une matrice de système. ")(
325 po::bool_switch()->default_value(
false),
326 "Lorsqu'il est spécifié, traiter les fichiers d'entrée comme binaires au lieu de MatrixMarket. "
327 "Il est supposé que les fichiers ont été convertis au format binaire avec l'utilitaire mm2bin. ")(
329 po::bool_switch()->default_value(
false),
330 "Mettre à l'échelle la matrice de sorte que la diagonale soit unitaire. ")(
332 po::value<int>()->default_value(1),
333 "La taille du bloc de la matrice du système. "
334 "Lorsqu'elle est spécifiée, la matrice du système est supposée avoir une structure par blocs. "
335 "C'est généralement le cas pour les problèmes en élasticité, en mécanique des structures, "
336 "pour les systèmes couplés d'EDP (tels que les équations de Navier-Stokes), etc. ")(
338 po::value<int>()->default_value(32),
339 "La taille du problème de Poisson à résoudre lorsqu'aucune matrice de système n'est fournie. "
340 "Spécifié comme le nombre de nœuds de grille le long de chaque dimension d'un cube unitaire. "
341 "Le système résultant aura n*n*n inconnues. ")(
343 po::value<double>()->default_value(1.0),
344 "La valeur d'anisotropie pour la valeur de Poisson générée. "
345 "Utilisée pour déterminer la mise à l'échelle du problème le long des axes X, Y et Z : "
346 "hy = hx * a, hz = hy * a.")(
348 po::bool_switch()->default_value(
false),
349 "Lorsqu'il est spécifié, la hiérarchie AMG n'est pas construite. "
350 "Au lieu de cela, le problème est résolu à l'aide d'un lisseur à un niveau comme préconditionneur. ")(
352 po::bool_switch()->default_value(
false),
353 "Lorsqu'il est spécifié, la matrice sera réordonnée pour améliorer la localité du cache")(
355 po::value<double>()->default_value(0),
356 "Valeur à utiliser comme approximation initiale. ")(
358 po::bool_switch()->default_value(
false),
359 "Utiliser une approximation initiale aléatoire. ")(
362 "Fichier de sortie. Sera enregistré au format MatrixMarket. "
363 "Lorsqu'il est omis, la solution n'est pas enregistrée. ");
372 if (vm.count(
"help")) {
373 std::cout << desc << std::endl;
377 for (
int i = 0; i < argc; ++i) {
380 std::cout << argv[i];
382 std::cout << std::endl;
385 if (vm.count(
"prm-file")) {
386 prm.read_json(vm[
"prm-file"].as<string>());
389 if (vm.count(
"prm")) {
390 for (
const string& v : vm[
"prm"].as<vector<string>>()) {
396 vector<ptrdiff_t> ptr, col;
397 vector<double> val, rhs, null, x;
399 if (vm.count(
"matrix")) {
400 auto t = prof.scoped_tic(
"reading");
402 string Afile = vm[
"matrix"].as<
string>();
403 bool binary = vm[
"binary"].as<
bool>();
406 io::read_crs(Afile, rows, ptr, col, val);
410 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
411 precondition(rows == cols,
"Matrice de système non carrée");
414 if (vm.count(
"rhs")) {
415 string bfile = vm[
"rhs"].as<
string>();
420 io::read_dense(bfile, n, m, rhs);
423 std::tie(n, m) = io::mm_reader(bfile)(rhs);
426 precondition(n == rows && m == 1,
"Le vecteur RHS a une taille incorrecte");
428 else if (vm[
"f1"].as<bool>()) {
430 for (
size_t i = 0; i < rows; ++i) {
432 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j)
438 rhs.resize(rows, vm[
"f0"].as<bool>() ? 0.0 : 1.0);
441 if (vm.count(
"null")) {
442 string nfile = vm[
"null"].as<
string>();
447 io::read_dense(nfile, m, nv, null);
450 std::tie(m, nv) = io::mm_reader(nfile)(null);
453 precondition(m == rows,
"Les vecteurs proches de l'espace nul ont une taille incorrecte");
455 else if (vm.count(
"coords")) {
456 string cfile = vm[
"coords"].as<
string>();
457 std::vector<double> coo;
462 io::read_dense(cfile, m, ndim, coo);
465 std::tie(m, ndim) = io::mm_reader(cfile)(coo);
468 precondition(m * ndim == rows && (ndim == 2 || ndim == 3),
"Matrice de coordonnées de taille incorrecte");
470 nv = Alina::rigid_body_modes(ndim, coo, null);
474 prm.put(
"precond.coarsening.nullspace.cols", nv);
475 prm.put(
"precond.coarsening.nullspace.rows", rows);
476 prm.put(
"precond.coarsening.nullspace.B", &null[0]);
480 auto t = prof.scoped_tic(
"assembling");
481 rows = sample_problem(vm[
"size"].as<int>(), val, col, ptr, rhs, vm[
"anisotropy"].as<double>());
484 if (vm[
"scale"].as<bool>()) {
485 std::vector<double> dia(rows, 1.0);
487 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(rows); ++i) {
489 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j) {
491 d = 1 /
sqrt(val[j]);
498 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(rows); ++i) {
500 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j) {
501 val[j] *= dia[i] * dia[col[j]];
506 x.resize(rows, vm[
"initial"].as<double>());
507 if (vm[
"random-initial"].as<bool>() || vm[
"f0"].as<bool>()) {
509 std::uniform_real_distribution<double> rnd(-1, 1);
514 if (vm[
"f0"].as<bool>()) {
515 prm.put(
"solver.ns_search",
true);
518 int block_size = vm[
"block-size"].as<
int>();
519 std::cout <<
"BlockSize= " << block_size <<
"\n";
521 if (vm[
"single-level"].as<bool>())
522 prm.put(
"precond.class",
"relaxation");
525 bool do_hypre =
false;
527 do_hypre = v.value();
530#ifndef SOLVER_BACKEND_BUILTIN
534#ifdef SOLVER_BACKEND_BUILTIN
535 _doHypreSolver(rows, ptr, col, val, rhs, x, argc, argv);
539 solver_result = solve(prm, rows, ptr, col, val, rhs, x, block_size, vm[
"reorder"].as<bool>());
541 if (vm.count(
"output")) {
542 auto t = prof.scoped_tic(
"write");
543 Alina::IO::mm_write(vm[
"output"].as<string>(), &x[0], x.size());
546 std::cout <<
"Itérations: " << solver_result.nbIteration() << std::endl
547 <<
"Erreur: " << solver_result.residual() << std::endl
548 << prof << std::endl;
Convenience class that bundles together a preconditioner and an iterative solver.
Classe pour stocker les paramètres sous forme d'arbre hiérarchique clé/valeur.
NUMA-aware vector container.
Classe template pour convertir un type.
Constructeur d'analyseur d'arguments en ligne de commande fluide.
Décrit un ensemble d'options en ligne de commande.
Décrit les arguments positionnels (non-options).
Stocke les valeurs d'options analysées.
Vue d'un tableau d'éléments de type T.
Chaîne de caractères unicode.
apfloat sqrt(apfloat v)
Racine carrée de v.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Alina::detail::empty_params params
Runtime-configurable wrappers around iterative solvers.