Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
SchurPressureCorrection.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/preprocessor/seq/for_each.hpp>
24
25#if defined(SOLVER_BACKEND_CUDA)
26# include "arccore/alina/CudaBackend.h"
27# include "arccore/alina/relaxation_cusparse_ilu0.h"
28 template <class T> using Backend = Arcane::Alina::backend::cuda<T>;
29#else
30# ifndef SOLVER_BACKEND_BUILTIN
31# define SOLVER_BACKEND_BUILTIN
32# endif
33#include "arccore/alina/BuiltinBackend.h"
34template <class T> using Backend = Arcane::Alina::BuiltinBackend<T>;
35#endif
36
37#include "arccore/alina/PreconditionedSolver.h"
38#include "arccore/alina/make_block_solver.h"
39#include "arccore/alina/StaticMatrix.h"
40#include "arccore/alina/Adapters.h"
41#include "arccore/alina/AMG.h"
42#include "arccore/alina/SolverRuntime.h"
43#include "arccore/alina/CoarseningRuntime.h"
44#include "arccore/alina/RelaxationRuntime.h"
45#include "arccore/alina/SchurPressureCorrectionPreconditioner.h"
46#include "arccore/alina/PreconditionerRuntime.h"
47#include "arccore/alina/Adapters.h"
48
49#include "arccore/alina/IO.h"
50#include "arccore/alina/Profiler.h"
51
52 using namespace Arcane;
53using namespace Arcane::Alina;
54
55#ifndef ARCCORE_ALINA_BLOCK_SIZES
56# define ARCCORE_ALINA_BLOCK_SIZES (3)(4)
57#endif
58
59using Alina::precondition;
60
61//---------------------------------------------------------------------------
62
63template <class USolver, class PSolver, class Matrix>
64void solve_schur(const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
65{
66 auto& prof = Alina::Profiler::globalProfiler();
68
69#if defined(SOLVER_BACKEND_CUDA)
70 cusparseCreate(&bprm.cusparse_handle);
71 {
72 int dev;
73 cudaGetDevice(&dev);
74
75 cudaDeviceProp prop;
76 cudaGetDeviceProperties(&prop, dev);
77 std::cout << prop.name << std::endl
78 << std::endl;
79 }
80#endif
81
82 auto t1 = prof.scoped_tic("schur_complement");
83
84 prof.tic("setup");
87 solve(K, prm, bprm);
88 prof.toc("setup");
89
90 std::cout << solve << std::endl;
91
92 auto f = Backend<double>::copy_vector(rhs, bprm);
93 auto x = Backend<double>::create_vector(rhs.size(), bprm);
94 Alina::backend::clear(*x);
95
96 prof.tic("solve");
97 Alina::SolverResult r = solve(*f, *x);
98 prof.toc("solve");
99
100 std::cout << "Iterations: " << r.nbIteration() << std::endl
101 << "Error: " << r.residual() << std::endl;
102}
103
104#define ARCCORE_ALINA_BLOCK_PSOLVER(z, data, B) \
105 case B: { \
106 typedef Backend<StaticMatrix<double, B, B>> BBackend; \
107 typedef ::Arcane::Alina::make_block_solver< \
108 PreconditionerRuntime<BBackend>, SolverRuntime<BBackend>> PSolver; \
109 solve_schur<USolver, PSolver>(K, rhs, prm); \
110 } break;
111
112//---------------------------------------------------------------------------
113template <class USolver, class Matrix> void
114solve_schur(int pb, const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
115{
116 switch (pb) {
117 case 1: {
119 solve_schur<USolver, PSolver>(K, rhs, prm);
120 } break;
121#if defined(SOLVER_BACKEND_BUILTIN)
122 BOOST_PP_SEQ_FOR_EACH(ARCCORE_ALINA_BLOCK_PSOLVER, ~, ARCCORE_ALINA_BLOCK_SIZES)
123#endif
124 default:
125 precondition(false, "Unsupported block size for pressure");
126 }
127}
128
129#define ARCCORE_ALINA_BLOCK_USOLVER(z, data, B) \
130 case B: { \
131 typedef Backend<StaticMatrix<double, B, B>> BBackend; \
132 typedef make_block_solver< PreconditionerRuntime<BBackend>, SolverRuntime<BBackend>> USolver; \
133 solve_schur<USolver>(pb, K, rhs, prm); \
134 } break;
135
136//---------------------------------------------------------------------------
137template <class Matrix>
138void solve_schur(int ub, int pb, const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
139{
140 switch (ub) {
141 case 1: {
143 solve_schur<USolver>(pb, K, rhs, prm);
144 } break;
145#if defined(SOLVER_BACKEND_BUILTIN)
146 BOOST_PP_SEQ_FOR_EACH(ARCCORE_ALINA_BLOCK_USOLVER, ~, ARCCORE_ALINA_BLOCK_SIZES)
147#endif
148 default:
149 precondition(false, "Unsupported block size for flow");
150 }
151}
152
153//---------------------------------------------------------------------------
154int main(int argc, char* argv[])
155{
156 auto& prof = Alina::Profiler::globalProfiler();
157 using std::string;
158 using std::vector;
159
160 namespace po = boost::program_options;
161 namespace io = Alina::IO;
162
163 po::options_description desc("Options");
164
165 desc.add_options()("help,h", "show help")(
166 "binary,B",
167 po::bool_switch()->default_value(false),
168 "When specified, treat input files as binary instead of as MatrixMarket. "
169 "It is assumed the files were converted to binary format with mm2bin utility. ")(
170 "matrix,A",
171 po::value<string>()->required(),
172 "The system matrix in MatrixMarket format")(
173 "rhs,f",
174 po::value<string>(),
175 "The right-hand side in MatrixMarket format")(
176 "pmask,m",
177 po::value<string>(),
178 "The pressure mask in MatrixMarket format. Or, if the parameter has "
179 "the form '%n:m', then each (n+i*m)-th variable is treated as pressure.")(
180 "ub",
181 po::value<int>()->default_value(1),
182 "Block-size of the 'flow'/'non-pressure' part of the matrix")(
183 "pb",
184 po::value<int>()->default_value(1),
185 "Block-size of the 'pressure' part of the matrix")(
186 "params,P",
187 po::value<string>(),
188 "parameter file in json format")(
189 "prm,p",
190 po::value<vector<string>>()->multitoken(),
191 "Parameters specified as name=value pairs. "
192 "May be provided multiple times. Examples:\n"
193 " -p solver.tol=1e-3\n"
194 " -p precond.coarse_enough=300");
195
196 po::variables_map vm;
197 po::store(po::parse_command_line(argc, argv, desc), vm);
198
199 if (vm.count("help")) {
200 std::cout << desc << std::endl;
201 return 0;
202 }
203
204 po::notify(vm);
205
207 if (vm.count("params"))
208 prm.read_json(vm["params"].as<string>());
209
210 if (vm.count("prm")) {
211 for (const string& v : vm["prm"].as<vector<string>>()) {
212 prm.putKeyValue(v);
213 }
214 }
215
216 size_t rows;
217 vector<ptrdiff_t> ptr, col;
218 vector<double> val, rhs;
219 std::vector<char> pm;
220
221 {
222 auto t = prof.scoped_tic("reading");
223
224 string Afile = vm["matrix"].as<string>();
225 bool binary = vm["binary"].as<bool>();
226
227 if (binary) {
228 io::read_crs(Afile, rows, ptr, col, val);
229 }
230 else {
231 size_t cols;
232 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
233 precondition(rows == cols, "Non-square system matrix");
234 }
235
236 if (vm.count("rhs")) {
237 string bfile = vm["rhs"].as<string>();
238
239 size_t n, m;
240
241 if (binary) {
242 io::read_dense(bfile, n, m, rhs);
243 }
244 else {
245 std::tie(n, m) = io::mm_reader(bfile)(rhs);
246 }
247
248 precondition(n == rows && m == 1, "The RHS vector has wrong size");
249 }
250 else {
251 rhs.resize(rows, 1.0);
252 }
253
254 if (vm.count("pmask")) {
255 std::string pmask = vm["pmask"].as<string>();
256 prm.put("precond.pmask_size", rows);
257
258 switch (pmask[0]) {
259 case '%':
260 case '<':
261 case '>':
262 prm.put("precond.pmask_pattern", pmask);
263 break;
264 default: {
265 size_t n, m;
266 std::tie(n, m) = Alina::IO::mm_reader(pmask)(pm);
267 precondition(n == rows && m == 1, "Mask file has wrong size");
268 prm.put("precond.pmask", static_cast<void*>(&pm[0]));
269 }
270 }
271 }
272 }
273
274 solve_schur(vm["ub"].as<int>(), vm["pb"].as<int>(),
275 std::tie(rows, ptr, col, val), rhs, prm);
276
277 std::cout << prof << std::endl;
278}
Matrix market reader.
Definition IO.h:52
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.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Alina::detail::empty_params params
Runtime-configurable wrappers around iterative solvers.