deal.II version GIT relicensing-6839-g338455934c 2026-10-02 12:10: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_muelu.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# ifdef DEAL_II_TRILINOS_WITH_MUELU
20
22# include <MueLu_CreateEpetraPreconditioner.hpp>
23# include <ml_MultiLevelPreconditioner.h>
25
26
27# endif // DEAL_II_TRILINOS_WITH_MUELU
28#endif // DEAL_II_WITH_TRILINOS
29
31
32#ifdef DEAL_II_WITH_TRILINOS
33# ifdef DEAL_II_TRILINOS_WITH_MUELU
34
35namespace TrilinosWrappers
36{
38 const bool elliptic,
39 const unsigned int n_cycles,
40 const bool w_cycle,
41 const double aggregation_threshold,
42 const std::vector<std::vector<bool>> &constant_modes,
43 const unsigned int smoother_sweeps,
44 const unsigned int smoother_overlap,
45 const bool output_details,
46 const char *smoother_type,
47 const char *coarse_type)
48 : elliptic(elliptic)
49 , n_cycles(n_cycles)
50 , w_cycle(w_cycle)
51 , aggregation_threshold(aggregation_threshold)
52 , constant_modes(constant_modes)
53 , smoother_sweeps(smoother_sweeps)
54 , smoother_overlap(smoother_overlap)
55 , output_details(output_details)
56 , smoother_type(smoother_type)
57 , coarse_type(coarse_type)
58 {}
59
60
61
63 {
64 // clang-tidy wants to default the constructor if we disable the check
65 // in case we compile without 64-bit indices
66# ifdef DEAL_II_WITH_64BIT_INDICES
67 constexpr bool enabled = false;
68# else
69 constexpr bool enabled = true;
70# endif
71 AssertThrow(enabled,
73 "PreconditionAMGMueLu does not support 64bit-indices!"));
74 }
75
76
77
78 void
80 const AdditionalData &additional_data)
81 {
82 initialize(matrix.trilinos_matrix(), additional_data);
83 }
84
85
86
87 void
88 PreconditionAMGMueLu::initialize(const Epetra_CrsMatrix &matrix,
89 const AdditionalData &additional_data)
90 {
91 // Build the AMG preconditioner.
92 Teuchos::ParameterList parameter_list;
93
94 parameter_list.set("parameterlist: syntax", "ml");
95
96 if (additional_data.elliptic == true)
97 ML_Epetra::SetDefaults("SA", parameter_list);
98 else
99 {
100 ML_Epetra::SetDefaults("NSSA", parameter_list);
101 parameter_list.set("aggregation: block scaling", true);
102 }
103 // MIS does not exist anymore, only choice are uncoupled and coupled. When
104 // using uncoupled, aggregates cannot span multiple processes. When using
105 // coupled aggregates can span multiple processes.
106 parameter_list.set("aggregation: type", "Uncoupled");
107
108 parameter_list.set("smoother: type", additional_data.smoother_type);
109 parameter_list.set("coarse: type", additional_data.coarse_type);
110
111 parameter_list.set("smoother: sweeps",
112 static_cast<int>(additional_data.smoother_sweeps));
113 parameter_list.set("cycle applications",
114 static_cast<int>(additional_data.n_cycles));
115 if (additional_data.w_cycle == true)
116 parameter_list.set("prec type", "MGW");
117 else
118 parameter_list.set("prec type", "MGV");
119
120 parameter_list.set("smoother: Chebyshev alpha", 10.);
121 parameter_list.set("smoother: ifpack overlap",
122 static_cast<int>(additional_data.smoother_overlap));
123 parameter_list.set("aggregation: threshold",
124 additional_data.aggregation_threshold);
125 parameter_list.set("coarse: max size", 2000);
126
127 if (additional_data.output_details)
128 parameter_list.set("ML output", 10);
129 else
130 parameter_list.set("ML output", 0);
131
132 const Epetra_Map &domain_map = matrix.OperatorDomainMap();
133
134 const size_type constant_modes_dimension =
135 additional_data.constant_modes.size();
136 Epetra_MultiVector distributed_constant_modes(
137 domain_map, constant_modes_dimension > 0 ? constant_modes_dimension : 1);
138 std::vector<double> dummy(constant_modes_dimension);
139
140 if (constant_modes_dimension > 0)
141 {
142 const size_type n_rows = TrilinosWrappers::n_global_rows(matrix);
143 const bool constant_modes_are_global =
144 additional_data.constant_modes[0].size() == n_rows;
145 const size_type n_relevant_rows =
146 constant_modes_are_global ? n_rows :
147 additional_data.constant_modes[0].size();
148 const size_type my_size = domain_map.NumMyElements();
149 if (constant_modes_are_global == false)
150 Assert(n_relevant_rows == my_size,
151 ExcDimensionMismatch(n_relevant_rows, my_size));
152 Assert(n_rows == static_cast<size_type>(TrilinosWrappers::global_length(
153 distributed_constant_modes)),
156 distributed_constant_modes)));
157
158 // Reshape null space as a contiguous vector of doubles so that
159 // Trilinos can read from it.
160 for (size_type d = 0; d < constant_modes_dimension; ++d)
161 for (size_type row = 0; row < my_size; ++row)
162 {
164 constant_modes_are_global ?
165 TrilinosWrappers::global_index(domain_map, row) :
166 row;
167 distributed_constant_modes[d][row] = static_cast<double>(
168 additional_data.constant_modes[d][global_row_id]);
169 }
170
171 parameter_list.set("null space: type", "pre-computed");
172 parameter_list.set("null space: dimension",
173 distributed_constant_modes.NumVectors());
174 if (my_size > 0)
175 parameter_list.set("null space: vectors",
176 distributed_constant_modes.Values());
177 // We need to set a valid pointer to data even if there is no data on
178 // the current processor. Therefore, pass a dummy in that case
179 else
180 parameter_list.set("null space: vectors", dummy.data());
181 }
182
183 initialize(matrix, parameter_list);
184 }
185
186
187
188 void
190 Teuchos::ParameterList &muelu_parameters)
191 {
192 initialize(matrix.trilinos_matrix(), muelu_parameters);
193 }
194
195
196
197 void
198 PreconditionAMGMueLu::initialize(const Epetra_CrsMatrix &matrix,
199 Teuchos::ParameterList &muelu_parameters)
200 {
201 const auto teuchos_wrapped_matrix =
202 Teuchos::rcp(const_cast<Epetra_CrsMatrix *>(&matrix), false);
203 preconditioner = MueLu::CreateEpetraPreconditioner(teuchos_wrapped_matrix,
204 muelu_parameters);
205 }
206
207
208
209 template <typename number>
210 void
212 const ::SparseMatrix<number> &deal_ii_sparse_matrix,
213 const AdditionalData &additional_data,
214 const double drop_tolerance,
215 const ::SparsityPattern *use_this_sparsity)
216 {
217 preconditioner.reset();
218 const size_type n_rows = deal_ii_sparse_matrix.m();
219
220 // Init Epetra Matrix using an equidistributed map; avoid storing the
221 // nonzero elements.
222 IndexSet distributor(n_rows);
223 const unsigned int n_mpi_processes = communicator.NumProc();
224 const unsigned int my_id = communicator.MyPID();
225 distributor.add_range(my_id * n_rows / n_mpi_processes,
226 (my_id + 1) * n_rows / n_mpi_processes);
227
228 if (trilinos_matrix.get() == nullptr)
229 trilinos_matrix = std::make_shared<SparseMatrix>();
230
231 trilinos_matrix->reinit(distributor,
232 distributor,
233 deal_ii_sparse_matrix,
234 communicator.Comm(),
235 drop_tolerance,
236 true,
237 use_this_sparsity);
238
239 initialize(*trilinos_matrix, additional_data);
240 }
241
242
243
244 void
250
251
252
255 {
256 unsigned int memory = sizeof(*this);
257
258 // todo: find a way to read out ML's data
259 // sizes
260 if (trilinos_matrix.get() != nullptr)
261 memory += trilinos_matrix->memory_consumption();
262 return memory;
263 }
264
265
266
267# ifndef DOXYGEN
268 // explicit instantiations
269 template void
270 PreconditionAMGMueLu::initialize(const ::SparseMatrix<double> &,
271 const AdditionalData &,
272 const double,
273 const ::SparsityPattern *);
274 template void
275 PreconditionAMGMueLu::initialize(const ::SparseMatrix<float> &,
276 const AdditionalData &,
277 const double,
278 const ::SparsityPattern *);
279# endif
280
281} // namespace TrilinosWrappers
282
283
284# endif // DEAL_II_TRILINOS_WITH_MUELU
285#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)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
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 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")