31#if defined(SOLVER_BACKEND_CUDA)
40#include <boost/scope_exit.hpp>
41#include <boost/program_options.hpp>
43#if defined(SOLVER_BACKEND_CUDA)
44# include "arccore/alina/CudaBackend.h"
45# include "arccore/alina/relaxation_cusparse_ilu0.h"
48# ifndef SOLVER_BACKEND_BUILTIN
49# define SOLVER_BACKEND_BUILTIN
51#include "arccore/alina/BuiltinBackend.h"
55#include "arccore/trace/ITraceMng.h"
57#include "arccore/alina/DistributedDirectSolverRuntime.h"
58#include "arccore/alina/DistributedSolverRuntime.h"
59#include "arccore/alina/DistributedSubDomainDeflation.h"
60#include "arccore/alina/AMG.h"
61#include "arccore/alina/CoarseningRuntime.h"
62#include "arccore/alina/RelaxationRuntime.h"
63#include "arccore/alina/Profiler.h"
64#include "AlinaSamplesCommon.h"
67using namespace Arcane::Alina;
69#include "DomainPartition.h"
74 std::vector<double> x;
75 std::vector<double> y;
76 std::vector<double> z;
78 deflation_vectors(ptrdiff_t n,
size_t nv = 4)
85 size_t dim()
const {
return nv; }
87 double operator()(ptrdiff_t i,
int j)
const
105 const DomainPartition<3>& part;
106 const std::vector<ptrdiff_t>& dom;
108 renumbering(
const DomainPartition<3>& p,
109 const std::vector<ptrdiff_t>& d)
114 ptrdiff_t operator()(ptrdiff_t i, ptrdiff_t j, ptrdiff_t k)
const
116 boost::array<ptrdiff_t, 3> p = { { i, j, k } };
117 std::pair<int, ptrdiff_t> v = part.index(p);
118 return dom[v.first] + v.second;
124 auto& prof = Alina::Profiler::globalProfiler();
128 tm->
info() <<
"World size: " << world.size;
134 auto coarsening = Alina::eCoarserningType::smoothed_aggregation;
135 auto relaxation = Alina::eRelaxationType::spai0;
136 auto iterative_solver = Alina::eSolverType::bicgstabl;
137 auto direct_solver = Alina::eDistributedDirectSolverType::skyline_lu;
139 bool just_relax =
false;
140 bool symm_dirichlet =
true;
141 std::string parameter_file;
143 namespace po = boost::program_options;
144 po::options_description desc(
"Options");
146 desc.add_options()(
"help,h",
"show help")(
148 po::value<bool>(&symm_dirichlet)->default_value(symm_dirichlet),
149 "Use symmetric Dirichlet conditions in laplace2d")(
151 po::value<ptrdiff_t>(&n)->default_value(n),
154 po::value<Alina::eCoarserningType>(&coarsening)->default_value(coarsening),
155 "ruge_stuben, aggregation, smoothed_aggregation, smoothed_aggr_emin")(
157 po::value<Alina::eRelaxationType>(&relaxation)->default_value(relaxation),
158 "gauss_seidel, ilu0, iluk, ilut, damped_jacobi, spai0, spai1, chebyshev")(
160 po::value<Alina::eSolverType>(&iterative_solver)->default_value(iterative_solver),
161 "cg, bicgstab, bicgstabl, gmres")(
163 po::value<Alina::eDistributedDirectSolverType>(&direct_solver)->default_value(direct_solver),
165#ifdef ARCCORE_ALINA_HAVE_EIGEN
171 "Use constant deflation (linear deflation is used by default)")(
173 po::value<std::string>(¶meter_file),
174 "parameter file in json format")(
176 po::value<std::vector<std::string>>()->multitoken(),
177 "Parameters specified as name=value pairs. "
178 "May be provided multiple times. Examples:\n"
179 " -p solver.tol=1e-3\n"
180 " -p precond.coarse_enough=300")(
182 po::bool_switch(&just_relax),
183 "Do not create AMG hierarchy, use relaxation as preconditioner");
185 po::variables_map vm;
186 po::store(po::parse_command_line(argc, argv, desc), vm);
189 if (vm.count(
"help")) {
190 std::cout << desc << std::endl;
195 if (vm.count(
"params"))
196 prm.read_json(parameter_file);
198 if (vm.count(
"prm")) {
199 for (
const std::string& v : vm[
"prm"].as<std::vector<std::string>>()) {
204 prm.put(
"isolver.type", iterative_solver);
205 prm.put(
"dsolver.type", direct_solver);
207 boost::array<ptrdiff_t, 3> lo = { { 0, 0, 0 } };
208 boost::array<ptrdiff_t, 3> hi = { { n - 1, n - 1, n - 1 } };
210 prof.tic(
"partition");
211 DomainPartition<3> part(lo, hi, world.size);
212 ptrdiff_t chunk = part.size(world.rank);
214 std::vector<ptrdiff_t> domain(world.size + 1);
215 MPI_Allgather(&chunk, 1, Alina::mpi_datatype<ptrdiff_t>(),
216 &domain[1], 1, Alina::mpi_datatype<ptrdiff_t>(), world);
217 std::partial_sum(domain.begin(), domain.end(), domain.begin());
219 lo = part.domain(world.rank).min_corner();
220 hi = part.domain(world.rank).max_corner();
225 for (ptrdiff_t k = lo[2]; k <= hi[2]; ++k) {
226 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
227 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
228 boost::array<ptrdiff_t, 3> p = { { i, j, k } };
229 std::pair<int, ptrdiff_t> v = part.index(p);
231 def.x[v.second] = (i - (lo[0] + hi[0]) / 2);
232 def.y[v.second] = (j - (lo[1] + hi[1]) / 2);
233 def.z[v.second] = (k - (lo[2] + hi[2]) / 2);
237 prof.toc(
"partition");
239 prof.tic(
"assemble");
240 std::vector<ptrdiff_t> ptr;
241 std::vector<ptrdiff_t> col;
242 std::vector<double> val;
243 std::vector<double> rhs;
245 ptr.reserve(chunk + 1);
246 col.reserve(chunk * 7);
247 val.reserve(chunk * 7);
252 const double h2i = (n - 1) * (n - 1);
254 for (ptrdiff_t k = lo[2]; k <= hi[2]; ++k) {
255 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
256 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
258 if (!symm_dirichlet && (i == 0 || j == 0 || k == 0 || i + 1 == n || j + 1 == n || k + 1 == n)) {
259 col.push_back(renum(i, j, k));
265 col.push_back(renum(i, j, k - 1));
270 col.push_back(renum(i, j - 1, k));
275 col.push_back(renum(i - 1, j, k));
279 col.push_back(renum(i, j, k));
280 val.push_back(6 * h2i);
283 col.push_back(renum(i + 1, j, k));
288 col.push_back(renum(i, j + 1, k));
293 col.push_back(renum(i, j, k + 1));
299 ptr.push_back(col.size());
303 prof.toc(
"assemble");
307#if defined(SOLVER_BACKEND_VEXCL)
308 vex::Context ctx(vex::Filter::Env);
309 std::cout << ctx << std::endl;
311#elif defined(SOLVER_BACKEND_CUDA)
312 cusparseCreate(&bprm.cusparse_handle);
315 auto f = Backend::copy_vector(rhs, bprm);
316 auto x = Backend::create_vector(chunk, bprm);
318 Alina::backend::clear(*x);
323 std::function<double(ptrdiff_t,
unsigned)> def_vec = std::cref(def);
324 prm.put(
"num_def_vec", def.dim());
325 prm.put(
"def_vec", &def_vec);
328 prm.put(
"local.type", relaxation);
335 SDD solve(world, std::tie(chunk, ptr, col, val), prm, bprm);
339 std::tie(iters, resid) = solve(*f, *x);
343 prm.put(
"local.coarsening.type", coarsening);
344 prm.put(
"local.relax.type", relaxation);
351 SDD solve(world, std::tie(chunk, ptr, col, val), prm, bprm);
355 std::tie(iters, resid) = solve(*f, *x);
359 tm->
info() <<
"Iterations: " << iters <<
"\n"
360 <<
"Error: " << resid <<
"\n\n"
365int main(
int argc,
char* argv[])
367 return Arcane::Alina::SampleMainContext::execMain(main2, argc, argv);
Runtime wrapper for distributed direct solvers.
Distributed solver based on subdomain deflation.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Alina::detail::empty_params params
Pointwise constant deflation vectors.
Convenience wrapper around MPI_Comm.