Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
SolverComplex.cc
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#include <iostream>
20#include <string>
21
22#include <boost/program_options.hpp>
23#include <boost/range/iterator_range.hpp>
24#include <boost/preprocessor/seq/for_each.hpp>
25
26#include "arccore/alina/BuiltinBackend.h"
27#include "arccore/alina/ValueTypeComplex.h"
28#include "arccore/alina/StaticMatrix.h"
29#include "arccore/alina/Adapters.h"
30
31#include "arccore/alina/SolverRuntime.h"
32#include "arccore/alina/CoarseningRuntime.h"
33#include "arccore/alina/RelaxationRuntime.h"
34#include "arccore/alina/PreconditionerRuntime.h"
35#include "arccore/alina/PreconditionedSolver.h"
36#include "arccore/alina/AMG.h"
37#include "arccore/alina/IO.h"
38
39#include "arccore/alina/Profiler.h"
40
41#include "SampleProblemCommon.h"
42
43#ifndef ARCCORE_ALINA_BLOCK_SIZES
44#define ARCCORE_ALINA_BLOCK_SIZES (2)(3)(4)
45#endif
46using namespace Arcane;
47using namespace Arcane::Alina;
48
49using Alina::precondition;
50
51//---------------------------------------------------------------------------
52template <class Precond, class Matrix>
54solve(const Matrix& A,
55 const Alina::PropertyTree& prm,
56 std::vector<std::complex<double>> const& f,
57 std::vector<std::complex<double>>& x)
58{
59 auto& prof = Alina::Profiler::globalProfiler();
60
61 typedef typename Precond::backend_type Backend;
62
63 typedef typename Alina::math::rhs_of<typename Backend::value_type>::type rhs_type;
64 size_t n = Alina::backend::nbRow(A);
65
66 rhs_type const* fptr = reinterpret_cast<rhs_type const*>(&f[0]);
67 rhs_type* xptr = reinterpret_cast<rhs_type*>(&x[0]);
68 SmallSpan<const rhs_type> frng(fptr, n);
69 SmallSpan<rhs_type> xrng(xptr, n);
70
72
73 prof.tic("setup");
74 Solver solve(A, prm);
75 prof.toc("setup");
76
77 std::cout << solve << std::endl;
78
79 {
80 auto t = prof.scoped_tic("solve");
81 return solve(frng, xrng);
82 }
83}
84
85//---------------------------------------------------------------------------
86int main(int argc, char* argv[])
87{
88 auto& prof = Alina::Profiler::globalProfiler();
89 namespace po = boost::program_options;
90 namespace io = Alina::IO;
91
92 using std::string;
93 using std::vector;
94
95 po::options_description desc("Options");
96
97 desc.add_options()("help,h", "Show this help.")("prm-file,P",
98 po::value<string>(),
99 "Parameter file in json format. ")(
100 "prm,p",
101 po::value<vector<string>>()->multitoken(),
102 "Parameters specified as name=value pairs. "
103 "May be provided multiple times. Examples:\n"
104 " -p solver.tol=1e-3\n"
105 " -p precond.coarse_enough=300")("matrix,A",
106 po::value<string>(),
107 "System matrix in the MatrixMarket format. "
108 "When not specified, solves a Poisson problem in 3D unit cube. ")(
109 "rhs,f",
110 po::value<string>(),
111 "The RHS vector in the MatrixMarket format. "
112 "When omitted, a vector of ones is used by default. "
113 "Should only be provided together with a system matrix. ")(
114 "null,N",
115 po::value<string>(),
116 "The near null-space vectors in the MatrixMarket format. "
117 "Should be a dense matrix of size N*M, where N is the number of "
118 "unknowns, and M is the number of null-space vectors. "
119 "Should only be provided together with a system matrix. ")(
120 "binary,B",
121 po::bool_switch()->default_value(false),
122 "When specified, treat input files as binary instead of as MatrixMarket. "
123 "It is assumed the files were converted to binary format with mm2bin utility. ")(
124 "block-size,b",
125 po::value<int>()->default_value(1),
126 "The block size of the system matrix. "
127 "When specified, the system matrix is assumed to have block-wise structure. "
128 "This usually is the case for problems in elasticity, structural mechanics, "
129 "for coupled systems of PDE (such as Navier-Stokes equations), etc. ")(
130 "size,n",
131 po::value<int>()->default_value(32),
132 "The size of the Poisson problem to solve when no system matrix is given. "
133 "Specified as number of grid nodes along each dimension of a unit cube. "
134 "The resulting system will have n*n*n unknowns. ")(
135 "single-level,1",
136 po::bool_switch()->default_value(false),
137 "When specified, the AMG hierarchy is not constructed. "
138 "Instead, the problem is solved using a single-level smoother as preconditioner. ")(
139 "initial,x",
140 po::value<double>()->default_value(0),
141 "Value to use as initial approximation. ")(
142 "output,o",
143 po::value<string>(),
144 "Output file. Will be saved in the MatrixMarket format. "
145 "When omitted, the solution is not saved. ");
146
147 po::variables_map vm;
148 po::store(po::parse_command_line(argc, argv, desc), vm);
149 po::notify(vm);
150
151 if (vm.count("help")) {
152 std::cout << desc << std::endl;
153 return 0;
154 }
155
157 if (vm.count("prm-file")) {
158 prm.read_json(vm["prm-file"].as<string>());
159 }
160
161 if (vm.count("prm")) {
162 for (const string& v : vm["prm"].as<vector<string>>()) {
163 prm.putKeyValue(v);
164 }
165 }
166
167 size_t rows;
168 vector<ptrdiff_t> ptr, col;
169 vector<std::complex<double>> val, rhs, null, x;
170
171 if (vm.count("matrix")) {
172 auto t = prof.scoped_tic("reading");
173
174 string Afile = vm["matrix"].as<string>();
175 bool binary = vm["binary"].as<bool>();
176
177 if (binary) {
178 io::read_crs(Afile, rows, ptr, col, val);
179 }
180 else {
181 size_t cols;
182 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
183 precondition(rows == cols, "Non-square system matrix");
184 }
185
186 if (vm.count("rhs")) {
187 string bfile = vm["rhs"].as<string>();
188
189 size_t n, m;
190 if (binary) {
191 io::read_dense(bfile, n, m, rhs);
192 }
193 else {
194 std::tie(n, m) = io::mm_reader(bfile)(rhs);
195 }
196
197 precondition(n == rows && m == 1, "The RHS vector has wrong size");
198 }
199 else {
200 rhs.resize(rows, 1.0);
201 }
202
203 if (vm.count("null")) {
204 string nfile = vm["null"].as<string>();
205
206 size_t m, nv;
207
208 if (binary) {
209 io::read_dense(nfile, m, nv, null);
210 }
211 else {
212 std::tie(m, nv) = io::mm_reader(nfile)(null);
213 }
214
215 precondition(m == rows, "Near null-space vectors have wrong size");
216
217 prm.put("precond.coarsening.nullspace.cols", nv);
218 prm.put("precond.coarsening.nullspace.rows", rows);
219 prm.put("precond.coarsening.nullspace.B", &null[0]);
220 }
221 }
222 else {
223 auto t = prof.scoped_tic("assembling");
224 rows = sample_problem(vm["size"].as<int>(), val, col, ptr, rhs);
225 }
226
227 x.resize(rows, vm["initial"].as<double>());
228
229 if (vm["single-level"].as<bool>())
230 prm.put("precond.class", "relaxation");
231
232 int block_size = vm["block-size"].as<int>();
234#define CALL_BLOCK_SOLVER(z, data, B) \
235 case B: { \
236 typedef StaticMatrix<std::complex<double>, B, B> value_type; \
237 typedef ::Arcane::Alina::BuiltinBackend<value_type> Backend; \
238 r = solve<::Arcane::Alina::PreconditionerRuntime<Backend>>( \
239 ::Arcane::Alina::adapter::block_matrix<value_type>( \
240 std::tie(rows, ptr, col, val)), \
241 prm, rhs, x); \
242 } break;
243
244 switch (block_size) {
245 case 1: {
247 r = solve<PreconditionerRuntime<Backend>>(
248 std::tie(rows, ptr, col, val), prm, rhs, x);
249 } break;
250 BOOST_PP_SEQ_FOR_EACH(CALL_BLOCK_SOLVER, ~, ARCCORE_ALINA_BLOCK_SIZES)
251 }
252
253#undef CALL_BLOCK_SOLVER
254
255 if (vm.count("output")) {
256 auto t = prof.scoped_tic("write");
257 Alina::IO::mm_write(vm["output"].as<string>(), &x[0], x.size());
258 }
259
260 std::cout << "Iterations: " << r.nbIteration() << std::endl
261 << "Error: " << r.residual() << std::endl
262 << prof << std::endl;
263}
Convenience class that bundles together a preconditioner and an iterative solver.
Result of a solving.
Definition AlinaUtils.h:52
Matrix class, to be used by user.
Vue d'un tableau d'éléments de type T.
Definition Span.h:801
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-