deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00: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
petsc_precondition.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) 2004 - 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
14
15#ifdef DEAL_II_WITH_PETSC
16
18
24
25# include <petscconf.h>
26
27# include <cmath>
28
29
30#endif // DEAL_II_WITH_PETSC
31
33
34#ifdef DEAL_II_WITH_PETSC
35
36namespace PETScWrappers
37{
43
45 : pc(nullptr)
46 {}
47
49 {
50 try
51 {
52 clear();
53 }
54 catch (...)
55 {}
56 }
57
58 void
60 {
61 if (pc)
62 {
63 PetscErrorCode ierr = PCDestroy(&pc);
64 AssertThrow(ierr == 0, ExcPETScError(ierr));
65 }
66 }
67
68 void
70 {
72
73 PetscErrorCode ierr = PCApply(pc, src, dst);
74 AssertThrow(ierr == 0, ExcPETScError(ierr));
75 }
76
77 void
79 {
81
82 PetscErrorCode ierr = PCApplyTranspose(pc, src, dst);
83 AssertThrow(ierr == 0, ExcPETScError(ierr));
84 }
85
86 void
88 {
90
91 PetscErrorCode ierr = PCSetUp(pc);
92 AssertThrow(ierr == 0, ExcPETScError(ierr));
93 }
94
97 {
98 return PetscObjectComm(reinterpret_cast<PetscObject>(pc));
99 }
100
101 void
103 {
104 // only allow the creation of the
105 // preconditioner once
107
109 PetscErrorCode ierr = PetscObjectGetComm(
110 reinterpret_cast<PetscObject>(static_cast<const Mat &>(matrix)), &comm);
111 AssertThrow(ierr == 0, ExcPETScError(ierr));
112
114
115 ierr = PCSetOperators(pc, matrix, matrix);
116 AssertThrow(ierr == 0, ExcPETScError(ierr));
117 }
118
119 void
121 {
122 clear();
123 PetscErrorCode ierr = PCCreate(comm, &pc);
124 AssertThrow(ierr == 0, ExcPETScError(ierr));
125 }
126
127 const PC &
129 {
130 return pc;
131 }
132
133
134 /* ----------------- PreconditionJacobi -------------------- */
135
139
140
141
143 const AdditionalData &additional_data_)
145 {
146 additional_data = additional_data_;
147
148 PetscErrorCode ierr = PCCreate(comm, &pc);
149 AssertThrow(ierr == 0, ExcPETScError(ierr));
150
151 initialize();
152 }
153
154
155
157 const AdditionalData &additional_data)
158 : PreconditionBase(matrix.get_mpi_communicator())
159 {
161 }
162
163
164
165 void
167 {
169
170 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCJACOBI));
171 AssertThrow(ierr == 0, ExcPETScError(ierr));
172
173 ierr = PCSetFromOptions(pc);
174 AssertThrow(ierr == 0, ExcPETScError(ierr));
175 }
176
177
178
179 void
181 const AdditionalData &additional_data_)
182 {
183 clear();
184
185 additional_data = additional_data_;
186
187 create_pc_with_mat(matrix_);
188 initialize();
189 }
190
191
192 /* ----------------- PreconditionBlockJacobi -------------------- */
193
197
199 const MPI_Comm comm,
200 const AdditionalData &additional_data_)
202 {
203 additional_data = additional_data_;
204
205 PetscErrorCode ierr = PCCreate(comm, &pc);
206 AssertThrow(ierr == 0, ExcPETScError(ierr));
207
208 initialize();
209 }
210
211
212
214 const MatrixBase &matrix,
215 const AdditionalData &additional_data)
216 : PreconditionBase(matrix.get_mpi_communicator())
217 {
219 }
220
221
222
223 void
225 {
226 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCBJACOBI));
227 AssertThrow(ierr == 0, ExcPETScError(ierr));
228
229 ierr = PCSetFromOptions(pc);
230 AssertThrow(ierr == 0, ExcPETScError(ierr));
231 }
232
233
234
235 void
237 const AdditionalData &additional_data_)
238 {
239 clear();
240
241 additional_data = additional_data_;
242
243 create_pc_with_mat(matrix_);
244 initialize();
245 }
246
247
248 /* ----------------- PreconditionSOR -------------------- */
249
253
254
255
257 : omega(omega)
258 {}
259
260
261
268
269
270 void
272 const AdditionalData &additional_data_)
273 {
274 clear();
275
276 additional_data = additional_data_;
277
278 create_pc_with_mat(matrix_);
279
280 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCSOR));
281 AssertThrow(ierr == 0, ExcPETScError(ierr));
282
283 // then set flags as given
284 ierr = PCSORSetOmega(pc, additional_data.omega);
285 AssertThrow(ierr == 0, ExcPETScError(ierr));
286
287 ierr = PCSetFromOptions(pc);
288 AssertThrow(ierr == 0, ExcPETScError(ierr));
289 }
290
291
292 /* ----------------- PreconditionSSOR -------------------- */
293
297
298
299
301 : omega(omega)
302 {}
303
304
305
312
313
314 void
316 const AdditionalData &additional_data_)
317 {
318 clear();
319
320 additional_data = additional_data_;
321
322 create_pc_with_mat(matrix_);
323
324 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCSOR));
325 AssertThrow(ierr == 0, ExcPETScError(ierr));
326
327 // then set flags as given
328 ierr = PCSORSetOmega(pc, additional_data.omega);
329 AssertThrow(ierr == 0, ExcPETScError(ierr));
330
331 // convert SOR to SSOR
332 ierr = PCSORSetSymmetric(pc, SOR_SYMMETRIC_SWEEP);
333 AssertThrow(ierr == 0, ExcPETScError(ierr));
334
335 ierr = PCSetFromOptions(pc);
336 AssertThrow(ierr == 0, ExcPETScError(ierr));
337 }
338
339
340 /* ----------------- PreconditionICC -------------------- */
341
345
346
347
349 : levels(levels)
350 {}
351
352
353
360
361
362 void
364 const AdditionalData &additional_data_)
365 {
366 clear();
367
368 additional_data = additional_data_;
369
370 create_pc_with_mat(matrix_);
371
372 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCICC));
373 AssertThrow(ierr == 0, ExcPETScError(ierr));
374
375 // then set flags
376 ierr = PCFactorSetLevels(pc, additional_data.levels);
377 AssertThrow(ierr == 0, ExcPETScError(ierr));
378
379 ierr = PCSetFromOptions(pc);
380 AssertThrow(ierr == 0, ExcPETScError(ierr));
381 }
382
383
384 /* ----------------- PreconditionILU -------------------- */
385
389
390
391
393 : levels(levels)
394 {}
395
396
397
404
405
406 void
408 const AdditionalData &additional_data_)
409 {
410 clear();
411
412 additional_data = additional_data_;
413
414 create_pc_with_mat(matrix_);
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
427
428 /* ----------------- PreconditionBoomerAMG -------------------- */
429
431 const bool symmetric_operator,
432 const double strong_threshold,
433 const double max_row_sum,
434 const unsigned int aggressive_coarsening_num_levels,
435 const bool output_details,
436 const RelaxationType relaxation_type_up,
437 const RelaxationType relaxation_type_down,
438 const RelaxationType relaxation_type_coarse,
439 const unsigned int n_sweeps_coarse,
440 const double tol,
441 const unsigned int max_iter,
442 const bool w_cycle)
443 : symmetric_operator(symmetric_operator)
444 , strong_threshold(strong_threshold)
445 , max_row_sum(max_row_sum)
446 , aggressive_coarsening_num_levels(aggressive_coarsening_num_levels)
447 , output_details(output_details)
448 , relaxation_type_up(relaxation_type_up)
449 , relaxation_type_down(relaxation_type_down)
450 , relaxation_type_coarse(relaxation_type_coarse)
451 , n_sweeps_coarse(n_sweeps_coarse)
452 , tol(tol)
453 , max_iter(max_iter)
454 , w_cycle(w_cycle)
455 {}
456
457
458
459# ifdef DEAL_II_PETSC_WITH_HYPRE
460 namespace
461 {
466 std::string
467 to_string(
469 {
470 std::string string_type;
471
472 switch (relaxation_type)
473 {
475 string_type = "Jacobi";
476 break;
479 string_type = "sequential-Gauss-Seidel";
480 break;
483 string_type = "seqboundary-Gauss-Seidel";
484 break;
486 string_type = "SOR/Jacobi";
487 break;
490 string_type = "backward-SOR/Jacobi";
491 break;
494 string_type = "symmetric-SOR/Jacobi";
495 break;
498 string_type = " l1scaled-SOR/Jacobi";
499 break;
502 string_type = "Gaussian-elimination";
503 break;
506 string_type = "l1-Gauss-Seidel";
507 break;
510 string_type = "backward-l1-Gauss-Seidel";
511 break;
513 string_type = "CG";
514 break;
516 string_type = "Chebyshev";
517 break;
519 string_type = "FCF-Jacobi";
520 break;
523 string_type = "l1scaled-Jacobi";
524 break;
526 string_type = "None";
527 break;
528 default:
530 }
531 return string_type;
532 }
533 } // namespace
534# endif
535
536
537
541
542
543
545 const MPI_Comm comm,
546 const AdditionalData &additional_data_)
548 {
549 additional_data = additional_data_;
550
551 PetscErrorCode ierr = PCCreate(comm, &pc);
552 AssertThrow(ierr == 0, ExcPETScError(ierr));
553
554# ifdef DEAL_II_PETSC_WITH_HYPRE
555 initialize();
556# else // DEAL_II_PETSC_WITH_HYPRE
557 Assert(false,
558 ExcMessage("Your PETSc installation does not include a copy of "
559 "the hypre package necessary for this preconditioner."));
560# endif
561 }
562
563
564
566 const MatrixBase &matrix,
567 const AdditionalData &additional_data)
568 : PreconditionBase(matrix.get_mpi_communicator())
569 {
571 }
572
573
574
575 void
577 {
578# ifdef DEAL_II_PETSC_WITH_HYPRE
579 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCHYPRE));
580 AssertThrow(ierr == 0, ExcPETScError(ierr));
581
582 ierr = PCHYPRESetType(pc, "boomeramg");
583 AssertThrow(ierr == 0, ExcPETScError(ierr));
584
586 {
587 set_option_value("-pc_hypre_boomeramg_print_statistics", "1");
588 }
589
590 set_option_value("-pc_hypre_boomeramg_agg_nl",
591 std::to_string(
593
594 set_option_value("-pc_hypre_boomeramg_max_row_sum",
595 std::to_string(additional_data.max_row_sum));
596
597 set_option_value("-pc_hypre_boomeramg_strong_threshold",
598 std::to_string(additional_data.strong_threshold));
599
600 // change to symmetric SOR/Jacobi when using a symmetric operator for
601 // backward compatibility
605 {
608 }
609
613 {
616 }
617
621 {
624 }
625
626 auto relaxation_type_is_symmetric =
627 [](AdditionalData::RelaxationType relaxation_type) {
628 return relaxation_type == AdditionalData::RelaxationType::Jacobi ||
629 relaxation_type ==
631 relaxation_type ==
633 relaxation_type == AdditionalData::RelaxationType::None ||
634 relaxation_type ==
636 relaxation_type == AdditionalData::RelaxationType::CG ||
638 };
639
641 !relaxation_type_is_symmetric(additional_data.relaxation_type_up))
642 Assert(false,
643 ExcMessage("Use a symmetric smoother for relaxation_type_up"));
644
646 !relaxation_type_is_symmetric(additional_data.relaxation_type_down))
647 Assert(false,
648 ExcMessage("Use a symmetric smoother for relaxation_type_down"));
649
651 !relaxation_type_is_symmetric(additional_data.relaxation_type_coarse))
652 Assert(false,
653 ExcMessage("Use a symmetric smoother for relaxation_type_coarse"));
654
655 set_option_value("-pc_hypre_boomeramg_relax_type_up",
657 set_option_value("-pc_hypre_boomeramg_relax_type_down",
659 set_option_value("-pc_hypre_boomeramg_relax_type_coarse",
661 set_option_value("-pc_hypre_boomeramg_grid_sweeps_coarse",
662 std::to_string(additional_data.n_sweeps_coarse));
663
664 set_option_value("-pc_hypre_boomeramg_tol",
665 std::to_string(additional_data.tol));
666 set_option_value("-pc_hypre_boomeramg_max_iter",
667 std::to_string(additional_data.max_iter));
668
670 {
671 set_option_value("-pc_hypre_boomeramg_cycle_type", "W");
672 }
673
674 ierr = PCSetFromOptions(pc);
675 AssertThrow(ierr == 0, ExcPETScError(ierr));
676# else
677 Assert(false,
678 ExcMessage("Your PETSc installation does not include a copy of "
679 "the hypre package necessary for this preconditioner."));
680# endif
681 }
682
683
684
685 void
687 const AdditionalData &additional_data_)
688 {
689# ifdef DEAL_II_PETSC_WITH_HYPRE
690 clear();
691
692 additional_data = additional_data_;
693
694 create_pc_with_mat(matrix_);
695 initialize();
696
697# else // DEAL_II_PETSC_WITH_HYPRE
698 (void)matrix_;
699 (void)additional_data_;
700 Assert(false,
701 ExcMessage("Your PETSc installation does not include a copy of "
702 "the hypre package necessary for this preconditioner."));
703# endif
704 }
705
706
707 /* ----------------- PreconditionParaSails -------------------- */
708
710 const unsigned int symmetric,
711 const unsigned int n_levels,
712 const double threshold,
713 const double filter,
714 const bool output_details)
715 : symmetric(symmetric)
716 , n_levels(n_levels)
717 , threshold(threshold)
718 , filter(filter)
719 , output_details(output_details)
720 {}
721
722
723
727
728
729
731 const MatrixBase &matrix,
732 const AdditionalData &additional_data)
733 : PreconditionBase(matrix.get_mpi_communicator())
734 {
736 }
737
738
739 void
741 const AdditionalData &additional_data_)
742 {
743 clear();
744
745 additional_data = additional_data_;
746
747# ifdef DEAL_II_PETSC_WITH_HYPRE
748 create_pc_with_mat(matrix_);
749
750 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCHYPRE));
751 AssertThrow(ierr == 0, ExcPETScError(ierr));
752
753 ierr = PCHYPRESetType(pc, "parasails");
754 AssertThrow(ierr == 0, ExcPETScError(ierr));
755
757 {
758 set_option_value("-pc_hypre_parasails_logging", "1");
759 }
760
764 "ParaSails parameter symmetric can only be equal to 0, 1, 2!"));
765
766 std::stringstream ssStream;
767
769 {
770 case 0:
771 {
772 ssStream << "nonsymmetric";
773 break;
774 }
775
776 case 1:
777 {
778 ssStream << "SPD";
779 break;
780 }
781
782 case 2:
783 {
784 ssStream << "nonsymmetric,SPD";
785 break;
786 }
787
788 default:
789 Assert(
790 false,
792 "ParaSails parameter symmetric can only be equal to 0, 1, 2!"));
793 }
794
795 set_option_value("-pc_hypre_parasails_sym", ssStream.str());
796
797 set_option_value("-pc_hypre_parasails_nlevels",
798 std::to_string(additional_data.n_levels));
799
800 ssStream.str(""); // empty the stringstream
801 ssStream << additional_data.threshold;
802 set_option_value("-pc_hypre_parasails_thresh", ssStream.str());
803
804 ssStream.str(""); // empty the stringstream
805 ssStream << additional_data.filter;
806 set_option_value("-pc_hypre_parasails_filter", ssStream.str());
807
808 ierr = PCSetFromOptions(pc);
809 AssertThrow(ierr == 0, ExcPETScError(ierr));
810
811# else // DEAL_II_PETSC_WITH_HYPRE
812 (void)matrix_;
813 Assert(false,
814 ExcMessage("Your PETSc installation does not include a copy of "
815 "the hypre package necessary for this preconditioner."));
816# endif
817 }
818
819
820 /* ----------------- PreconditionNone ------------------------- */
821
825
826
827
829 const AdditionalData &additional_data)
830 : PreconditionBase(matrix.get_mpi_communicator())
831 {
833 }
834
835
836 void
838 const AdditionalData &additional_data_)
839 {
840 clear();
841
842 additional_data = additional_data_;
843
844 create_pc_with_mat(matrix_);
845
846 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCNONE));
847 AssertThrow(ierr == 0, ExcPETScError(ierr));
848
849 ierr = PCSetFromOptions(pc);
850 AssertThrow(ierr == 0, ExcPETScError(ierr));
851 }
852
853
854 /* ----------------- PreconditionLU -------------------- */
855
857 const double zero_pivot,
858 const double damping)
859 : pivoting(pivoting)
860 , zero_pivot(zero_pivot)
861 , damping(damping)
862 {}
863
864
865
869
870
871
873 const AdditionalData &additional_data)
874 : PreconditionBase(matrix.get_mpi_communicator())
875 {
877 }
878
879
880 void
882 const AdditionalData &additional_data_)
883 {
884 clear();
885
886 additional_data = additional_data_;
887
888 create_pc_with_mat(matrix_);
889
890 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCLU));
891 AssertThrow(ierr == 0, ExcPETScError(ierr));
892
893 // set flags as given
894 ierr = PCFactorSetColumnPivot(pc, additional_data.pivoting);
895 AssertThrow(ierr == 0, ExcPETScError(ierr));
896
897 ierr = PCFactorSetZeroPivot(pc, additional_data.zero_pivot);
898 AssertThrow(ierr == 0, ExcPETScError(ierr));
899
900 ierr = PCFactorSetShiftAmount(pc, additional_data.damping);
901 AssertThrow(ierr == 0, ExcPETScError(ierr));
902
903 ierr = PCSetFromOptions(pc);
904 AssertThrow(ierr == 0, ExcPETScError(ierr));
905 }
906
907 /* ----------------- PreconditionBDDC -------------------- */
908
909 template <int dim>
911 const bool use_vertices,
912 const bool use_edges,
913 const bool use_faces,
914 const bool symmetric,
915 const std::vector<Point<dim>> coords)
916 : use_vertices(use_vertices)
917 , use_edges(use_edges)
918 , use_faces(use_faces)
919 , symmetric(symmetric)
920 , coords(coords)
921 {}
922
923
924
925 template <int dim>
929
930
931
932 template <int dim>
934 const MPI_Comm comm,
935 const AdditionalData &additional_data_)
937 {
938 additional_data = additional_data_;
939
940 PetscErrorCode ierr = PCCreate(comm, &pc);
941 AssertThrow(ierr == 0, ExcPETScError(ierr));
942
943 initialize();
944 }
945
946
947
948 template <int dim>
950 const AdditionalData &additional_data)
951 : PreconditionBase(matrix.get_mpi_communicator())
952 {
954 }
955
956
957
958 template <int dim>
959 void
961 {
962# if DEAL_II_PETSC_VERSION_GTE(3, 10, 0)
963 PetscErrorCode ierr = PCSetType(pc, const_cast<char *>(PCBDDC));
964 AssertThrow(ierr == 0, ExcPETScError(ierr));
965
966 // The matrix must be of IS type. We check for this to avoid the PETSc error
967 // in order to suggest the correct matrix reinit method.
968 {
969 MatType current_type;
970 Mat A, P;
971 PetscBool flg;
972
973 ierr = PCGetOperators(pc, &A, &P);
974 AssertThrow(ierr == 0, ExcPETScError(ierr));
975 ierr = PCGetUseAmat(pc, &flg);
976 AssertThrow(ierr == 0, ExcPETScError(ierr));
977
978 ierr = MatGetType(flg ? A : P, &current_type);
979 AssertThrow(ierr == 0, ExcPETScError(ierr));
981 strcmp(current_type, MATIS) == 0,
983 "Matrix must be of IS type. For this, the variant of reinit that includes the active dofs must be used."));
984 }
985
986
987 std::stringstream ssStream;
988
989 if (additional_data.use_vertices)
990 set_option_value("-pc_bddc_use_vertices", "true");
991 else
992 set_option_value("-pc_bddc_use_vertices", "false");
993 if (additional_data.use_edges)
994 set_option_value("-pc_bddc_use_edges", "true");
995 else
996 set_option_value("-pc_bddc_use_edges", "false");
997 if (additional_data.use_faces)
998 set_option_value("-pc_bddc_use_faces", "true");
999 else
1000 set_option_value("-pc_bddc_use_faces", "false");
1001 if (additional_data.symmetric)
1002 set_option_value("-pc_bddc_symmetric", "true");
1003 else
1004 set_option_value("-pc_bddc_symmetric", "false");
1005 if (additional_data.coords.size() > 0)
1006 {
1007 set_option_value("-pc_bddc_corner_selection", "true");
1008 // Convert coords vector to PETSc data array
1009 std::vector<PetscReal> coords_petsc(additional_data.coords.size() *
1010 dim);
1011 for (unsigned int i = 0, j = 0; i < additional_data.coords.size(); ++i)
1012 {
1013 for (j = 0; j < dim; ++j)
1014 coords_petsc[dim * i + j] = additional_data.coords[i][j];
1015 }
1016
1017 ierr = PCSetCoordinates(pc,
1018 dim,
1019 additional_data.coords.size(),
1020 coords_petsc.data());
1021 AssertThrow(ierr == 0, ExcPETScError(ierr));
1022 }
1023 else
1024 {
1025 set_option_value("-pc_bddc_corner_selection", "false");
1026 ierr = PCSetCoordinates(pc, 0, 0, nullptr);
1027 AssertThrow(ierr == 0, ExcPETScError(ierr));
1028 }
1029
1030
1031 ierr = PCSetFromOptions(pc);
1032 AssertThrow(ierr == 0, ExcPETScError(ierr));
1033# else
1035 false, ExcMessage("BDDC preconditioner requires PETSc 3.10.0 or newer"));
1036# endif
1037 }
1038
1039
1040
1041 template <int dim>
1042 void
1044 const AdditionalData &additional_data_)
1045 {
1046 clear();
1047
1048 additional_data = additional_data_;
1049
1050 create_pc_with_mat(matrix_);
1051 initialize();
1052 }
1053
1054 /* ----------------- PreconditionShell -------------------- */
1055
1057 {
1058 initialize(matrix);
1059 }
1060
1065
1066 void
1068 {
1069 PetscErrorCode ierr;
1070 if (pc)
1071 {
1072 ierr = PCDestroy(&pc);
1073 AssertThrow(ierr == 0, ExcPETScError(ierr));
1074 }
1076
1077 ierr = PCSetType(pc, PCSHELL);
1078 AssertThrow(ierr == 0, ExcPETScError(ierr));
1079 ierr = PCShellSetContext(pc, static_cast<void *>(this));
1080 AssertThrow(ierr == 0, ExcPETScError(ierr));
1081 ierr = PCShellSetSetUp(pc, PreconditionShell::pcsetup);
1082 AssertThrow(ierr == 0, ExcPETScError(ierr));
1083 ierr = PCShellSetApply(pc, PreconditionShell::pcapply);
1084 AssertThrow(ierr == 0, ExcPETScError(ierr));
1085 ierr = PCShellSetApplyTranspose(pc, PreconditionShell::pcapply_transpose);
1086 AssertThrow(ierr == 0, ExcPETScError(ierr));
1087 ierr = PCShellSetName(pc, "deal.II user solve");
1088 AssertThrow(ierr == 0, ExcPETScError(ierr));
1089 }
1090
1091 void
1093 {
1094 initialize(matrix.get_mpi_communicator());
1095 PetscErrorCode ierr;
1096 ierr = PCSetOperators(pc, matrix, matrix);
1097 AssertThrow(ierr == 0, ExcPETScError(ierr));
1098 }
1099
1100# ifndef PetscCall
1101# define PetscCall(code) \
1102 do \
1103 { \
1104 PetscErrorCode ierr = (code); \
1105 CHKERRQ(ierr); \
1106 } \
1107 while (false)
1108# endif
1109
1110 PetscErrorCode
1112 {
1113 PetscFunctionBeginUser;
1114 // Failed reason is not reset uniformly within the
1115 // interface code of PCSetUp in PETSc.
1116 // We handle it here.
1117 PetscCall(pc_set_failed_reason(ppc, PC_NOERROR));
1118 PetscFunctionReturn(PETSC_SUCCESS);
1119 }
1120
1121 PetscErrorCode
1122 PreconditionShell::pcapply(PC ppc, Vec x, Vec y)
1123 {
1124 void *ctx;
1125
1126 PetscFunctionBeginUser;
1127 PetscCall(PCShellGetContext(ppc, &ctx));
1128
1129 auto *user = static_cast<PreconditionShell *>(ctx);
1130 if (!user->vmult)
1131 SETERRQ(
1132 PetscObjectComm((PetscObject)ppc),
1133 PETSC_ERR_LIB,
1134 "Failure in ::PETScWrappers::PreconditionShell::pcapply. Missing std::function vmult");
1135
1136 VectorBase src(x);
1137 VectorBase dst(y);
1138 const int lineno = __LINE__;
1139 try
1140 {
1141 user->vmult(dst, src);
1142 }
1143 catch (const RecoverableUserCallbackError &)
1144 {
1145 PetscCall(pc_set_failed_reason(ppc, PC_SUBPC_ERROR));
1146 }
1147 catch (...)
1148 {
1149 return PetscError(
1150 PetscObjectComm((PetscObject)ppc),
1151 lineno + 3,
1152 "vmult",
1153 __FILE__,
1154 PETSC_ERR_LIB,
1155 PETSC_ERROR_INITIAL,
1156 "Failure in pcapply from ::PETScWrappers::NonlinearSolver");
1157 }
1159 PetscFunctionReturn(PETSC_SUCCESS);
1160 }
1161
1162 PetscErrorCode
1164 {
1165 void *ctx;
1166
1167 PetscFunctionBeginUser;
1168 PetscCall(PCShellGetContext(ppc, &ctx));
1169
1170 auto *user = static_cast<PreconditionShell *>(ctx);
1171 if (!user->vmultT)
1172 SETERRQ(
1173 PetscObjectComm((PetscObject)ppc),
1174 PETSC_ERR_LIB,
1175 "Failure in ::PETScWrappers::PreconditionShell::pcapply_transpose. Missing std::function vmultT");
1176
1177 VectorBase src(x);
1178 VectorBase dst(y);
1179 const int lineno = __LINE__;
1180 try
1181 {
1182 user->vmultT(dst, src);
1183 }
1184 catch (const RecoverableUserCallbackError &)
1185 {
1186 PetscCall(pc_set_failed_reason(ppc, PC_SUBPC_ERROR));
1187 }
1188 catch (...)
1189 {
1190 return PetscError(
1191 PetscObjectComm((PetscObject)ppc),
1192 lineno + 3,
1193 "vmultT",
1194 __FILE__,
1195 PETSC_ERR_LIB,
1196 PETSC_ERROR_INITIAL,
1197 "Failure in pcapply_transpose from ::PETScWrappers::NonlinearSolver");
1198 }
1200 PetscFunctionReturn(PETSC_SUCCESS);
1201 }
1202
1203
1204} // namespace PETScWrappers
1205
1208
1209
1210#endif // DEAL_II_WITH_PETSC
void Tvmult(VectorBase &dst, const VectorBase &src) const
void vmult(VectorBase &dst, const VectorBase &src) const
void create_pc_with_mat(const MatrixBase &)
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())
static PetscErrorCode pcapply_transpose(PC pc, Vec src, Vec dst)
static PetscErrorCode pcsetup(PC pc)
void initialize(const MPI_Comm comm)
static PetscErrorCode pcapply(PC pc, Vec src, Vec dst)
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
#define Assert(cond, exc)
static ::ExceptionBase & ExcInvalidState()
static ::ExceptionBase & RecoverableUserCallbackError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
const MPI_Comm comm
Definition mpi.cc:912
void set_option_value(const std::string &name, const std::string &value)
PetscErrorCode pc_set_failed_reason(PC pc, PCFailedReason reason)
void petsc_increment_state_counter(Vec v)
#define PetscCall(code)
AdditionalData(const bool use_vertices=true, const bool use_edges=false, const bool use_faces=false, const bool symmetric=false, const std::vector< Point< dim > > coords={})
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)