31#if defined(SOLVER_BACKEND_CUDA)
40#include <boost/scope_exit.hpp>
42#if defined(SOLVER_BACKEND_CUDA)
43# include "arccore/alina/CudaBackend.h"
44# include "arccore/alina/relaxation_cusparse_ilu0.h"
47# ifndef SOLVER_BACKEND_BUILTIN
48# define SOLVER_BACKEND_BUILTIN
50#include "arccore/alina/BuiltinBackend.h"
54#include "arccore/trace/ITraceMng.h"
56#include "arccore/alina/DistributedDirectSolverRuntime.h"
57#include "arccore/alina/DistributedSolverRuntime.h"
58#include "arccore/alina/DistributedSubDomainDeflation.h"
59#include "arccore/alina/AMG.h"
60#include "arccore/alina/CoarseningRuntime.h"
61#include "arccore/alina/RelaxationRuntime.h"
62#include "arccore/alina/Profiler.h"
64#include "arccore/common/internal/ProgramOptions.h"
66#include "AlinaSamplesCommon.h"
69using namespace Arcane::Alina;
71#include "DomainPartition.h"
76 std::vector<double> x;
77 std::vector<double> y;
78 std::vector<double> z;
80 deflation_vectors(ptrdiff_t n,
size_t nv = 4)
87 size_t dim()
const {
return nv; }
89 double operator()(ptrdiff_t i,
int j)
const
107 const DomainPartition<3>& part;
108 const std::vector<ptrdiff_t>& dom;
110 renumbering(
const DomainPartition<3>& p,
111 const std::vector<ptrdiff_t>& d)
116 ptrdiff_t operator()(ptrdiff_t i, ptrdiff_t j, ptrdiff_t k)
const
118 boost::array<ptrdiff_t, 3> p = { { i, j, k } };
119 std::pair<int, ptrdiff_t> v = part.index(p);
120 return dom[v.first] + v.second;
126 auto& prof = Alina::Profiler::globalProfiler();
130 tm->
info() <<
"World size: " << world.size;
136 auto coarsening = Alina::eCoarserningType::smoothed_aggregation;
137 auto relaxation = Alina::eRelaxationType::spai0;
138 auto iterative_solver = Alina::eSolverType::bicgstabl;
139 auto direct_solver = Alina::eDistributedDirectSolverType::skyline_lu;
141 bool just_relax =
false;
142 bool symm_dirichlet =
true;
143 std::string parameter_file;
145 namespace po = Arcane::ProgramOptions;
148 desc.add_options()(
"help,h",
"afficher l'aide")(
150 po::value<bool>(&symm_dirichlet)->default_value(symm_dirichlet),
151 "Utiliser des conditions de Dirichlet symétriques dans laplace2d")(
153 po::value<ptrdiff_t>(&n)->default_value(n),
154 "taille du domaine")(
156 po::value<Alina::eCoarserningType>(&coarsening)->default_value(coarsening),
157 "ruge_stuben, aggregation, smoothed_aggregation, smoothed_aggr_emin")(
159 po::value<Alina::eRelaxationType>(&relaxation)->default_value(relaxation),
160 "gauss_seidel, ilu0, iluk, ilut, damped_jacobi, spai0, spai1, chebyshev")(
162 po::value<Alina::eSolverType>(&iterative_solver)->default_value(iterative_solver),
163 "cg, bicgstab, bicgstabl, gmres")(
165 po::value<Alina::eDistributedDirectSolverType>(&direct_solver)->default_value(direct_solver),
167#ifdef ARCCORE_ALINA_HAVE_EIGEN
173 "Utiliser la déflation constante (la déflation linéaire est utilisée par défaut)")(
175 po::value<std::string>(¶meter_file),
176 "fichier de paramètres au format json")(
178 po::value<std::vector<std::string>>()->multitoken(),
179 "Paramètres spécifiés sous forme de paires nom=valeur. "
180 "Peut être fourni plusieurs fois. Exemples:\n"
181 " -p solver.tol=1e-3\n"
182 " -p precond.coarse_enough=300")(
184 po::bool_switch(&just_relax),
185 "Ne pas créer la hiérarchie AMG, utiliser la relaxation comme préconditionneur");
188 po::store(po::parse_command_line(argc, argv, desc), vm);
191 if (vm.count(
"help")) {
192 std::cout << desc << std::endl;
197 if (vm.count(
"params"))
198 prm.read_json(parameter_file);
200 if (vm.count(
"prm")) {
201 for (
const std::string& v : vm[
"prm"].as<std::vector<std::string>>()) {
206 prm.put(
"isolver.type", iterative_solver);
207 prm.put(
"dsolver.type", direct_solver);
209 boost::array<ptrdiff_t, 3> lo = { { 0, 0, 0 } };
210 boost::array<ptrdiff_t, 3> hi = { { n - 1, n - 1, n - 1 } };
212 prof.tic(
"partition");
213 DomainPartition<3> part(lo, hi, world.size);
214 ptrdiff_t chunk = part.size(world.rank);
216 std::vector<ptrdiff_t> domain(world.size + 1);
219 mpAllGather(world.m_message_passing_mng.get(), send_buf, receive_buf);
220 std::partial_sum(domain.begin(), domain.end(), domain.begin());
222 lo = part.domain(world.rank).min_corner();
223 hi = part.domain(world.rank).max_corner();
228 for (ptrdiff_t k = lo[2]; k <= hi[2]; ++k) {
229 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
230 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
231 boost::array<ptrdiff_t, 3> p = { { i, j, k } };
232 std::pair<int, ptrdiff_t> v = part.index(p);
234 def.x[v.second] = (i - (lo[0] + hi[0]) / 2);
235 def.y[v.second] = (j - (lo[1] + hi[1]) / 2);
236 def.z[v.second] = (k - (lo[2] + hi[2]) / 2);
240 prof.toc(
"partition");
242 prof.tic(
"assemble");
243 std::vector<ptrdiff_t> ptr;
244 std::vector<ptrdiff_t> col;
245 std::vector<double> val;
246 std::vector<double> rhs;
248 ptr.reserve(chunk + 1);
249 col.reserve(chunk * 7);
250 val.reserve(chunk * 7);
255 const double h2i = (n - 1) * (n - 1);
257 for (ptrdiff_t k = lo[2]; k <= hi[2]; ++k) {
258 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
259 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
261 if (!symm_dirichlet && (i == 0 || j == 0 || k == 0 || i + 1 == n || j + 1 == n || k + 1 == n)) {
262 col.push_back(renum(i, j, k));
268 col.push_back(renum(i, j, k - 1));
273 col.push_back(renum(i, j - 1, k));
278 col.push_back(renum(i - 1, j, k));
282 col.push_back(renum(i, j, k));
283 val.push_back(6 * h2i);
286 col.push_back(renum(i + 1, j, k));
291 col.push_back(renum(i, j + 1, k));
296 col.push_back(renum(i, j, k + 1));
302 ptr.push_back(col.size());
306 prof.toc(
"assemble");
310#if defined(SOLVER_BACKEND_VEXCL)
311 vex::Context ctx(vex::Filter::Env);
312 std::cout << ctx << std::endl;
314#elif defined(SOLVER_BACKEND_CUDA)
315 cusparseCreate(&bprm.cusparse_handle);
318 auto f = Backend::copy_vector(rhs, bprm);
319 auto x = Backend::create_vector(chunk, bprm);
321 Alina::backend::clear(*x);
326 std::function<double(ptrdiff_t,
unsigned)> def_vec = std::cref(def);
327 prm.put(
"num_def_vec", def.dim());
328 prm.put(
"def_vec", &def_vec);
331 prm.put(
"local.type", relaxation);
338 SDD solve(world, std::tie(chunk, ptr, col, val), prm, bprm);
342 std::tie(iters, resid) = solve(*f, *x);
346 prm.put(
"local.coarsening.type", coarsening);
347 prm.put(
"local.relax.type", relaxation);
354 SDD solve(world, std::tie(chunk, ptr, col, val), prm, bprm);
358 std::tie(iters, resid) = solve(*f, *x);
362 tm->
info() <<
"Itérations: " << iters <<
"\n"
363 <<
"Erreur: " << resid <<
"\n\n"
368int main(
int argc,
char* argv[])
370 return Arcane::Alina::SampleMainContext::execMain(main2, argc, argv);
Runtime wrapper for distributed direct solvers.
Solveur distribué basé sur la déflation de sous-domaines.
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.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
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 --
Alina::detail::empty_params params
Vecteurs de déflation constants ponctuels.
Wrapper de commodité autour de MPI_Comm.