deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
trilinos_precondition_ml.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2015 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
15
16#ifdef DEAL_II_WITH_TRILINOS
17
20# include <deal.II/lac/vector.h>
21
23
24# include <Epetra_MultiVector.h>
25# include <Ifpack.h>
26# include <Ifpack_Chebyshev.h>
27# include <Teuchos_ParameterList.hpp>
28# include <Teuchos_RCP.hpp>
29# include <ml_MultiLevelPreconditioner.h>
30# include <ml_include.h>
31
33
34
35#endif // DEAL_II_WITH_TRILINOS
36
38
39#ifdef DEAL_II_WITH_TRILINOS
40
41namespace TrilinosWrappers
42{
43 /* -------------------------- PreconditionAMG -------------------------- */
44
46 const bool elliptic,
47 const bool higher_order_elements,
48 const unsigned int n_cycles,
49 const bool w_cycle,
50 const double aggregation_threshold,
51 const std::vector<std::vector<bool>> &constant_modes,
52 const unsigned int smoother_sweeps,
53 const unsigned int smoother_overlap,
54 const bool output_details,
55 const char *smoother_type,
56 const char *coarse_type)
57 : elliptic(elliptic)
58 , higher_order_elements(higher_order_elements)
59 , n_cycles(n_cycles)
60 , w_cycle(w_cycle)
61 , aggregation_threshold(aggregation_threshold)
62 , constant_modes(constant_modes)
63 , smoother_sweeps(smoother_sweeps)
64 , smoother_overlap(smoother_overlap)
65 , output_details(output_details)
66 , smoother_type(smoother_type)
67 , coarse_type(coarse_type)
68 {}
69
70
71
72 void
74 Teuchos::ParameterList &parameter_list,
75 std::unique_ptr<Epetra_MultiVector> &distributed_constant_modes,
76 const Epetra_RowMatrix &matrix) const
77 {
78 if (elliptic == true)
79 {
80 ML_Epetra::SetDefaults("SA", parameter_list);
81
82 // uncoupled mode can give a lot of warnings or even fail when there
83 // are too many entries per row and aggregation gets complicated, but
84 // MIS does not work if too few elements are located on one
85 // processor. work around these warnings by choosing the different
86 // strategies in different situations: for low order, always use the
87 // standard choice uncoupled. if higher order, right now we also just
88 // use Uncoupled, but we should be aware that maybe MIS might be
89 // needed
90 if (higher_order_elements)
91 parameter_list.set("aggregation: type", "Uncoupled");
92 }
93 else
94 {
95 ML_Epetra::SetDefaults("NSSA", parameter_list);
96 parameter_list.set("aggregation: type", "Uncoupled");
97 parameter_list.set("aggregation: block scaling", true);
98 }
99
100 parameter_list.set("smoother: type", smoother_type);
101 parameter_list.set("coarse: type", coarse_type);
102
103 // Force re-initialization of the random seed to make ML deterministic
104 parameter_list.set("initialize random seed", true);
105
106 parameter_list.set("smoother: sweeps", static_cast<int>(smoother_sweeps));
107 parameter_list.set("cycle applications", static_cast<int>(n_cycles));
108 if (w_cycle == true)
109 parameter_list.set("prec type", "MGW");
110 else
111 parameter_list.set("prec type", "MGV");
112
113 parameter_list.set("smoother: Chebyshev alpha", 10.);
114 parameter_list.set("smoother: ifpack overlap",
115 static_cast<int>(smoother_overlap));
116 parameter_list.set("aggregation: threshold", aggregation_threshold);
117 parameter_list.set("coarse: max size", 2000);
118
119 if (output_details)
120 parameter_list.set("ML output", 10);
121 else
122 parameter_list.set("ML output", 0);
123
124 set_operator_null_space(parameter_list, distributed_constant_modes, matrix);
125 }
126
127
128
129 void
131 Teuchos::ParameterList &parameter_list,
132 std::unique_ptr<Epetra_MultiVector> &ptr_distributed_constant_modes,
133 const Epetra_RowMatrix &matrix) const
134 {
135 const auto run = [&](const auto &constant_modes) {
136 const Epetra_Map &domain_map = matrix.OperatorDomainMap();
137
138 const size_type constant_modes_dimension = constant_modes.size();
139 ptr_distributed_constant_modes =
140 std::make_unique<Epetra_MultiVector>(domain_map,
141 constant_modes_dimension > 0 ?
142 constant_modes_dimension :
143 1);
144 Assert(ptr_distributed_constant_modes, ExcNotInitialized());
145 Epetra_MultiVector &distributed_constant_modes =
146 *ptr_distributed_constant_modes;
147
148 if (constant_modes_dimension > 0)
149 {
150 const size_type global_size = TrilinosWrappers::n_global_rows(matrix);
151 Assert(global_size ==
153 distributed_constant_modes)),
154 ExcDimensionMismatch(global_size,
156 distributed_constant_modes)));
157 const bool constant_modes_are_global =
158 constant_modes[0].size() == global_size;
159 const size_type my_size = domain_map.NumMyElements();
160
161 // Reshape null space as a contiguous vector of doubles so that
162 // Trilinos can read from it.
163 const size_type expected_mode_size =
164 constant_modes_are_global ? global_size : my_size;
165 for (size_type d = 0; d < constant_modes_dimension; ++d)
166 {
167 Assert(constant_modes[d].size() == expected_mode_size,
168 ExcDimensionMismatch(constant_modes[d].size(),
169 expected_mode_size));
170 for (size_type row = 0; row < my_size; ++row)
171 {
172 const TrilinosWrappers::types::int_type mode_index =
173 constant_modes_are_global ?
174 TrilinosWrappers::global_index(domain_map, row) :
175 row;
176 distributed_constant_modes[d][row] =
177 static_cast<double>(constant_modes[d][mode_index]);
178 }
179 }
180
181 parameter_list.set("null space: type", "pre-computed");
182 parameter_list.set("null space: dimension",
183 distributed_constant_modes.NumVectors());
184 parameter_list.set("null space: vectors",
185 distributed_constant_modes.Values());
186 }
187 };
188
189 if (!constant_modes_values.empty())
190 {
191 AssertDimension(constant_modes.size(), 0);
192 run(constant_modes_values);
193 }
194 else
195 run(constant_modes);
196 }
197
198
199
200 void
202 Teuchos::ParameterList &parameter_list,
203 std::unique_ptr<Epetra_MultiVector> &distributed_constant_modes,
204 const SparseMatrix &matrix) const
205 {
206 return set_parameters(parameter_list,
207 distributed_constant_modes,
208 matrix.trilinos_matrix());
209 }
210
211
212
213 void
215 Teuchos::ParameterList &parameter_list,
216 std::unique_ptr<Epetra_MultiVector> &distributed_constant_modes,
217 const SparseMatrix &matrix) const
218 {
219 return set_operator_null_space(parameter_list,
220 distributed_constant_modes,
221 matrix.trilinos_matrix());
222 }
223
224
225
227 {
228 preconditioner.reset();
229 trilinos_matrix.reset();
230 }
231
232
233
234 void
236 const AdditionalData &additional_data)
237 {
238 initialize(matrix.trilinos_matrix(), additional_data);
239 }
240
241
242
243 void
244 PreconditionAMG::initialize(const Epetra_RowMatrix &matrix,
245 const AdditionalData &additional_data)
246 {
247 // Build the AMG preconditioner.
248 Teuchos::ParameterList ml_parameters;
249 std::unique_ptr<Epetra_MultiVector> distributed_constant_modes;
250 additional_data.set_parameters(ml_parameters,
251 distributed_constant_modes,
252 matrix);
253
254 initialize(matrix, ml_parameters);
255
256 if (additional_data.output_details)
257 {
258 ML_Epetra::MultiLevelPreconditioner *multilevel_operator =
259 dynamic_cast<ML_Epetra::MultiLevelPreconditioner *>(
260 preconditioner.get());
261 Assert(multilevel_operator != nullptr,
262 ExcMessage("Preconditioner setup failed."));
263 multilevel_operator->PrintUnused(0);
264 }
265 }
266
267
268
269 void
271 const Teuchos::ParameterList &ml_parameters)
272 {
273 initialize(matrix.trilinos_matrix(), ml_parameters);
274 }
275
276
277
278 void
279 PreconditionAMG::initialize(const Epetra_RowMatrix &matrix,
280 const Teuchos::ParameterList &ml_parameters)
281 {
282 preconditioner.reset(
283 new ML_Epetra::MultiLevelPreconditioner(matrix, ml_parameters));
284 }
285
286
287
288 template <typename number>
289 void
291 const ::SparseMatrix<number> &deal_ii_sparse_matrix,
292 const AdditionalData &additional_data,
293 const double drop_tolerance,
294 const ::SparsityPattern *use_this_sparsity)
295 {
296 preconditioner.reset();
297 const size_type n_rows = deal_ii_sparse_matrix.m();
298
299 // Init Epetra Matrix using an equidistributed map; avoid storing the
300 // nonzero elements.
301 IndexSet distributor(n_rows);
302 const unsigned int n_mpi_processes = communicator.NumProc();
303 const unsigned int my_id = communicator.MyPID();
304 distributor.add_range(my_id * n_rows / n_mpi_processes,
305 (my_id + 1) * n_rows / n_mpi_processes);
306
307 if (trilinos_matrix.get() == nullptr)
308 trilinos_matrix = std::make_shared<SparseMatrix>();
309
310 trilinos_matrix->reinit(distributor,
311 distributor,
312 deal_ii_sparse_matrix,
313 communicator.Comm(),
314 drop_tolerance,
315 true,
316 use_this_sparsity);
317
318 initialize(*trilinos_matrix, additional_data);
319 }
320
321
322
323 void
325 {
326 ML_Epetra::MultiLevelPreconditioner *multilevel_operator =
327 dynamic_cast<ML_Epetra::MultiLevelPreconditioner *>(preconditioner.get());
328 multilevel_operator->ReComputePreconditioner();
329 }
330
331
332
333 void
339
340
341
344 {
345 unsigned int memory = sizeof(*this);
346
347 // todo: find a way to read out ML's data
348 // sizes
349 if (trilinos_matrix.get() != nullptr)
350 memory += trilinos_matrix->memory_consumption();
351 return memory;
352 }
353
354
355
356# ifndef DOXYGEN
357 // explicit instantiations
358 template void
359 PreconditionAMG::initialize(const ::SparseMatrix<double> &,
360 const AdditionalData &,
361 const double,
362 const ::SparsityPattern *);
363 template void
364 PreconditionAMG::initialize(const ::SparseMatrix<float> &,
365 const AdditionalData &,
366 const double,
367 const ::SparsityPattern *);
368# endif
369
370
371
372} // namespace TrilinosWrappers
373
374
375#endif // DEAL_II_WITH_TRILINOS
void add_range(const size_type begin, const size_type end)
Definition index_set.h:1786
std::shared_ptr< SparseMatrix > trilinos_matrix
void initialize(const SparseMatrix &matrix, const AdditionalData &additional_data=AdditionalData())
Teuchos::RCP< Epetra_Operator > preconditioner
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:636
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:680
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
std::size_t size
Definition mpi.cc:733
TrilinosWrappers::types::int_type global_index(const Epetra_BlockMap &map, const ::types::global_dof_index i)
TrilinosWrappers::types::int_type n_global_rows(const Epetra_CrsGraph &graph)
TrilinosWrappers::types::int_type global_length(const Epetra_MultiVector &vector)
AdditionalData(const bool elliptic=true, const bool higher_order_elements=false, const unsigned int n_cycles=1, const bool w_cycle=false, const double aggregation_threshold=1e-4, const std::vector< std::vector< bool > > &constant_modes=std::vector< std::vector< bool > >(0), const unsigned int smoother_sweeps=2, const unsigned int smoother_overlap=0, const bool output_details=false, const char *smoother_type="Chebyshev", const char *coarse_type="Amesos-KLU")
void set_operator_null_space(Teuchos::ParameterList &parameter_list, std::unique_ptr< Epetra_MultiVector > &distributed_constant_modes, const Epetra_RowMatrix &matrix) const
void set_parameters(Teuchos::ParameterList &parameter_list, std::unique_ptr< Epetra_MultiVector > &distributed_constant_modes, const Epetra_RowMatrix &matrix) const