Reference documentation for deal.II version 8.4.2
trilinos_precondition_muelu.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2015 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/lac/trilinos_precondition.h>
17 
18 #ifdef DEAL_II_WITH_TRILINOS
19 #if DEAL_II_TRILINOS_VERSION_GTE(11,14,0)
20 
21 # include <deal.II/lac/vector.h>
22 # include <deal.II/lac/sparse_matrix.h>
23 # include <deal.II/lac/trilinos_sparse_matrix.h>
24 
25 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
26 # include <Teuchos_ParameterList.hpp>
27 # include <Teuchos_RCP.hpp>
28 # include <Epetra_MultiVector.h>
29 # include <ml_include.h>
30 # include <ml_MultiLevelPreconditioner.h>
31 
32 # include <MueLu.hpp>
33 # include <MueLu_EpetraOperator.hpp>
34 # include <MueLu_MLParameterListInterpreter.hpp>
36 
37 DEAL_II_NAMESPACE_OPEN
38 
39 namespace TrilinosWrappers
40 {
41  namespace
42  {
43 #ifndef DEAL_II_WITH_64BIT_INDICES
44  int n_global_rows (const Epetra_RowMatrix &matrix)
45  {
46  return matrix.NumGlobalRows();
47  }
48 
49  int global_length (const Epetra_MultiVector &vector)
50  {
51  return vector.GlobalLength();
52  }
53 
54  int gid(const Epetra_Map &map, unsigned int i)
55  {
56  return map.GID(i);
57  }
58 #else
59  long long int n_global_rows (const Epetra_RowMatrix &matrix)
60  {
61  return matrix.NumGlobalRows64();
62  }
63 
64  long long int global_length (const Epetra_MultiVector &vector)
65  {
66  return vector.GlobalLength64();
67  }
68 
69  long long int gid(const Epetra_Map &map, ::types::global_dof_index i)
70  {
71  return map.GID64(i);
72  }
73 #endif
74  }
75 
76 
77 
79  AdditionalData (const bool elliptic,
80  const unsigned int n_cycles,
81  const bool w_cycle,
82  const double aggregation_threshold,
83  const std::vector<std::vector<bool> > &constant_modes,
84  const unsigned int smoother_sweeps,
85  const unsigned int smoother_overlap,
86  const bool output_details,
87  const char *smoother_type,
88  const char *coarse_type)
89  :
90  elliptic (elliptic),
91  n_cycles (n_cycles),
92  w_cycle (w_cycle),
93  aggregation_threshold (aggregation_threshold),
94  constant_modes (constant_modes),
95  smoother_sweeps (smoother_sweeps),
96  smoother_overlap (smoother_overlap),
97  output_details (output_details),
98  smoother_type (smoother_type),
99  coarse_type (coarse_type)
100  {}
101 
102 
104  {
105  preconditioner.reset();
106  trilinos_matrix.reset();
107  }
108 
109 
110 
111  void
113  const AdditionalData &additional_data)
114  {
115  initialize(matrix.trilinos_matrix(), additional_data);
116  }
117 
118 
119 
120  void
121  PreconditionAMGMueLu::initialize (const Epetra_CrsMatrix &matrix,
122  const AdditionalData &additional_data)
123  {
124  // Build the AMG preconditioner.
125  Teuchos::ParameterList parameter_list;
126 
127  if (additional_data.elliptic == true)
128  ML_Epetra::SetDefaults("SA",parameter_list);
129  else
130  {
131  ML_Epetra::SetDefaults("NSSA",parameter_list);
132  parameter_list.set("aggregation: block scaling", true);
133  }
134  // MIS does not exist anymore, only choice are uncoupled and coupled. When using
135  // uncoupled, aggregates cannot span multiple processes. When using coupled
136  // aggregates can span multiple processes.
137  parameter_list.set("aggregation: type", "Uncoupled");
138 
139  parameter_list.set("smoother: type", additional_data.smoother_type);
140  parameter_list.set("coarse: type", additional_data.coarse_type);
141 
142  parameter_list.set("smoother: sweeps",
143  static_cast<int>(additional_data.smoother_sweeps));
144  parameter_list.set("cycle applications",
145  static_cast<int>(additional_data.n_cycles));
146  if (additional_data.w_cycle == true)
147  parameter_list.set("prec type", "MGW");
148  else
149  parameter_list.set("prec type", "MGV");
150 
151  parameter_list.set("smoother: Chebyshev alpha",10.);
152  parameter_list.set("smoother: ifpack overlap",
153  static_cast<int>(additional_data.smoother_overlap));
154  parameter_list.set("aggregation: threshold",
155  additional_data.aggregation_threshold);
156  parameter_list.set("coarse: max size", 2000);
157 
158  if (additional_data.output_details)
159  parameter_list.set("ML output", 10);
160  else
161  parameter_list.set("ML output", 0);
162 
163  const Epetra_Map &domain_map = matrix.OperatorDomainMap();
164 
165  const size_type constant_modes_dimension =
166  additional_data.constant_modes.size();
167  Epetra_MultiVector distributed_constant_modes (domain_map,
168  constant_modes_dimension > 0 ?
169  constant_modes_dimension : 1);
170  std::vector<double> dummy (constant_modes_dimension);
171 
172  if (constant_modes_dimension > 0)
173  {
174  const size_type n_rows = n_global_rows(matrix);
175  const bool constant_modes_are_global =
176  additional_data.constant_modes[0].size() == n_rows;
177  const size_type n_relevant_rows =
178  constant_modes_are_global ? n_rows : additional_data.constant_modes[0].size();
179  const size_type my_size = domain_map.NumMyElements();
180  if (constant_modes_are_global == false)
181  Assert (n_relevant_rows == my_size,
182  ExcDimensionMismatch(n_relevant_rows, my_size));
183  Assert (n_rows ==
184  static_cast<size_type>(global_length(distributed_constant_modes)),
185  ExcDimensionMismatch(n_rows,
186  global_length(distributed_constant_modes)));
187 
188  (void)n_relevant_rows;
189  (void)global_length;
190 
191  // Reshape null space as a contiguous vector of doubles so that
192  // Trilinos can read from it.
193  for (size_type d=0; d<constant_modes_dimension; ++d)
194  for (size_type row=0; row<my_size; ++row)
195  {
196  TrilinosWrappers::types::int_type global_row_id =
197  constant_modes_are_global ? gid(domain_map,row) : row;
198  distributed_constant_modes[d][row] =
199  additional_data.constant_modes[d][global_row_id];
200  }
201 
202  parameter_list.set("null space: type", "pre-computed");
203  parameter_list.set("null space: dimension",
204  distributed_constant_modes.NumVectors());
205  if (my_size > 0)
206  parameter_list.set("null space: vectors",
207  distributed_constant_modes.Values());
208  // We need to set a valid pointer to data even if there is no data on
209  // the current processor. Therefore, pass a dummy in that case
210  else
211  parameter_list.set("null space: vectors",
212  &dummy[0]);
213  }
214 
215  initialize (matrix, parameter_list);
216  }
217 
218 
219 
220  void
222  Teuchos::ParameterList &muelu_parameters)
223  {
224  initialize(matrix.trilinos_matrix(), muelu_parameters);
225  }
226 
227 
228 
229  void
230  PreconditionAMGMueLu::initialize (const Epetra_CrsMatrix &matrix,
231  Teuchos::ParameterList &muelu_parameters)
232  {
233  // We cannot use MueLu::CreateEpetraOperator directly because, we cannot
234  // transfer ownership of MueLu::EpetraOperator from Teuchos::RCP to
235  // std::shared_ptr.
236 
237  // For now, just use serial node, i.e. no multithreaing or GPU.
238  typedef KokkosClassic::DefaultNode::DefaultNodeType node;
239  preconditioner.reset ();
240 
241  // Cast matrix into a MueLu::Matrix. The constness needs to be cast away.
242  // MueLu uses Teuchos::RCP which are Trilinos version of std::shared_ptr.
243  Teuchos::RCP<Epetra_CrsMatrix> rcp_matrix = Teuchos::rcpFromRef(
244  *(const_cast<Epetra_CrsMatrix *>(&matrix)));
245  Teuchos::RCP<Xpetra::CrsMatrix<double,int,int,node> > muelu_crs_matrix =
246  Teuchos::rcp(new Xpetra::EpetraCrsMatrix (rcp_matrix));
247  Teuchos::RCP<Xpetra::Matrix<double,int,int,node> > muelu_matrix =
248  Teuchos::rcp(new Xpetra::CrsMatrixWrap<double,int,int,node> (muelu_crs_matrix));
249 
250  // Create the multigrid hierarchy using ML parameters.
251  Teuchos::RCP<MueLu::HierarchyManager<double,int,int,node> > hierarchy_factory;
252  hierarchy_factory = Teuchos::rcp(
253  new MueLu::MLParameterListInterpreter<double,int,int,node> (muelu_parameters));
254  Teuchos::RCP<MueLu::Hierarchy<double,int,int,node> > hierarchy = hierarchy_factory->CreateHierarchy();
255  hierarchy->GetLevel(0)->Set("A",muelu_matrix);
256  hierarchy_factory->SetupHierarchy(*hierarchy);
257 
258  // MueLu::EpetraOperator is just a wrapper around a "standard"
259  // Epetra_Operator.
260  preconditioner.reset(new MueLu::EpetraOperator(hierarchy));
261  }
262 
263 
264 
265  template <typename number>
266  void
268  initialize (const ::SparseMatrix<number> &deal_ii_sparse_matrix,
269  const AdditionalData &additional_data,
270  const double drop_tolerance,
271  const ::SparsityPattern *use_this_sparsity)
272  {
273  preconditioner.reset();
274  const size_type n_rows = deal_ii_sparse_matrix.m();
275 
276  // Init Epetra Matrix using an
277  // equidistributed map; avoid
278  // storing the nonzero
279  // elements.
280  vector_distributor.reset (new Epetra_Map(static_cast<TrilinosWrappers::types::int_type>(n_rows),
281  0, communicator));
282 
283  if (trilinos_matrix.get() == 0)
284  trilinos_matrix.reset (new SparseMatrix());
285 
287  deal_ii_sparse_matrix, drop_tolerance, true,
288  use_this_sparsity);
289 
290  initialize (*trilinos_matrix, additional_data);
291  }
292 
293 
294 
296  {
298  trilinos_matrix.reset();
299  }
300 
301 
302 
305  {
306  unsigned int memory = sizeof(this);
307 
308  // todo: find a way to read out ML's data
309  // sizes
310  if (trilinos_matrix.get() != 0)
311  memory += trilinos_matrix->memory_consumption();
312  return memory;
313  }
314 
315 
316 
317  // explicit instantiations
318  template void PreconditionAMGMueLu::initialize (const ::SparseMatrix<double> &,
319  const AdditionalData &, const double,
320  const ::SparsityPattern *);
321  template void PreconditionAMGMueLu::initialize (const ::SparseMatrix<float> &,
322  const AdditionalData &, const double,
323  const ::SparsityPattern *);
324 
325 }
326 
327 DEAL_II_NAMESPACE_CLOSE
328 
329 #endif // DEAL_II_TRILINOS_VERSION_GTE(11,14,0)
330 #endif // DEAL_II_WITH_TRILINOS
void initialize(const SparseMatrix &matrix, const AdditionalData &additional_data=AdditionalData())
AdditionalData(const bool elliptic=true, const unsigned int n_cycles=1, const bool w_cyle=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_cxx11::shared_ptr< SparseMatrix > trilinos_matrix
std_cxx11::shared_ptr< Epetra_Map > vector_distributor
std_cxx11::shared_ptr< Epetra_Operator > preconditioner
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:294
void initialize(const SparseMatrix &matrix, const AdditionalData &additional_data=AdditionalData())