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