Reference documentation for deal.II version 9.0.0
petsc_precondition.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2017 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/petsc_precondition.h>
17 
18 #ifdef DEAL_II_WITH_PETSC
19 
20 # include <deal.II/base/utilities.h>
21 # include <deal.II/lac/exceptions.h>
22 # include <deal.II/lac/petsc_compatibility.h>
23 # include <deal.II/lac/petsc_matrix_base.h>
24 # include <deal.II/lac/petsc_vector_base.h>
25 # include <deal.II/lac/petsc_solver.h>
26 # include <petscconf.h>
27 # include <cmath>
28 
29 DEAL_II_NAMESPACE_OPEN
30 
31 namespace PETScWrappers
32 {
34  :
35  pc(nullptr), matrix(nullptr)
36  {}
37 
39  {
40  try
41  {
42  clear();
43  }
44  catch (...)
45  {}
46  }
47 
48  void
50  {
51  matrix = nullptr;
52 
53  if (pc!=nullptr)
54  {
55  PetscErrorCode ierr = PCDestroy(&pc);
56  pc = nullptr;
57  AssertThrow (ierr == 0, ExcPETScError(ierr));
58  }
59  }
60 
61 
62  void
64  const VectorBase &src) const
65  {
67 
68  const PetscErrorCode ierr = PCApply(pc, src, dst);
69  AssertThrow (ierr == 0, ExcPETScError(ierr));
70  }
71 
72 
73  void
75  {
76  // only allow the creation of the
77  // preconditioner once
79 
80  MPI_Comm comm;
81  // this ugly cast is necessary because the
82  // type Mat and PETScObject are
83  // unrelated.
84  PetscErrorCode ierr = PetscObjectGetComm(reinterpret_cast<PetscObject>(matrix),
85  &comm);
86  AssertThrow (ierr == 0, ExcPETScError(ierr));
87 
88  ierr = PCCreate(comm, &pc);
89  AssertThrow (ierr == 0, ExcPETScError(ierr));
90 
91 #if DEAL_II_PETSC_VERSION_LT(3, 5, 0)
92  ierr = PCSetOperators(pc, matrix, matrix, SAME_PRECONDITIONER);
93 #else
94  ierr = PCSetOperators(pc, matrix, matrix);
95 #endif
96  AssertThrow (ierr == 0, ExcPETScError(ierr));
97  }
98 
99 
100  const PC &
102  {
103  return pc;
104  }
105 
106 
107  PreconditionerBase::operator Mat () const
108  {
109  return matrix;
110  }
111 
112 
113  /* ----------------- PreconditionJacobi -------------------- */
115  const AdditionalData &additional_data_)
116  {
117  additional_data = additional_data_;
118 
119  PetscErrorCode ierr = PCCreate(comm, &pc);
120  AssertThrow (ierr == 0, ExcPETScError(ierr));
121 
122  initialize();
123  }
124 
125 
126 
128  const AdditionalData &additional_data)
129  {
131  }
132 
133  void
135  {
137 
138  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCJACOBI));
139  AssertThrow (ierr == 0, ExcPETScError(ierr));
140 
141  ierr = PCSetFromOptions (pc);
142  AssertThrow (ierr == 0, ExcPETScError(ierr));
143  }
144 
145  void
147  const AdditionalData &additional_data_)
148  {
149  clear ();
150 
151  matrix = static_cast<Mat>(matrix_);
152  additional_data = additional_data_;
153 
154  create_pc();
155  initialize();
156 
157  PetscErrorCode ierr = PCSetUp (pc);
158  AssertThrow (ierr == 0, ExcPETScError(ierr));
159  }
160 
161 
162  /* ----------------- PreconditionBlockJacobi -------------------- */
164  const AdditionalData &additional_data_)
165  {
166  additional_data = additional_data_;
167 
168  PetscErrorCode ierr = PCCreate(comm, &pc);
169  AssertThrow (ierr == 0, ExcPETScError(ierr));
170 
171  initialize();
172  }
173 
174 
175 
178  const AdditionalData &additional_data)
179  {
181  }
182 
183  void
185  {
186  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCBJACOBI));
187  AssertThrow (ierr == 0, ExcPETScError(ierr));
188 
189  ierr = PCSetFromOptions (pc);
190  AssertThrow (ierr == 0, ExcPETScError(ierr));
191  }
192 
193 
194  void
196  const AdditionalData &additional_data_)
197  {
198  clear ();
199 
200  matrix = static_cast<Mat>(matrix_);
201  additional_data = additional_data_;
202 
203  create_pc();
204  initialize();
205 
206  PetscErrorCode ierr = PCSetUp (pc);
207  AssertThrow (ierr == 0, ExcPETScError(ierr));
208  }
209 
210 
211  /* ----------------- PreconditionSOR -------------------- */
212 
214  AdditionalData (const double omega)
215  :
216  omega (omega)
217  {}
218 
219 
220 
223  {
225  }
226 
227 
228  void
230  const AdditionalData &additional_data_)
231  {
232  clear ();
233 
234  matrix = static_cast<Mat>(matrix_);
235  additional_data = additional_data_;
236 
237  create_pc();
238 
239  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCSOR));
240  AssertThrow (ierr == 0, ExcPETScError(ierr));
241 
242  // then set flags as given
243  ierr = PCSORSetOmega (pc, additional_data.omega);
244  AssertThrow (ierr == 0, ExcPETScError(ierr));
245 
246  ierr = PCSetFromOptions (pc);
247  AssertThrow (ierr == 0, ExcPETScError(ierr));
248 
249  ierr = PCSetUp (pc);
250  AssertThrow (ierr == 0, ExcPETScError(ierr));
251  }
252 
253 
254  /* ----------------- PreconditionSSOR -------------------- */
255 
257  AdditionalData (const double omega)
258  :
259  omega (omega)
260  {}
261 
262 
263 
266  {
268  }
269 
270 
271  void
273  const AdditionalData &additional_data_)
274  {
275  clear ();
276 
277  matrix = static_cast<Mat>(matrix_);
278  additional_data = additional_data_;
279 
280  create_pc();
281 
282  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCSOR));
283  AssertThrow (ierr == 0, ExcPETScError(ierr));
284 
285  // then set flags as given
286  ierr = PCSORSetOmega (pc, additional_data.omega);
287  AssertThrow (ierr == 0, ExcPETScError(ierr));
288 
289  // convert SOR to SSOR
290  ierr = PCSORSetSymmetric (pc, SOR_SYMMETRIC_SWEEP);
291  AssertThrow (ierr == 0, ExcPETScError(ierr));
292 
293  ierr = PCSetFromOptions (pc);
294  AssertThrow (ierr == 0, ExcPETScError(ierr));
295 
296  ierr = PCSetUp (pc);
297  AssertThrow (ierr == 0, ExcPETScError(ierr));
298  }
299 
300 
301  /* ----------------- PreconditionEisenstat -------------------- */
302 
304  AdditionalData (const double omega)
305  :
306  omega (omega)
307  {}
308 
309 
310 
313  {
315  }
316 
317 
318  void
320  const AdditionalData &additional_data_)
321  {
322  clear ();
323 
324  matrix = static_cast<Mat>(matrix_);
325  additional_data = additional_data_;
326 
327  create_pc();
328 
329  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCEISENSTAT));
330  AssertThrow (ierr == 0, ExcPETScError(ierr));
331 
332  // then set flags as given
333  ierr = PCEisenstatSetOmega (pc, additional_data.omega);
334  AssertThrow (ierr == 0, ExcPETScError(ierr));
335 
336  ierr = PCSetFromOptions (pc);
337  AssertThrow (ierr == 0, ExcPETScError(ierr));
338 
339  ierr = PCSetUp (pc);
340  AssertThrow (ierr == 0, ExcPETScError(ierr));
341  }
342 
343 
344  /* ----------------- PreconditionICC -------------------- */
345 
346 
348  AdditionalData (const unsigned int levels)
349  :
350  levels (levels)
351  {}
352 
353 
354 
357  {
359  }
360 
361 
362  void
364  const AdditionalData &additional_data_)
365  {
366  clear ();
367 
368  matrix = static_cast<Mat>(matrix_);
369  additional_data = additional_data_;
370 
371  create_pc();
372 
373  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCICC));
374  AssertThrow (ierr == 0, ExcPETScError(ierr));
375 
376  // then set flags
377  ierr = PCFactorSetLevels (pc, additional_data.levels);
378  AssertThrow (ierr == 0, ExcPETScError(ierr));
379 
380  ierr = PCSetFromOptions (pc);
381  AssertThrow (ierr == 0, ExcPETScError(ierr));
382 
383  ierr = PCSetUp (pc);
384  AssertThrow (ierr == 0, ExcPETScError(ierr));
385  }
386 
387 
388  /* ----------------- PreconditionILU -------------------- */
389 
391  AdditionalData (const unsigned int levels)
392  :
393  levels (levels)
394  {}
395 
396 
397 
400  {
402  }
403 
404 
405  void
407  const AdditionalData &additional_data_)
408  {
409  clear ();
410 
411  matrix = static_cast<Mat>(matrix_);
412  additional_data = additional_data_;
413 
414  create_pc();
415 
416  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCILU));
417  AssertThrow (ierr == 0, ExcPETScError(ierr));
418 
419  // then set flags
420  ierr = PCFactorSetLevels (pc, additional_data.levels);
421  AssertThrow (ierr == 0, ExcPETScError(ierr));
422 
423  ierr = PCSetFromOptions (pc);
424  AssertThrow (ierr == 0, ExcPETScError(ierr));
425 
426  ierr = PCSetUp (pc);
427  AssertThrow (ierr == 0, ExcPETScError(ierr));
428  }
429 
430 
431  /* ----------------- PreconditionBoomerAMG -------------------- */
432 
434  AdditionalData(const bool symmetric_operator,
435  const double strong_threshold,
436  const double max_row_sum,
437  const unsigned int aggressive_coarsening_num_levels,
438  const bool output_details
439  )
440  :
441  symmetric_operator(symmetric_operator),
442  strong_threshold(strong_threshold),
443  max_row_sum(max_row_sum),
444  aggressive_coarsening_num_levels(aggressive_coarsening_num_levels),
445  output_details(output_details)
446  {}
447 
448 
449 
451  const AdditionalData &additional_data_)
452  {
453  additional_data = additional_data_;
454 
455  PetscErrorCode ierr = PCCreate(comm, &pc);
456  AssertThrow (ierr == 0, ExcPETScError(ierr));
457 
458 #ifdef DEAL_II_PETSC_WITH_HYPRE
459  initialize();
460 #else // DEAL_II_PETSC_WITH_HYPRE
461  (void)pc;
462  Assert (false,
463  ExcMessage ("Your PETSc installation does not include a copy of "
464  "the hypre package necessary for this preconditioner."));
465 #endif
466  }
467 
468 
471  {
473  }
474 
475  void
477  {
478 #ifdef DEAL_II_PETSC_WITH_HYPRE
479  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCHYPRE));
480  AssertThrow (ierr == 0, ExcPETScError(ierr));
481 
482  ierr = PCHYPRESetType(pc, "boomeramg");
483  AssertThrow (ierr == 0, ExcPETScError(ierr));
484 
486  {
487  set_option_value("-pc_hypre_boomeramg_print_statistics", "1");
488  }
489 
490  set_option_value("-pc_hypre_boomeramg_agg_nl",
492 
493  std::stringstream ssStream;
494  ssStream << additional_data.max_row_sum;
495  set_option_value("-pc_hypre_boomeramg_max_row_sum", ssStream.str());
496 
497  ssStream.str(""); // empty the stringstream
498  ssStream << additional_data.strong_threshold;
499  set_option_value("-pc_hypre_boomeramg_strong_threshold", ssStream.str());
500 
502  {
503  set_option_value("-pc_hypre_boomeramg_relax_type_up", "symmetric-SOR/Jacobi");
504  set_option_value("-pc_hypre_boomeramg_relax_type_down", "symmetric-SOR/Jacobi");
505  set_option_value("-pc_hypre_boomeramg_relax_type_coarse", "Gaussian-elimination");
506  }
507  else
508  {
509  set_option_value("-pc_hypre_boomeramg_relax_type_up", "SOR/Jacobi");
510  set_option_value("-pc_hypre_boomeramg_relax_type_down", "SOR/Jacobi");
511  set_option_value("-pc_hypre_boomeramg_relax_type_coarse", "Gaussian-elimination");
512  }
513 
514  ierr = PCSetFromOptions (pc);
515  AssertThrow (ierr == 0, ExcPETScError(ierr));
516 #else
517  Assert (false,
518  ExcMessage ("Your PETSc installation does not include a copy of "
519  "the hypre package necessary for this preconditioner."));
520 #endif
521  }
522 
523  void
525  const AdditionalData &additional_data_)
526  {
527 #ifdef DEAL_II_PETSC_WITH_HYPRE
528  clear ();
529 
530  matrix = static_cast<Mat>(matrix_);
531  additional_data = additional_data_;
532 
533  create_pc();
534  initialize ();
535 
536  PetscErrorCode ierr = PCSetUp (pc);
537  AssertThrow (ierr == 0, ExcPETScError(ierr));
538 
539 #else // DEAL_II_PETSC_WITH_HYPRE
540  (void)matrix_;
541  (void)additional_data_;
542  Assert (false,
543  ExcMessage ("Your PETSc installation does not include a copy of "
544  "the hypre package necessary for this preconditioner."));
545 #endif
546  }
547 
548 
549  /* ----------------- PreconditionParaSails -------------------- */
550 
552  AdditionalData(const unsigned int symmetric,
553  const unsigned int n_levels,
554  const double threshold,
555  const double filter,
556  const bool output_details)
557  :
558  symmetric(symmetric),
559  n_levels(n_levels),
560  threshold(threshold),
561  filter(filter),
562  output_details(output_details)
563  {}
564 
565 
566 
569  {
571  }
572 
573 
574  void
576  const AdditionalData &additional_data_)
577  {
578  clear ();
579 
580  matrix = static_cast<Mat>(matrix_);
581  additional_data = additional_data_;
582 
583 #ifdef DEAL_II_PETSC_WITH_HYPRE
584  create_pc();
585 
586  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCHYPRE));
587  AssertThrow (ierr == 0, ExcPETScError(ierr));
588 
589  ierr = PCHYPRESetType(pc, "parasails");
590  AssertThrow (ierr == 0, ExcPETScError(ierr));
591 
593  {
594  set_option_value("-pc_hypre_parasails_logging","1");
595  }
596 
598  additional_data.symmetric == 1 ||
600  ExcMessage("ParaSails parameter symmetric can only be equal to 0, 1, 2!"));
601 
602  std::stringstream ssStream;
603 
604  switch (additional_data.symmetric)
605  {
606  case 0:
607  {
608  ssStream << "nonsymmetric";
609  break;
610  }
611 
612  case 1:
613  {
614  ssStream << "SPD";
615  break;
616  }
617 
618  case 2:
619  {
620  ssStream << "nonsymmetric,SPD";
621  break;
622  }
623 
624  default:
625  Assert (false,
626  ExcMessage("ParaSails parameter symmetric can only be equal to 0, 1, 2!"));
627  };
628 
629  set_option_value("-pc_hypre_parasails_sym",ssStream.str());
630 
631  set_option_value ("-pc_hypre_parasails_nlevels",
633 
634  ssStream.str(""); // empty the stringstream
635  ssStream << additional_data.threshold;
636  set_option_value("-pc_hypre_parasails_thresh", ssStream.str());
637 
638  ssStream.str(""); // empty the stringstream
639  ssStream << additional_data.filter;
640  set_option_value("-pc_hypre_parasails_filter", ssStream.str());
641 
642  ierr = PCSetFromOptions (pc);
643  AssertThrow (ierr == 0, ExcPETScError(ierr));
644 
645  ierr = PCSetUp (pc);
646  AssertThrow (ierr == 0, ExcPETScError(ierr));
647 
648 #else // DEAL_II_PETSC_WITH_HYPRE
649  (void)pc;
650  Assert (false,
651  ExcMessage ("Your PETSc installation does not include a copy of "
652  "the hypre package necessary for this preconditioner."));
653 #endif
654  }
655 
656 
657  /* ----------------- PreconditionNone ------------------------- */
658 
661  {
663  }
664 
665 
666  void
668  const AdditionalData &additional_data_)
669  {
670  clear ();
671 
672  matrix = static_cast<Mat>(matrix_);
673  additional_data = additional_data_;
674 
675  create_pc();
676 
677  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCNONE));
678  AssertThrow (ierr == 0, ExcPETScError(ierr));
679 
680  ierr = PCSetFromOptions (pc);
681  AssertThrow (ierr == 0, ExcPETScError(ierr));
682 
683  ierr = PCSetUp (pc);
684  AssertThrow (ierr == 0, ExcPETScError(ierr));
685  }
686 
687 
688  /* ----------------- PreconditionLU -------------------- */
689 
691  AdditionalData (const double pivoting,
692  const double zero_pivot,
693  const double damping)
694  :
695  pivoting (pivoting),
696  zero_pivot (zero_pivot),
697  damping (damping)
698  {}
699 
700 
701 
704  {
706  }
707 
708 
709  void
711  const AdditionalData &additional_data_)
712  {
713  clear ();
714 
715  matrix = static_cast<Mat>(matrix_);
716  additional_data = additional_data_;
717 
718  create_pc();
719 
720  PetscErrorCode ierr = PCSetType (pc, const_cast<char *>(PCLU));
721  AssertThrow (ierr == 0, ExcPETScError(ierr));
722 
723  // set flags as given
724  ierr = PCFactorSetColumnPivot (pc, additional_data.pivoting);
725  AssertThrow (ierr == 0, ExcPETScError(ierr));
726 
727  ierr = PCFactorSetZeroPivot (pc, additional_data.zero_pivot);
728  AssertThrow (ierr == 0, ExcPETScError(ierr));
729 
730  ierr = PCFactorSetShiftAmount (pc, additional_data.damping);
731  AssertThrow (ierr == 0, ExcPETScError(ierr));
732 
733  ierr = PCSetFromOptions (pc);
734  AssertThrow (ierr == 0, ExcPETScError(ierr));
735 
736  ierr = PCSetUp (pc);
737  AssertThrow (ierr == 0, ExcPETScError(ierr));
738  }
739 
740 }
741 
742 DEAL_II_NAMESPACE_CLOSE
743 
744 #endif // DEAL_II_WITH_PETSC
void vmult(VectorBase &dst, const VectorBase &src) const
AdditionalData(const double pivoting=1.e-6, const double zero_pivot=1.e-12, const double damping=0.0)
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:107
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
void set_option_value(const std::string &name, const std::string &value)
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
static ::ExceptionBase & ExcInvalidState()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1142
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
AdditionalData(const unsigned int symmetric=1, const unsigned int n_levels=1, const double threshold=0.1, const double filter=0.05, const bool output_details=false)
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
AdditionalData(const bool symmetric_operator=false, const double strong_threshold=0.25, const double max_row_sum=0.9, const unsigned int aggressive_coarsening_num_levels=0, const bool output_details=false)