[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
linear_solver.cpp
1 #include <deal.II/base/conditional_ostream.h>
2 
3 #include <deal.II/lac/solver_control.h>
4 #include <deal.II/lac/trilinos_precondition.h>
5 #include <deal.II/lac/trilinos_solver.h>
6 
7 #include "Ifpack.h"
8 #include <Ifpack_ILU.h>
9 
10 #include <deal.II/lac/solver_gmres.h>
11 
12 #include "linear_solver.h"
13 
14 #include "global_counter.hpp"
15 
16 namespace PHiLiP {
17 
18 class PreconditionILU_RAS: public dealii::TrilinosWrappers::PreconditionILU {
19 
20  using dealii::TrilinosWrappers::PreconditionILU::AdditionalData;
21 
22 public:
23  void initialize(const dealii::TrilinosWrappers::SparseMatrix &matrix, const AdditionalData &additional_data)
24  {
25  preconditioner.reset();
26 
27  matrix.trilinos_matrix().Print(std::cout);
28 
29  Epetra_CrsMatrix * epetra_matrix = const_cast<Epetra_CrsMatrix *>(&(matrix.trilinos_matrix()));
30 
31  Ifpack_Preconditioner *ifpack = dynamic_cast<Ifpack_Preconditioner *>(preconditioner.get());
32 
33  preconditioner.reset(Ifpack().Create("ILU", epetra_matrix, additional_data.overlap));
34 
35  std::cout << ifpack << std::endl;
36  ifpack = dynamic_cast<Ifpack_Preconditioner *>(preconditioner.get());
37  std::cout << ifpack << std::endl;
38 
39  Assert(ifpack != nullptr, dealii::ExcMessage("Trilinos could not create this " "preconditioner"));
40 
41  int ierr;
42 
43  Teuchos::ParameterList parameter_list;
44  parameter_list.set("fact: level-of-fill", static_cast<int>(additional_data.ilu_fill));
45  parameter_list.set("fact: absolute threshold", additional_data.ilu_atol);
46  parameter_list.set("fact: relative threshold", additional_data.ilu_rtol);
47  //parameter_list.set("schwarz: combine mode", "Add");
48  parameter_list.set("schwarz: reordering type", "rcm");
49 
50  ierr = ifpack->SetParameters(parameter_list);
51  AssertThrow(ierr == 0, dealii::ExcTrilinosError(ierr));
52 
53  ierr = ifpack->Initialize();
54  AssertThrow(ierr == 0, dealii::ExcTrilinosError(ierr));
55 
56  ierr = ifpack->Compute();
57  AssertThrow(ierr == 0, dealii::ExcTrilinosError(ierr));
58 
59  ifpack->Print(std::cout);
60 
61  Ifpack_ILU *ifpack_ilu = dynamic_cast<Ifpack_ILU *>(ifpack);
62 
63  {
64  const Epetra_CrsMatrix &L = ifpack_ilu->L();
65  const Epetra_Vector &D = ifpack_ilu->D();
66  const Epetra_CrsMatrix &U = ifpack_ilu->U();
67 
68  L.Print(std::cout);
69  D.Print(std::cout);
70  U.Print(std::cout);
71  }
72 
73 
74  Ifpack Factory;
75 
76  Teuchos::ParameterList List;
77 
78  const std::string PrecType = "ILU";
79  List.set("fact: level-of-fill", 0);
80 
81  List.set("schwarz: reordering type", "rcm");
82  const int OverlapLevel = 1; // one row of overlap among the processes
83  Ifpack_Preconditioner *jacobian_prec = Factory.Create(PrecType, epetra_matrix, OverlapLevel);
84  jacobian_prec->Print(std::cout);
85  assert (jacobian_prec != 0);
86 
87 
88  ierr = jacobian_prec->SetParameters(List);
89  AssertThrow(ierr == 0, dealii::ExcTrilinosError(ierr));
90  ierr = jacobian_prec->Initialize();
91  AssertThrow(ierr == 0, dealii::ExcTrilinosError(ierr));
92  ierr = jacobian_prec->Compute();
93  AssertThrow(ierr == 0, dealii::ExcTrilinosError(ierr));
94 
95  preconditioner.reset(jacobian_prec);
96 
97 
98  {
99  ifpack = dynamic_cast<Ifpack_Preconditioner *>(preconditioner.get());
100  ifpack_ilu = dynamic_cast<Ifpack_ILU *>(ifpack);
101  const Epetra_CrsMatrix &L = ifpack_ilu->L();
102  const Epetra_Vector &D = ifpack_ilu->D();
103  const Epetra_CrsMatrix &U = ifpack_ilu->U();
104 
105  L.Print(std::cout);
106  D.Print(std::cout);
107  U.Print(std::cout);
108  }
109  };
110 };
111 
112 std::pair<unsigned int, double>
113 solve_linear3 (
114  const dealii::TrilinosWrappers::SparseMatrix &system_matrix,
115  dealii::LinearAlgebra::distributed::Vector<double> &right_hand_side,
116  dealii::LinearAlgebra::distributed::Vector<double> &solution,
117  const Parameters::LinearSolverParam &param)
118 {
119  std::shared_ptr<dealii::TrilinosWrappers::PreconditionBase> preconditioner;
120  // ILU Preconditioner
121  if (param.ilut_fill < 1) {
122  typedef dealii::TrilinosWrappers::PreconditionILU::AdditionalData AddiData_ILU;
123  const unsigned int overlap = 1;
124  AddiData_ILU precond_settings(std::abs(param.ilut_fill), param.ilut_atol, param.ilut_rtol, overlap);
125 
126  std::shared_ptr<dealii::TrilinosWrappers::PreconditionILU> ilu_preconditioner = std::make_shared<dealii::TrilinosWrappers::PreconditionILU> ();
127  ilu_preconditioner->initialize(system_matrix, precond_settings);
128 
129  preconditioner = ilu_preconditioner;
130  } else {
131  typedef dealii::TrilinosWrappers::PreconditionILUT::AdditionalData AddiData_ILUT;
132  const unsigned int overlap = 1;
133  AddiData_ILUT precond_settings(param.ilut_fill, param.ilut_atol, param.ilut_rtol, overlap);
134 
135  std::shared_ptr<dealii::TrilinosWrappers::PreconditionILUT> ilut_preconditioner = std::make_shared<dealii::TrilinosWrappers::PreconditionILUT> ();
136  ilut_preconditioner->initialize(system_matrix, precond_settings);
137 
138  preconditioner = ilut_preconditioner;
139  }
140 
141  // Solver convergence settings
142  const double rhs_norm = right_hand_side.l2_norm();
143  const double linear_residual_tolerance = param.linear_residual * rhs_norm;
144  const int max_iterations = param.max_iterations;
145 
146  const bool log_history = (param.linear_solver_output == Parameters::OutputEnum::verbose);
147  const bool log_result = true;//(param.linear_solver_output == Parameters::OutputEnum::verbose);
148  dealii::SolverControl solver_control(max_iterations, linear_residual_tolerance, log_history, log_result);
149  if (log_history) solver_control.enable_history_data();
150 
151  const bool right_preconditioning = false; // default: false
152  const bool use_default_residual = true;//false; // default: true
153  const bool force_re_orthogonalization = false; // default: false
154  using VectorType = dealii::LinearAlgebra::distributed::Vector<double>;
155  typedef typename dealii::SolverGMRES<VectorType>::AdditionalData AddiData_GMRES;
156  AddiData_GMRES add_data_gmres( param.restart_number, right_preconditioning, use_default_residual, force_re_orthogonalization);
157  dealii::SolverGMRES<VectorType> solver_gmres(solver_control, add_data_gmres);
158 
159 
160  solver_gmres.solve(system_matrix, solution, right_hand_side, *preconditioner);
161 
162  return {solver_control.last_step(), solver_control.last_value()};
163 
164 }
165 
166 std::pair<unsigned int, double>
168  const dealii::TrilinosWrappers::SparseMatrix &system_matrix,
169  dealii::LinearAlgebra::distributed::Vector<double> &right_hand_side,
170  dealii::LinearAlgebra::distributed::Vector<double> &solution,
171  const Parameters::LinearSolverParam &param)
172 {
173 
174  // if (pcout.is_active()) system_matrix.print(pcout.get_stream(), true);
175  // if (pcout.is_active()) solution.print(pcout.get_stream());
176 
177  Parameters::LinearSolverParam::LinearSolverEnum direct_type = Parameters::LinearSolverParam::LinearSolverEnum::direct;
178  Parameters::LinearSolverParam::LinearSolverEnum gmres_type = Parameters::LinearSolverParam::LinearSolverEnum::gmres;
179 
180  //if (param.linear_solver_output == Parameters::OutputEnum::verbose) {
181  // dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
182  // if (pcout.is_active()) right_hand_side.print(pcout.get_stream());
183  // if (pcout.is_active()) solution.print(pcout.get_stream());
184  // dealii::FullMatrix<double> fullA(system_matrix.m());
185  // fullA.copy_from(system_matrix);
186  // pcout<<"Dense matrix:"<<std::endl;
187  // if (pcout.is_active()) fullA.print_formatted(pcout.get_stream(), 12, true, 10, "0", 1., 0.);
188  //}
189  if (param.linear_solver_type == direct_type) {
190 
191  dealii::SolverControl solver_control(1, 0);
192  dealii::TrilinosWrappers::SolverDirect::AdditionalData data(false);
193  //dealii::TrilinosWrappers::SolverDirect::AdditionalData data(parameters.output == Parameters::Solver::verbose);
194  dealii::TrilinosWrappers::SolverDirect direct(solver_control, data);
195 
196  direct.solve(system_matrix, solution, right_hand_side);
197  return {solver_control.last_step(), solver_control.last_value()};
198  } else if (param.linear_solver_type == gmres_type) {
199  //solution = right_hand_side;
200  //solution *= 1e-3;
201  solution *= 0.0;
202  Epetra_Vector x(View,
203  system_matrix.trilinos_matrix().DomainMap(),
204  solution.begin());
205  Epetra_Vector b(View,
206  system_matrix.trilinos_matrix().RangeMap(),
207  right_hand_side.begin());
208  AztecOO solver;
209  solver.SetAztecOption( AZ_output, (param.linear_solver_output ? AZ_all : AZ_last));
210  solver.SetAztecOption(AZ_solver, AZ_gmres);
211  //solver.SetAztecOption(AZ_solver, AZ_bicgstab);
212  //solver.SetAztecOption(AZ_solver, AZ_cg);
213  solver.SetAztecOption(AZ_kspace, param.restart_number);
214  solver.SetRHS(&b);
215  solver.SetLHS(&x);
216 
217 
218  const double rhs_norm = right_hand_side.l2_norm();
219  const double linear_residual = param.linear_residual * rhs_norm;//1e-4;
220  const int max_iterations = param.max_iterations;//200
221  solver.SetUserMatrix(const_cast<Epetra_CrsMatrix *>(&system_matrix.trilinos_matrix()));
222  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
223  pcout << " Solving linear system with max_iterations = " << max_iterations
224  << " and linear residual tolerance: " << linear_residual << std::endl;
225 
226 
227  //solver.SetAztecOption(AZ_orthog, AZ_modified);
228  solver.SetAztecOption(AZ_orthog, AZ_classic);
229  solver.SetAztecOption(AZ_conv, AZ_rhs);
230 
231  solver.SetAztecOption(AZ_precond, AZ_dom_decomp);
232  solver.SetAztecOption(AZ_overlap, 1);
233  solver.SetAztecOption(AZ_reorder, 1); // RCM re-ordering
234  const int ilut_fill = param.ilut_fill;
235  if (ilut_fill < -99) {
236  // // Jacobi preconditioner.
237  //solver.SetAztecOption(AZ_precond, AZ_Jacobi);
238  //solver.SetAztecOption(AZ_poly_ord, 1);
239 
240  // No Preconditioner.
241  solver.SetAztecOption(AZ_precond, AZ_none);
242  } else if (ilut_fill < 1) {
243  solver.SetAztecOption(AZ_subdomain_solve, AZ_ilu);
244  solver.SetAztecOption(AZ_graph_fill, std::abs(ilut_fill));
245 
246  double ilut_rtol = param.ilut_rtol;//0.0,//1.1,
247  double ilut_atol = param.ilut_atol;//0.0,//1e-9,
248  solver.SetAztecParam(AZ_athresh, ilut_atol);
249  solver.SetAztecParam(AZ_rthresh, ilut_rtol);
250  } else {
251  const double ilut_drop = param.ilut_drop;
252  double ilut_rtol = param.ilut_rtol;//0.0,//1.1,
253  double ilut_atol = param.ilut_atol;//0.0,//1e-9,
254  solver.SetAztecOption(AZ_subdomain_solve, AZ_ilut);
255 
256  solver.SetAztecParam(AZ_drop, ilut_drop);
257  solver.SetAztecParam(AZ_ilut_fill, ilut_fill);
258  solver.SetAztecParam(AZ_athresh, ilut_atol);
259  solver.SetAztecParam(AZ_rthresh, ilut_rtol);
260  }
261 
262  unsigned int n_iterations = 0;
263  const int n_solves = 2;
264  for (int i_solve = 0; i_solve < n_solves; ++i_solve) {
265  solver.Iterate(max_iterations,
266  linear_residual);
267  n_iterations += solver.NumIters();
268  pcout << " Solve #" << i_solve + 1 << " out of " << n_solves << "."
269  << " Linear solver took " << solver.NumIters()
270  << " iterations resulting in a linear residual of " << solver.ScaledResidual()
271  << std::endl;
272  }
273 
274  pcout << " Totalling " << n_iterations
275  << " iterations resulting in a linear residual of " << solver.ScaledResidual() << std::endl
276  << " Current RHS norm: " << right_hand_side.l2_norm()
277  << " Linear solution norm: " << solution.l2_norm() << std::endl;
278 
279  //n_vmult += 3*solver.NumIters();
280  //dRdW_mult += 3*solver.NumIters();
281  n_vmult += 7*solver.NumIters();
282  dRdW_mult += 7*solver.NumIters();
283 
284  //std::abort();
285  return {solver.NumIters(), solver.TrueResidual()};
286  }
287  return {-1.0, -1.0};
288 }
289 
290 
291 } // PHiLiP namespace
double ilut_drop
Threshold to drop terms close to zero.
Parameters related to the linear solver.
LinearSolverEnum
Types of linear solvers available.
std::pair< unsigned int, double > solve_linear(const dealii::TrilinosWrappers::SparseMatrix &system_matrix, dealii::LinearAlgebra::distributed::Vector< double > &right_hand_side, dealii::LinearAlgebra::distributed::Vector< double > &solution, const Parameters::LinearSolverParam &param)
double ilut_atol
Add ilu_rtol to diagonal for more diagonal dominance.
Files for the baseline physics.
Definition: ADTypes.hpp:10
int restart_number
Number of iterations before restarting GMRES.
double linear_residual
Tolerance for linear residual.
LinearSolverEnum linear_solver_type
direct or gmres.
double ilut_rtol
Multiplies diagonal by ilut_rtol for more diagonal dominance.
int max_iterations
Maximum number of linear iteration.
OutputEnum linear_solver_output
Can either be verbose or quiet.