25#include <boost/range/iterator_range.hpp>
26#include <boost/scope_exit.hpp>
28#include "arccore/alina/BuiltinBackend.h"
29#include "arccore/alina/PreconditionerRuntime.h"
30#include "arccore/alina/Adapters.h"
31#include "arccore/alina/DistributedPreconditionedSolver.h"
32#include "arccore/alina/DistributedSolverRuntime.h"
33#include "arccore/alina/DistributedPreconditioner.h"
34#include "arccore/alina/Profiler.h"
35#include "arccore/alina/AlinaUtils.h"
38#include "arccore/alina/DistributedSolver.h"
41#include "arccore/alina/DistributedRelaxationRuntime.h"
43#include "arccore/common/internal/ProgramOptions.h"
45#include "DomainPartition.h"
48using namespace Arcane::Alina;
50using Alina::precondition;
55 const DomainPartition<2>& part;
56 const std::vector<ptrdiff_t>& dom;
58 renumbering(
const DomainPartition<2>& p,
59 const std::vector<ptrdiff_t>& d)
64 ptrdiff_t operator()(ptrdiff_t i, ptrdiff_t j)
const
66 boost::array<ptrdiff_t, 2> p = { { i, j } };
67 std::pair<int, ptrdiff_t> v = part.index(p);
68 return dom[v.first] + v.second;
74template <
template <
class>
class Precond,
class Matrix>
80 auto& prof = Alina::Profiler::globalProfiler();
86 const size_t n = Alina::backend::nbRow(A);
88 std::vector<double> rhs(n, 1), x(n, 0);
91 Solver solve(comm, A, prm);
95 auto t2 = prof.scoped_tic(
"solve");
102int main(
int argc,
char* argv[])
104 auto& prof = Alina::Profiler::globalProfiler();
105 namespace po = Arcane::ProgramOptions;
112 desc.add_options()(
"help,h",
"Show this help.")(
"prm-file,P",
114 "Fichier de paramètres au format json. ")(
116 po::value<vector<string>>()->multitoken(),
117 "Paramètres spécifiés sous forme de paires nom=valeur. "
118 "Peut être fourni plusieurs fois. Exemples:\n"
119 " -p solver.tol=1e-3\n"
120 " -p precond.coarse_enough=300")(
122 po::value<int>()->default_value(1024),
123 "La taille du problème de Poisson à résoudre. "
124 "Spécifié comme le nombre de nœuds de grille le long de chaque dimension d'un carré unité. "
125 "Le système résultant aura n*n inconnues. ")(
127 po::bool_switch()->default_value(
false),
128 "Lorsqu'il est spécifié, la hiérarchie AMG n'est pas construite. "
129 "Au lieu de cela, le problème est résolu à l'aide d'un lisseur à niveau unique comme préconditionneur. ")(
131 po::value<double>()->default_value(0),
132 "Valeur à utiliser comme approximation initiale. ");
135 po::store(po::parse_command_line(argc, argv, desc), vm);
138 if (vm.count(
"help")) {
139 std::cout << desc << std::endl;
144 if (vm.count(
"prm-file")) {
145 prm.read_json(vm[
"prm-file"].as<string>());
148 if (vm.count(
"prm")) {
154 MPI_Init(&argc, &argv);
155 BOOST_SCOPE_EXIT(
void)
164 std::cout <<
"World size: " << world.size << std::endl;
166 const ptrdiff_t n = vm[
"size"].as<
int>();
167 const double h2i = (n - 1) * (n - 1);
169 boost::array<ptrdiff_t, 2> lo = { { 0, 0 } };
170 boost::array<ptrdiff_t, 2> hi = { { n - 1, n - 1 } };
172 prof.tic(
"partition");
173 DomainPartition<2> part(lo, hi, world.size);
174 ptrdiff_t chunk = part.size(world.rank);
176 std::vector<ptrdiff_t> domain(world.size + 1);
179 mpAllGather(world.m_message_passing_mng.get(),send_buf,receive_buf);
180 std::partial_sum(domain.begin(), domain.end(), domain.begin());
182 lo = part.domain(world.rank).min_corner();
183 hi = part.domain(world.rank).max_corner();
184 prof.toc(
"partition");
188 prof.tic(
"assemble");
189 std::vector<ptrdiff_t> ptr;
190 std::vector<ptrdiff_t> col;
191 std::vector<double> val;
192 std::vector<double> rhs;
194 ptr.reserve(chunk + 1);
195 col.reserve(chunk * 5);
196 val.reserve(chunk * 5);
200 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
201 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
203 col.push_back(renum(i, j - 1));
208 col.push_back(renum(i - 1, j));
212 col.push_back(renum(i, j));
213 val.push_back(4 * h2i);
216 col.push_back(renum(i + 1, j));
221 col.push_back(renum(i, j + 1));
225 ptr.push_back(col.size());
228 prof.toc(
"assemble");
230 bool single_level = vm[
"single-level"].as<
bool>();
233 prm.put(
"precond.class",
"relaxation");
235 Alina::SolverResult r = solve<Alina::PreconditionerRuntime>(world, prm, std::tie(chunk, ptr, col, val));
237 if (world.rank == 0) {
238 std::cout <<
"Itérations: " << r.nbIteration() << std::endl
239 <<
"Erreur: " << r.residual() << std::endl
241 << prof << std::endl;
Iterative solver wrapper for distributed linear systems.
Classe pour stocker les paramètres sous forme d'arbre hiérarchique clé/valeur.
Vue modifiable d'un tableau d'un type T.
Vue constante d'un tableau de type T.
Matrix class, to be used by user.
Décrit un ensemble d'options en ligne de commande.
Stocke les valeurs d'options analysées.
void mpAllGather(IMessagePassingMng *pm, const ISerializer *send_serializer, ISerializer *receive_serialize)
Message allGather() pour une sérialisation.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Wrapper de commodité autour de MPI_Comm.