Reference documentation for deal.II version 9.3.3
\(\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\}}\)
petsc_precondition.cc
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 2004 - 2021 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.md at
12// the top level directory of deal.II.
13//
14// ---------------------------------------------------------------------
15
17
18#ifdef DEAL_II_WITH_PETSC
19
21
27
28# include <petscconf.h>
29
30# include <cmath>
31
33
34namespace PETScWrappers
35{
37 : pc(nullptr)
38 , matrix(nullptr)
39 {}
40
42 {
43 try
44 {
45 clear();
46 }
47 catch (...)
48 {}
49 }
50
51 void
53 {
54 matrix = nullptr;
55
56 if (pc != nullptr)
57 {
58 PetscErrorCode ierr = PCDestroy(&pc);
59 pc = nullptr;
60 AssertThrow(ierr == 0, ExcPETScError(ierr));
61 }
62 }
63
64
65 void
67 {
69
70 const PetscErrorCode ierr = PCApply(pc, src, dst);
71 AssertThrow(ierr == 0, ExcPETScError(ierr));
72 }
73
74
75 void
77 {
79
80 const PetscErrorCode ierr = PCApplyTranspose(pc, src, dst);
81 AssertThrow(ierr == 0, ExcPETScError(ierr));
82 }
83
84
85 void
87 {
88 // only allow the creation of the
89 // preconditioner once
91
93 // this ugly cast is necessary because the
94 // type Mat and PETScObject are
95 // unrelated.
96 PetscErrorCode ierr =
97 PetscObjectGetComm(reinterpret_cast<PetscObject>(matrix), &comm);
98 AssertThrow(ierr == 0, ExcPETScError(ierr));
99
100 ierr = PCCreate(comm, &pc);
101 AssertThrow(ierr == 0, ExcPETScError(ierr));
102
103# if DEAL_II_PETSC_VERSION_LT(3, 5, 0)
104 ierr = PCSetOperators(pc, matrix, matrix, SAME_PRECONDITIONER);
105# else
106 ierr = PCSetOperators(pc, matrix, matrix);
107# endif
108 AssertThrow(ierr == 0, ExcPETScError(ierr));
109 }
110
111
112 const PC &
114 {
115 return pc;
116 }
117
118
119 PreconditionBase::operator Mat() const
120 {
121 return matrix;
122 }
123
124
125 /* ----------------- PreconditionJacobi -------------------- */
127 const AdditionalData &additional_data_)
128 {
129 additional_data = additional_data_;
130
131 PetscErrorCode ierr = PCCreate(comm, &pc);
132 AssertThrow(ierr == 0, ExcPETScError(ierr));
133
134 initialize();
135 }
136
137
138
140 const AdditionalData &additional_data)
141 {
143 }
144
145 void
147 {
149
150 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCJACOBI));
151 AssertThrow(ierr == 0, ExcPETScError(ierr));
152
153 ierr = PCSetFromOptions(pc);
154 AssertThrow(ierr == 0, ExcPETScError(ierr));
155 }
156
157 void
159 const AdditionalData &additional_data_)
160 {
161 clear();
162
163 matrix = static_cast<Mat>(matrix_);
164 additional_data = additional_data_;
165
166 create_pc();
167 initialize();
168
169 PetscErrorCode ierr = PCSetUp(pc);
170 AssertThrow(ierr == 0, ExcPETScError(ierr));
171 }
172
173
174 /* ----------------- PreconditionBlockJacobi -------------------- */
176 const MPI_Comm & comm,
177 const AdditionalData &additional_data_)
178 {
179 additional_data = additional_data_;
180
181 PetscErrorCode ierr = PCCreate(comm, &pc);
182 AssertThrow(ierr == 0, ExcPETScError(ierr));
183
184 initialize();
185 }
186
187
188
190 const MatrixBase & matrix,
191 const AdditionalData &additional_data)
192 {
194 }
195
196 void
198 {
199 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCBJACOBI));
200 AssertThrow(ierr == 0, ExcPETScError(ierr));
201
202 ierr = PCSetFromOptions(pc);
203 AssertThrow(ierr == 0, ExcPETScError(ierr));
204 }
205
206
207 void
209 const AdditionalData &additional_data_)
210 {
211 clear();
212
213 matrix = static_cast<Mat>(matrix_);
214 additional_data = additional_data_;
215
216 create_pc();
217 initialize();
218
219 PetscErrorCode ierr = PCSetUp(pc);
220 AssertThrow(ierr == 0, ExcPETScError(ierr));
221 }
222
223
224 /* ----------------- PreconditionSOR -------------------- */
225
227 : omega(omega)
228 {}
229
230
231
234 {
236 }
237
238
239 void
241 const AdditionalData &additional_data_)
242 {
243 clear();
244
245 matrix = static_cast<Mat>(matrix_);
246 additional_data = additional_data_;
247
248 create_pc();
249
250 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCSOR));
251 AssertThrow(ierr == 0, ExcPETScError(ierr));
252
253 // then set flags as given
254 ierr = PCSORSetOmega(pc, additional_data.omega);
255 AssertThrow(ierr == 0, ExcPETScError(ierr));
256
257 ierr = PCSetFromOptions(pc);
258 AssertThrow(ierr == 0, ExcPETScError(ierr));
259
260 ierr = PCSetUp(pc);
261 AssertThrow(ierr == 0, ExcPETScError(ierr));
262 }
263
264
265 /* ----------------- PreconditionSSOR -------------------- */
266
268 : omega(omega)
269 {}
270
271
272
275 {
277 }
278
279
280 void
282 const AdditionalData &additional_data_)
283 {
284 clear();
285
286 matrix = static_cast<Mat>(matrix_);
287 additional_data = additional_data_;
288
289 create_pc();
290
291 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCSOR));
292 AssertThrow(ierr == 0, ExcPETScError(ierr));
293
294 // then set flags as given
295 ierr = PCSORSetOmega(pc, additional_data.omega);
296 AssertThrow(ierr == 0, ExcPETScError(ierr));
297
298 // convert SOR to SSOR
299 ierr = PCSORSetSymmetric(pc, SOR_SYMMETRIC_SWEEP);
300 AssertThrow(ierr == 0, ExcPETScError(ierr));
301
302 ierr = PCSetFromOptions(pc);
303 AssertThrow(ierr == 0, ExcPETScError(ierr));
304
305 ierr = PCSetUp(pc);
306 AssertThrow(ierr == 0, ExcPETScError(ierr));
307 }
308
309
310 /* ----------------- PreconditionEisenstat -------------------- */
311
313 : omega(omega)
314 {}
315
316
317
319 const MatrixBase & matrix,
321 {
323 }
324
325
326 void
328 const AdditionalData &additional_data_)
329 {
330 clear();
331
332 matrix = static_cast<Mat>(matrix_);
333 additional_data = additional_data_;
334
335 create_pc();
336
337 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCEISENSTAT));
338 AssertThrow(ierr == 0, ExcPETScError(ierr));
339
340 // then set flags as given
341 ierr = PCEisenstatSetOmega(pc, additional_data.omega);
342 AssertThrow(ierr == 0, ExcPETScError(ierr));
343
344 ierr = PCSetFromOptions(pc);
345 AssertThrow(ierr == 0, ExcPETScError(ierr));
346
347 ierr = PCSetUp(pc);
348 AssertThrow(ierr == 0, ExcPETScError(ierr));
349 }
350
351
352 /* ----------------- PreconditionICC -------------------- */
353
354
356 : levels(levels)
357 {}
358
359
360
363 {
365 }
366
367
368 void
370 const AdditionalData &additional_data_)
371 {
372 clear();
373
374 matrix = static_cast<Mat>(matrix_);
375 additional_data = additional_data_;
376
377 create_pc();
378
379 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCICC));
380 AssertThrow(ierr == 0, ExcPETScError(ierr));
381
382 // then set flags
383 ierr = PCFactorSetLevels(pc, additional_data.levels);
384 AssertThrow(ierr == 0, ExcPETScError(ierr));
385
386 ierr = PCSetFromOptions(pc);
387 AssertThrow(ierr == 0, ExcPETScError(ierr));
388
389 ierr = PCSetUp(pc);
390 AssertThrow(ierr == 0, ExcPETScError(ierr));
391 }
392
393
394 /* ----------------- PreconditionILU -------------------- */
395
397 : levels(levels)
398 {}
399
400
401
404 {
406 }
407
408
409 void
411 const AdditionalData &additional_data_)
412 {
413 clear();
414
415 matrix = static_cast<Mat>(matrix_);
416 additional_data = additional_data_;
417
418 create_pc();
419
420 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCILU));
421 AssertThrow(ierr == 0, ExcPETScError(ierr));
422
423 // then set flags
424 ierr = PCFactorSetLevels(pc, additional_data.levels);
425 AssertThrow(ierr == 0, ExcPETScError(ierr));
426
427 ierr = PCSetFromOptions(pc);
428 AssertThrow(ierr == 0, ExcPETScError(ierr));
429
430 ierr = PCSetUp(pc);
431 AssertThrow(ierr == 0, ExcPETScError(ierr));
432 }
433
434
435 /* ----------------- PreconditionBoomerAMG -------------------- */
436
438 const bool symmetric_operator,
439 const double strong_threshold,
440 const double max_row_sum,
441 const unsigned int aggressive_coarsening_num_levels,
442 const bool output_details,
443 const RelaxationType relaxation_type_up,
444 const RelaxationType relaxation_type_down,
445 const RelaxationType relaxation_type_coarse,
446 const unsigned int n_sweeps_coarse,
447 const double tol,
448 const unsigned int max_iter,
449 const bool w_cycle)
450 : symmetric_operator(symmetric_operator)
451 , strong_threshold(strong_threshold)
452 , max_row_sum(max_row_sum)
453 , aggressive_coarsening_num_levels(aggressive_coarsening_num_levels)
454 , output_details(output_details)
455 , relaxation_type_up(relaxation_type_up)
456 , relaxation_type_down(relaxation_type_down)
457 , relaxation_type_coarse(relaxation_type_coarse)
458 , n_sweeps_coarse(n_sweeps_coarse)
459 , tol(tol)
460 , max_iter(max_iter)
461 , w_cycle(w_cycle)
462 {}
463
464
465
466# ifdef DEAL_II_PETSC_WITH_HYPRE
467 namespace
468 {
473 std::string
474 to_string(
476 {
477 std::string string_type;
478
479 switch (relaxation_type)
480 {
482 string_type = "Jacobi";
483 break;
486 string_type = "sequential-Gauss-Seidel";
487 break;
490 string_type = "seqboundary-Gauss-Seidel";
491 break;
493 string_type = "SOR/Jacobi";
494 break;
497 string_type = "backward-SOR/Jacobi";
498 break;
501 string_type = "symmetric-SOR/Jacobi";
502 break;
505 string_type = " l1scaled-SOR/Jacobi";
506 break;
509 string_type = "Gaussian-elimination";
510 break;
513 string_type = "l1-Gauss-Seidel";
514 break;
517 string_type = "backward-l1-Gauss-Seidel";
518 break;
520 string_type = "CG";
521 break;
523 string_type = "Chebyshev";
524 break;
526 string_type = "FCF-Jacobi";
527 break;
530 string_type = "l1scaled-Jacobi";
531 break;
533 string_type = "None";
534 break;
535 default:
536 Assert(false, ExcNotImplemented());
537 }
538 return string_type;
539 }
540 } // namespace
541# endif
542
544 const MPI_Comm & comm,
545 const AdditionalData &additional_data_)
546 {
547 additional_data = additional_data_;
548
549 PetscErrorCode ierr = PCCreate(comm, &pc);
550 AssertThrow(ierr == 0, ExcPETScError(ierr));
551
552# ifdef DEAL_II_PETSC_WITH_HYPRE
553 initialize();
554# else // DEAL_II_PETSC_WITH_HYPRE
555 (void)pc;
556 Assert(false,
557 ExcMessage("Your PETSc installation does not include a copy of "
558 "the hypre package necessary for this preconditioner."));
559# endif
560 }
561
562
564 const MatrixBase & matrix,
566 {
568 }
569
570 void
572 {
573# ifdef DEAL_II_PETSC_WITH_HYPRE
574 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCHYPRE));
575 AssertThrow(ierr == 0, ExcPETScError(ierr));
576
577 ierr = PCHYPRESetType(pc, "boomeramg");
578 AssertThrow(ierr == 0, ExcPETScError(ierr));
579
581 {
582 set_option_value("-pc_hypre_boomeramg_print_statistics", "1");
583 }
584
585 set_option_value("-pc_hypre_boomeramg_agg_nl",
588
589 set_option_value("-pc_hypre_boomeramg_max_row_sum",
591
592 set_option_value("-pc_hypre_boomeramg_strong_threshold",
594
595 // change to symmetric SOR/Jacobi when using a symmetric operator for
596 // backward compatibility
600 {
603 }
604
608 {
611 }
612
616 {
619 }
620
621 auto relaxation_type_is_symmetric =
622 [](AdditionalData::RelaxationType relaxation_type) {
623 return relaxation_type == AdditionalData::RelaxationType::Jacobi ||
624 relaxation_type ==
626 relaxation_type ==
628 relaxation_type == AdditionalData::RelaxationType::None ||
629 relaxation_type ==
631 relaxation_type == AdditionalData::RelaxationType::CG ||
633 };
634
636 !relaxation_type_is_symmetric(additional_data.relaxation_type_up))
637 Assert(false,
638 ExcMessage("Use a symmetric smoother for relaxation_type_up"));
639
641 !relaxation_type_is_symmetric(additional_data.relaxation_type_down))
642 Assert(false,
643 ExcMessage("Use a symmetric smoother for relaxation_type_down"));
644
646 !relaxation_type_is_symmetric(additional_data.relaxation_type_coarse))
647 Assert(false,
648 ExcMessage("Use a symmetric smoother for relaxation_type_coarse"));
649
650 set_option_value("-pc_hypre_boomeramg_relax_type_up",
652 set_option_value("-pc_hypre_boomeramg_relax_type_down",
654 set_option_value("-pc_hypre_boomeramg_relax_type_coarse",
656 set_option_value("-pc_hypre_boomeramg_grid_sweeps_coarse",
658
659 set_option_value("-pc_hypre_boomeramg_tol",
661 set_option_value("-pc_hypre_boomeramg_max_iter",
663
665 {
666 set_option_value("-pc_hypre_boomeramg_cycle_type", "W");
667 }
668
669 ierr = PCSetFromOptions(pc);
670 AssertThrow(ierr == 0, ExcPETScError(ierr));
671# else
672 Assert(false,
673 ExcMessage("Your PETSc installation does not include a copy of "
674 "the hypre package necessary for this preconditioner."));
675# endif
676 }
677
678 void
680 const AdditionalData &additional_data_)
681 {
682# ifdef DEAL_II_PETSC_WITH_HYPRE
683 clear();
684
685 matrix = static_cast<Mat>(matrix_);
686 additional_data = additional_data_;
687
688 create_pc();
689 initialize();
690
691 PetscErrorCode ierr = PCSetUp(pc);
692 AssertThrow(ierr == 0, ExcPETScError(ierr));
693
694# else // DEAL_II_PETSC_WITH_HYPRE
695 (void)matrix_;
696 (void)additional_data_;
697 Assert(false,
698 ExcMessage("Your PETSc installation does not include a copy of "
699 "the hypre package necessary for this preconditioner."));
700# endif
701 }
702
703
704 /* ----------------- PreconditionParaSails -------------------- */
705
707 const unsigned int symmetric,
708 const unsigned int n_levels,
709 const double threshold,
710 const double filter,
711 const bool output_details)
713 , n_levels(n_levels)
714 , threshold(threshold)
715 , filter(filter)
716 , output_details(output_details)
717 {}
718
719
720
722 const MatrixBase & matrix,
724 {
726 }
727
728
729 void
731 const AdditionalData &additional_data_)
732 {
733 clear();
734
735 matrix = static_cast<Mat>(matrix_);
736 additional_data = additional_data_;
737
738# ifdef DEAL_II_PETSC_WITH_HYPRE
739 create_pc();
740
741 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCHYPRE));
742 AssertThrow(ierr == 0, ExcPETScError(ierr));
743
744 ierr = PCHYPRESetType(pc, "parasails");
745 AssertThrow(ierr == 0, ExcPETScError(ierr));
746
748 {
749 set_option_value("-pc_hypre_parasails_logging", "1");
750 }
751
755 "ParaSails parameter symmetric can only be equal to 0, 1, 2!"));
756
757 std::stringstream ssStream;
758
760 {
761 case 0:
762 {
763 ssStream << "nonsymmetric";
764 break;
765 }
766
767 case 1:
768 {
769 ssStream << "SPD";
770 break;
771 }
772
773 case 2:
774 {
775 ssStream << "nonsymmetric,SPD";
776 break;
777 }
778
779 default:
780 Assert(
781 false,
783 "ParaSails parameter symmetric can only be equal to 0, 1, 2!"));
784 }
785
786 set_option_value("-pc_hypre_parasails_sym", ssStream.str());
787
788 set_option_value("-pc_hypre_parasails_nlevels",
790
791 ssStream.str(""); // empty the stringstream
792 ssStream << additional_data.threshold;
793 set_option_value("-pc_hypre_parasails_thresh", ssStream.str());
794
795 ssStream.str(""); // empty the stringstream
796 ssStream << additional_data.filter;
797 set_option_value("-pc_hypre_parasails_filter", ssStream.str());
798
799 ierr = PCSetFromOptions(pc);
800 AssertThrow(ierr == 0, ExcPETScError(ierr));
801
802 ierr = PCSetUp(pc);
803 AssertThrow(ierr == 0, ExcPETScError(ierr));
804
805# else // DEAL_II_PETSC_WITH_HYPRE
806 (void)pc;
807 Assert(false,
808 ExcMessage("Your PETSc installation does not include a copy of "
809 "the hypre package necessary for this preconditioner."));
810# endif
811 }
812
813
814 /* ----------------- PreconditionNone ------------------------- */
815
818 {
820 }
821
822
823 void
825 const AdditionalData &additional_data_)
826 {
827 clear();
828
829 matrix = static_cast<Mat>(matrix_);
830 additional_data = additional_data_;
831
832 create_pc();
833
834 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCNONE));
835 AssertThrow(ierr == 0, ExcPETScError(ierr));
836
837 ierr = PCSetFromOptions(pc);
838 AssertThrow(ierr == 0, ExcPETScError(ierr));
839
840 ierr = PCSetUp(pc);
841 AssertThrow(ierr == 0, ExcPETScError(ierr));
842 }
843
844
845 /* ----------------- PreconditionLU -------------------- */
846
848 const double zero_pivot,
849 const double damping)
850 : pivoting(pivoting)
851 , zero_pivot(zero_pivot)
852 , damping(damping)
853 {}
854
855
856
859 {
861 }
862
863
864 void
866 const AdditionalData &additional_data_)
867 {
868 clear();
869
870 matrix = static_cast<Mat>(matrix_);
871 additional_data = additional_data_;
872
873 create_pc();
874
875 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCLU));
876 AssertThrow(ierr == 0, ExcPETScError(ierr));
877
878 // set flags as given
879 ierr = PCFactorSetColumnPivot(pc, additional_data.pivoting);
880 AssertThrow(ierr == 0, ExcPETScError(ierr));
881
882 ierr = PCFactorSetZeroPivot(pc, additional_data.zero_pivot);
883 AssertThrow(ierr == 0, ExcPETScError(ierr));
884
885 ierr = PCFactorSetShiftAmount(pc, additional_data.damping);
886 AssertThrow(ierr == 0, ExcPETScError(ierr));
887
888 ierr = PCSetFromOptions(pc);
889 AssertThrow(ierr == 0, ExcPETScError(ierr));
890
891 ierr = PCSetUp(pc);
892 AssertThrow(ierr == 0, ExcPETScError(ierr));
893 }
894
895} // namespace PETScWrappers
896
898
899#endif // DEAL_II_WITH_PETSC
void Tvmult(VectorBase &dst, const VectorBase &src) const
void vmult(VectorBase &dst, const VectorBase &src) const
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())
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())
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
void initialize(const MatrixBase &matrix, const AdditionalData &additional_data=AdditionalData())
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
Definition: exceptions.h:1465
std::string to_string(const T &t)
Definition: patterns.h:2329
static ::ExceptionBase & ExcInvalidState()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1575
@ matrix
Contents is actually a matrix.
@ symmetric
Matrix is symmetric.
void set_option_value(const std::string &name, const std::string &value)
*braid_SplitCommworld & comm
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, const RelaxationType relaxation_type_up=RelaxationType::SORJacobi, const RelaxationType relaxation_type_down=RelaxationType::SORJacobi, const RelaxationType relaxation_type_coarse=RelaxationType::GaussianElimination, const unsigned int n_sweeps_coarse=1, const double tol=0.0, const unsigned int max_iter=1, const bool w_cycle=false)
AdditionalData(const double pivoting=1.e-6, const double zero_pivot=1.e-12, const double damping=0.0)
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)