18 #include "libmesh/libmesh_common.h"
20 #ifdef LIBMESH_HAVE_PETSC
27 #include "libmesh/dof_map.h"
28 #include "libmesh/libmesh_logging.h"
29 #include "libmesh/petsc_linear_solver.h"
30 #include "libmesh/shell_matrix.h"
31 #include "libmesh/petsc_matrix.h"
32 #include "libmesh/petsc_preconditioner.h"
33 #include "libmesh/petsc_vector.h"
34 #include "libmesh/enum_to_string.h"
35 #include "libmesh/system.h"
36 #include "libmesh/petsc_auto_fieldsplit.h"
37 #include "libmesh/solver_configuration.h"
38 #include "libmesh/enum_preconditioner_type.h"
39 #include "libmesh/enum_solver_type.h"
40 #include "libmesh/enum_convergence_flags.h"
41 #include "libmesh/auto_ptr.h"
48 #if PETSC_RELEASE_LESS_THAN(3,0,1)
54 libmesh_error_msg(
"Preconditioner not initialized! Make sure you call init() before solve!");
56 preconditioner->
setup();
69 preconditioner->
apply(x_vec,y_vec);
81 libmesh_error_msg(
"Preconditioner not initialized! Make sure you call init() before solve!");
83 preconditioner->
setup();
97 preconditioner->
apply(x_vec,y_vec);
103 #ifdef LIBMESH_ENABLE_DEPRECATED
104 #if PETSC_RELEASE_LESS_THAN(3,0,1)
107 libmesh_deprecated();
113 libmesh_deprecated();
120 libmesh_deprecated();
126 libmesh_deprecated();
134 template <
typename T>
137 _restrict_solve_to_is(nullptr),
138 _restrict_solve_to_is_complement(nullptr),
141 if (this->n_processors() == 1)
149 template <
typename T>
156 if (_restrict_solve_to_is !=
nullptr)
158 PetscErrorCode
ierr = LibMeshISDestroy(&_restrict_solve_to_is);
159 LIBMESH_CHKERR(
ierr);
160 _restrict_solve_to_is =
nullptr;
163 if (_restrict_solve_to_is_complement !=
nullptr)
165 PetscErrorCode
ierr = LibMeshISDestroy(&_restrict_solve_to_is_complement);
166 LIBMESH_CHKERR(
ierr);
167 _restrict_solve_to_is_complement =
nullptr;
172 PetscErrorCode
ierr=0;
174 ierr = LibMeshKSPDestroy(&_ksp);
175 LIBMESH_CHKERR(
ierr);
178 this->_solver_type =
GMRES;
180 if (!this->_preconditioner)
182 if (this->n_processors() == 1)
192 template <
typename T>
200 PetscErrorCode
ierr=0;
203 ierr = KSPCreate (this->comm().
get(), &_ksp);
204 LIBMESH_CHKERR(
ierr);
208 ierr = KSPSetOptionsPrefix(_ksp,
name);
209 LIBMESH_CHKERR(
ierr);
213 ierr = KSPGetPC (_ksp, &_pc);
214 LIBMESH_CHKERR(
ierr);
217 this->set_petsc_solver_type();
221 if (this->_solver_configuration)
223 this->_solver_configuration->set_options_during_init();
233 ierr = KSPSetFromOptions (_ksp);
234 LIBMESH_CHKERR(
ierr);
244 #if PETSC_VERSION_LESS_THAN(3,0,0) || !PETSC_RELEASE_LESS_THAN(3,4,0)
248 const KSPType ksp_type;
251 ierr = KSPGetType (_ksp, &ksp_type);
252 LIBMESH_CHKERR(
ierr);
254 if (strcmp(ksp_type,
"preonly"))
256 ierr = KSPSetInitialGuessNonzero (_ksp, PETSC_TRUE);
257 LIBMESH_CHKERR(
ierr);
265 ierr = KSPSetResidualHistory(_ksp,
269 LIBMESH_CHKERR(
ierr);
274 if (this->_preconditioner)
276 this->_preconditioner->init();
277 PCShellSetContext(_pc,(
void *)this->_preconditioner);
285 template <
typename T>
294 PetscErrorCode
ierr=0;
297 ierr = KSPCreate (this->comm().
get(), &_ksp);
298 LIBMESH_CHKERR(
ierr);
302 ierr = KSPSetOptionsPrefix(_ksp,
name);
303 LIBMESH_CHKERR(
ierr);
310 ierr = KSPGetPC (_ksp, &_pc);
311 LIBMESH_CHKERR(
ierr);
314 #if PETSC_RELEASE_LESS_THAN(3,5,0)
315 ierr = KSPSetOperators(_ksp, matrix->
mat(), matrix->
mat(),DIFFERENT_NONZERO_PATTERN);
317 ierr = KSPSetOperators(_ksp, matrix->
mat(), matrix->
mat());
319 LIBMESH_CHKERR(
ierr);
322 this->set_petsc_solver_type();
326 if (this->_solver_configuration)
328 this->_solver_configuration->set_options_during_init();
338 ierr = KSPSetFromOptions (_ksp);
339 LIBMESH_CHKERR(
ierr);
349 #if PETSC_VERSION_LESS_THAN(3,0,0) || !PETSC_RELEASE_LESS_THAN(3,4,0)
352 const KSPType ksp_type;
355 ierr = KSPGetType (_ksp, &ksp_type);
356 LIBMESH_CHKERR(
ierr);
358 if (strcmp(ksp_type,
"preonly"))
360 ierr = KSPSetInitialGuessNonzero (_ksp, PETSC_TRUE);
361 LIBMESH_CHKERR(
ierr);
369 ierr = KSPSetResidualHistory(_ksp,
373 LIBMESH_CHKERR(
ierr);
376 if (this->_preconditioner)
378 this->_preconditioner->set_matrix(*matrix);
379 this->_preconditioner->init();
380 PCShellSetContext(_pc,(
void *)this->_preconditioner);
389 template <
typename T>
398 template <
typename T>
403 PetscErrorCode
ierr=0;
411 _subset_solve_mode = subset_solve_mode;
415 PetscInt * petsc_dofs =
nullptr;
416 ierr = PetscMalloc(dofs->size()*
sizeof(PetscInt), &petsc_dofs);
417 LIBMESH_CHKERR(
ierr);
420 petsc_dofs[i] = (*dofs)[i];
422 ierr = ISCreateLibMesh(this->comm().
get(),
423 cast_int<PetscInt>(dofs->size()),
425 &_restrict_solve_to_is);
426 LIBMESH_CHKERR(
ierr);
432 template <
typename T>
433 std::pair<unsigned int, Real>
439 const unsigned int m_its)
441 LOG_SCOPE(
"solve()",
"PetscLinearSolver");
445 PetscMatrix<T> * precond = cast_ptr<PetscMatrix<T> *>(&precond_in);
446 PetscVector<T> * solution = cast_ptr<PetscVector<T> *>(&solution_in);
451 PetscErrorCode
ierr=0;
452 PetscInt its=0, max_its = static_cast<PetscInt>(m_its);
453 PetscReal final_resid=0.;
469 Mat submat =
nullptr;
470 Mat subprecond =
nullptr;
471 Vec subrhs =
nullptr;
472 Vec subsolution =
nullptr;
473 VecScatter scatter =
nullptr;
474 std::unique_ptr<PetscMatrix<Number>> subprecond_matrix;
478 if (_restrict_solve_to_is !=
nullptr)
480 PetscInt is_local_size = this->_restrict_solve_to_is_local_size();
482 ierr = VecCreate(this->comm().
get(),&subrhs);
483 LIBMESH_CHKERR(
ierr);
484 ierr = VecSetSizes(subrhs,is_local_size,PETSC_DECIDE);
485 LIBMESH_CHKERR(
ierr);
486 ierr = VecSetFromOptions(subrhs);
487 LIBMESH_CHKERR(
ierr);
489 ierr = VecCreate(this->comm().
get(),&subsolution);
490 LIBMESH_CHKERR(
ierr);
491 ierr = VecSetSizes(subsolution,is_local_size,PETSC_DECIDE);
492 LIBMESH_CHKERR(
ierr);
493 ierr = VecSetFromOptions(subsolution);
494 LIBMESH_CHKERR(
ierr);
496 ierr = LibMeshVecScatterCreate(rhs->vec(), _restrict_solve_to_is, subrhs,
nullptr, &scatter);
497 LIBMESH_CHKERR(
ierr);
499 ierr = VecScatterBegin(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
500 LIBMESH_CHKERR(
ierr);
501 ierr = VecScatterEnd(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
502 LIBMESH_CHKERR(
ierr);
504 ierr = VecScatterBegin(scatter,solution->vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
505 LIBMESH_CHKERR(
ierr);
506 ierr = VecScatterEnd(scatter,solution->vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
507 LIBMESH_CHKERR(
ierr);
509 ierr = LibMeshCreateSubMatrix(matrix->
mat(),
510 _restrict_solve_to_is,
511 _restrict_solve_to_is,
512 #if PETSC_VERSION_LESS_THAN(3,1,0)
517 LIBMESH_CHKERR(
ierr);
519 ierr = LibMeshCreateSubMatrix(precond->mat(),
520 _restrict_solve_to_is,
521 _restrict_solve_to_is,
522 #if PETSC_VERSION_LESS_THAN(3,1,0)
527 LIBMESH_CHKERR(
ierr);
535 _create_complement_is(rhs_in);
536 PetscInt is_complement_local_size =
537 cast_int<PetscInt>(rhs_in.
local_size()-is_local_size);
539 Vec subvec1 =
nullptr;
540 Mat submat1 =
nullptr;
541 VecScatter scatter1 =
nullptr;
543 ierr = VecCreate(this->comm().
get(),&subvec1);
544 LIBMESH_CHKERR(
ierr);
545 ierr = VecSetSizes(subvec1,is_complement_local_size,PETSC_DECIDE);
546 LIBMESH_CHKERR(
ierr);
547 ierr = VecSetFromOptions(subvec1);
548 LIBMESH_CHKERR(
ierr);
550 ierr = LibMeshVecScatterCreate(rhs->vec(),_restrict_solve_to_is_complement, subvec1,
nullptr, &scatter1);
551 LIBMESH_CHKERR(
ierr);
553 ierr = VecScatterBegin(scatter1,_subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->vec(),subvec1,INSERT_VALUES,SCATTER_FORWARD);
554 LIBMESH_CHKERR(
ierr);
555 ierr = VecScatterEnd(scatter1,_subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->vec(),subvec1,INSERT_VALUES,SCATTER_FORWARD);
556 LIBMESH_CHKERR(
ierr);
558 ierr = VecScale(subvec1,-1.0);
559 LIBMESH_CHKERR(
ierr);
561 ierr = LibMeshCreateSubMatrix(matrix->
mat(),
562 _restrict_solve_to_is,
563 _restrict_solve_to_is_complement,
564 #if PETSC_VERSION_LESS_THAN(3,1,0)
569 LIBMESH_CHKERR(
ierr);
571 ierr = MatMultAdd(submat1,subvec1,subrhs,subrhs);
572 LIBMESH_CHKERR(
ierr);
574 ierr = LibMeshVecScatterDestroy(&scatter1);
575 LIBMESH_CHKERR(
ierr);
576 ierr = LibMeshVecDestroy(&subvec1);
577 LIBMESH_CHKERR(
ierr);
578 ierr = LibMeshMatDestroy(&submat1);
579 LIBMESH_CHKERR(
ierr);
581 #if PETSC_RELEASE_LESS_THAN(3,5,0)
582 ierr = KSPSetOperators(_ksp, submat, subprecond,
583 this->same_preconditioner ? SAME_PRECONDITIONER : DIFFERENT_NONZERO_PATTERN);
585 ierr = KSPSetOperators(_ksp, submat, subprecond);
587 PetscBool ksp_reuse_preconditioner = this->same_preconditioner ? PETSC_TRUE : PETSC_FALSE;
588 ierr = KSPSetReusePreconditioner(_ksp, ksp_reuse_preconditioner);
590 LIBMESH_CHKERR(
ierr);
592 if (this->_preconditioner)
594 subprecond_matrix = libmesh_make_unique<PetscMatrix<Number>>(subprecond, this->comm());
595 this->_preconditioner->set_matrix(*subprecond_matrix);
596 this->_preconditioner->init();
601 #if PETSC_RELEASE_LESS_THAN(3,5,0)
602 ierr = KSPSetOperators(_ksp, matrix->
mat(), precond->mat(),
603 this->same_preconditioner ? SAME_PRECONDITIONER : DIFFERENT_NONZERO_PATTERN);
605 ierr = KSPSetOperators(_ksp, matrix->
mat(), precond->mat());
607 PetscBool ksp_reuse_preconditioner = this->same_preconditioner ? PETSC_TRUE : PETSC_FALSE;
608 ierr = KSPSetReusePreconditioner(_ksp, ksp_reuse_preconditioner);
610 LIBMESH_CHKERR(
ierr);
612 if (this->_preconditioner)
614 this->_preconditioner->set_matrix(matrix_in);
615 this->_preconditioner->init();
621 ierr = KSPSetTolerances (_ksp, tol, PETSC_DEFAULT,
622 PETSC_DEFAULT, max_its);
623 LIBMESH_CHKERR(
ierr);
626 ierr = KSPSetFromOptions(_ksp);
627 LIBMESH_CHKERR(
ierr);
631 if (this->_solver_configuration)
633 this->_solver_configuration->configure_solver();
637 if (_restrict_solve_to_is !=
nullptr)
639 ierr = KSPSolve (_ksp, subrhs, subsolution);
640 LIBMESH_CHKERR(
ierr);
644 ierr = KSPSolve (_ksp, rhs->vec(), solution->vec());
645 LIBMESH_CHKERR(
ierr);
649 ierr = KSPGetIterationNumber (_ksp, &its);
650 LIBMESH_CHKERR(
ierr);
653 ierr = KSPGetResidualNorm (_ksp, &final_resid);
654 LIBMESH_CHKERR(
ierr);
656 if (_restrict_solve_to_is !=
nullptr)
658 switch(_subset_solve_mode)
661 ierr = VecZeroEntries(solution->vec());
662 LIBMESH_CHKERR(
ierr);
666 ierr = VecCopy(rhs->vec(),solution->vec());
667 LIBMESH_CHKERR(
ierr);
675 libmesh_error_msg(
"Invalid subset solve mode = " << _subset_solve_mode);
677 ierr = VecScatterBegin(scatter,subsolution,solution->vec(),INSERT_VALUES,SCATTER_REVERSE);
678 LIBMESH_CHKERR(
ierr);
679 ierr = VecScatterEnd(scatter,subsolution,solution->vec(),INSERT_VALUES,SCATTER_REVERSE);
680 LIBMESH_CHKERR(
ierr);
682 ierr = LibMeshVecScatterDestroy(&scatter);
683 LIBMESH_CHKERR(
ierr);
685 if (this->_preconditioner)
689 this->_preconditioner->set_matrix(matrix_in);
690 this->_preconditioner->init();
693 ierr = LibMeshVecDestroy(&subsolution);
694 LIBMESH_CHKERR(
ierr);
695 ierr = LibMeshVecDestroy(&subrhs);
696 LIBMESH_CHKERR(
ierr);
697 ierr = LibMeshMatDestroy(&submat);
698 LIBMESH_CHKERR(
ierr);
699 ierr = LibMeshMatDestroy(&subprecond);
700 LIBMESH_CHKERR(
ierr);
704 return std::make_pair(its, final_resid);
707 template <
typename T>
708 std::pair<unsigned int, Real>
713 const unsigned int m_its)
715 LOG_SCOPE(
"solve()",
"PetscLinearSolver");
720 PetscMatrix<T> * precond = cast_ptr<PetscMatrix<T> *>(&matrix_in);
721 PetscVector<T> * solution = cast_ptr<PetscVector<T> *>(&solution_in);
726 PetscErrorCode
ierr=0;
727 PetscInt its=0, max_its = static_cast<PetscInt>(m_its);
728 PetscReal final_resid=0.;
736 Mat submat =
nullptr;
737 Mat subprecond =
nullptr;
738 Vec subrhs =
nullptr;
739 Vec subsolution =
nullptr;
740 VecScatter scatter =
nullptr;
741 std::unique_ptr<PetscMatrix<Number>> subprecond_matrix;
745 if (_restrict_solve_to_is !=
nullptr)
747 PetscInt is_local_size = this->_restrict_solve_to_is_local_size();
749 ierr = VecCreate(this->comm().
get(),&subrhs);
750 LIBMESH_CHKERR(
ierr);
751 ierr = VecSetSizes(subrhs,is_local_size,PETSC_DECIDE);
752 LIBMESH_CHKERR(
ierr);
753 ierr = VecSetFromOptions(subrhs);
754 LIBMESH_CHKERR(
ierr);
756 ierr = VecCreate(this->comm().
get(),&subsolution);
757 LIBMESH_CHKERR(
ierr);
758 ierr = VecSetSizes(subsolution,is_local_size,PETSC_DECIDE);
759 LIBMESH_CHKERR(
ierr);
760 ierr = VecSetFromOptions(subsolution);
761 LIBMESH_CHKERR(
ierr);
763 ierr = LibMeshVecScatterCreate(rhs->vec(),_restrict_solve_to_is, subrhs,
nullptr, &scatter);
764 LIBMESH_CHKERR(
ierr);
766 ierr = VecScatterBegin(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
767 LIBMESH_CHKERR(
ierr);
768 ierr = VecScatterEnd(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
769 LIBMESH_CHKERR(
ierr);
771 ierr = VecScatterBegin(scatter,solution->vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
772 LIBMESH_CHKERR(
ierr);
773 ierr = VecScatterEnd(scatter,solution->vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
774 LIBMESH_CHKERR(
ierr);
776 ierr = LibMeshCreateSubMatrix(matrix->
mat(),
777 _restrict_solve_to_is,
778 _restrict_solve_to_is,
779 #if PETSC_VERSION_LESS_THAN(3,1,0)
784 LIBMESH_CHKERR(
ierr);
786 ierr = LibMeshCreateSubMatrix(precond->mat(),
787 _restrict_solve_to_is,
788 _restrict_solve_to_is,
789 #if PETSC_VERSION_LESS_THAN(3,1,0)
794 LIBMESH_CHKERR(
ierr);
802 _create_complement_is(rhs_in);
803 PetscInt is_complement_local_size =
804 cast_int<PetscInt>(rhs_in.
local_size()-is_local_size);
806 Vec subvec1 =
nullptr;
807 Mat submat1 =
nullptr;
808 VecScatter scatter1 =
nullptr;
810 ierr = VecCreate(this->comm().
get(),&subvec1);
811 LIBMESH_CHKERR(
ierr);
812 ierr = VecSetSizes(subvec1,is_complement_local_size,PETSC_DECIDE);
813 LIBMESH_CHKERR(
ierr);
814 ierr = VecSetFromOptions(subvec1);
815 LIBMESH_CHKERR(
ierr);
817 ierr = LibMeshVecScatterCreate(rhs->vec(),_restrict_solve_to_is_complement, subvec1,
nullptr, &scatter1);
818 LIBMESH_CHKERR(
ierr);
820 ierr = VecScatterBegin(scatter1,_subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->vec(),subvec1,INSERT_VALUES,SCATTER_FORWARD);
821 LIBMESH_CHKERR(
ierr);
822 ierr = VecScatterEnd(scatter1,_subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->vec(),subvec1,INSERT_VALUES,SCATTER_FORWARD);
823 LIBMESH_CHKERR(
ierr);
825 ierr = VecScale(subvec1,-1.0);
826 LIBMESH_CHKERR(
ierr);
828 ierr = LibMeshCreateSubMatrix(matrix->
mat(),
829 _restrict_solve_to_is,
830 _restrict_solve_to_is_complement,
831 #if PETSC_VERSION_LESS_THAN(3,1,0)
836 LIBMESH_CHKERR(
ierr);
838 ierr = MatMultAdd(submat1,subvec1,subrhs,subrhs);
839 LIBMESH_CHKERR(
ierr);
841 ierr = LibMeshVecScatterDestroy(&scatter1);
842 LIBMESH_CHKERR(
ierr);
843 ierr = LibMeshVecDestroy(&subvec1);
844 LIBMESH_CHKERR(
ierr);
845 ierr = LibMeshMatDestroy(&submat1);
846 LIBMESH_CHKERR(
ierr);
848 #if PETSC_RELEASE_LESS_THAN(3,5,0)
849 ierr = KSPSetOperators(_ksp, submat, subprecond,
850 this->same_preconditioner ? SAME_PRECONDITIONER : DIFFERENT_NONZERO_PATTERN);
852 ierr = KSPSetOperators(_ksp, submat, subprecond);
854 PetscBool ksp_reuse_preconditioner = this->same_preconditioner ? PETSC_TRUE : PETSC_FALSE;
855 ierr = KSPSetReusePreconditioner(_ksp, ksp_reuse_preconditioner);
857 LIBMESH_CHKERR(
ierr);
859 if (this->_preconditioner)
861 subprecond_matrix = libmesh_make_unique<PetscMatrix<Number>>(subprecond, this->comm());
862 this->_preconditioner->set_matrix(*subprecond_matrix);
863 this->_preconditioner->init();
868 #if PETSC_RELEASE_LESS_THAN(3,5,0)
869 ierr = KSPSetOperators(_ksp, matrix->
mat(), precond->mat(),
870 this->same_preconditioner ? SAME_PRECONDITIONER : DIFFERENT_NONZERO_PATTERN);
872 ierr = KSPSetOperators(_ksp, matrix->
mat(), precond->mat());
874 PetscBool ksp_reuse_preconditioner = this->same_preconditioner ? PETSC_TRUE : PETSC_FALSE;
875 ierr = KSPSetReusePreconditioner(_ksp, ksp_reuse_preconditioner);
877 LIBMESH_CHKERR(
ierr);
879 if (this->_preconditioner)
881 this->_preconditioner->set_matrix(matrix_in);
882 this->_preconditioner->init();
888 ierr = KSPSetTolerances (_ksp, tol, PETSC_DEFAULT,
889 PETSC_DEFAULT, max_its);
890 LIBMESH_CHKERR(
ierr);
893 ierr = KSPSetFromOptions(_ksp);
894 LIBMESH_CHKERR(
ierr);
897 if (_restrict_solve_to_is !=
nullptr)
899 ierr = KSPSolveTranspose (_ksp, subrhs, subsolution);
900 LIBMESH_CHKERR(
ierr);
904 ierr = KSPSolveTranspose (_ksp, rhs->vec(), solution->vec());
905 LIBMESH_CHKERR(
ierr);
909 ierr = KSPGetIterationNumber (_ksp, &its);
910 LIBMESH_CHKERR(
ierr);
913 ierr = KSPGetResidualNorm (_ksp, &final_resid);
914 LIBMESH_CHKERR(
ierr);
916 if (_restrict_solve_to_is !=
nullptr)
918 switch(_subset_solve_mode)
921 ierr = VecZeroEntries(solution->vec());
922 LIBMESH_CHKERR(
ierr);
926 ierr = VecCopy(rhs->vec(),solution->vec());
927 LIBMESH_CHKERR(
ierr);
935 libmesh_error_msg(
"Invalid subset solve mode = " << _subset_solve_mode);
937 ierr = VecScatterBegin(scatter,subsolution,solution->vec(),INSERT_VALUES,SCATTER_REVERSE);
938 LIBMESH_CHKERR(
ierr);
939 ierr = VecScatterEnd(scatter,subsolution,solution->vec(),INSERT_VALUES,SCATTER_REVERSE);
940 LIBMESH_CHKERR(
ierr);
942 ierr = LibMeshVecScatterDestroy(&scatter);
943 LIBMESH_CHKERR(
ierr);
945 if (this->_preconditioner)
949 this->_preconditioner->set_matrix(matrix_in);
950 this->_preconditioner->init();
953 ierr = LibMeshVecDestroy(&subsolution);
954 LIBMESH_CHKERR(
ierr);
955 ierr = LibMeshVecDestroy(&subrhs);
956 LIBMESH_CHKERR(
ierr);
957 ierr = LibMeshMatDestroy(&submat);
958 LIBMESH_CHKERR(
ierr);
959 ierr = LibMeshMatDestroy(&subprecond);
960 LIBMESH_CHKERR(
ierr);
964 return std::make_pair(its, final_resid);
968 template <
typename T>
969 std::pair<unsigned int, Real>
974 const unsigned int m_its)
977 #if PETSC_VERSION_LESS_THAN(3,1,0)
978 if (_restrict_solve_to_is !=
nullptr)
979 libmesh_error_msg(
"The current implementation of subset solves with " \
980 <<
"shell matrices requires PETSc version 3.1 or above. " \
981 <<
"Older PETSc version do not support automatic " \
982 <<
"submatrix generation of shell matrices.");
985 LOG_SCOPE(
"solve()",
"PetscLinearSolver");
988 PetscVector<T> * solution = cast_ptr<PetscVector<T> *>(&solution_in);
993 PetscErrorCode
ierr=0;
994 PetscInt its=0, max_its = static_cast<PetscInt>(m_its);
995 PetscReal final_resid=0.;
997 Mat submat =
nullptr;
998 Vec subrhs =
nullptr;
999 Vec subsolution =
nullptr;
1000 VecScatter scatter =
nullptr;
1008 ierr = MatCreateShell(this->comm().
get(),
1013 const_cast<void *>(static_cast<const void *>(&shell_matrix)),
1020 LIBMESH_CHKERR(
ierr);
1021 ierr = MatShellSetOperation(mat,MATOP_MULT,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult));
1022 LIBMESH_CHKERR(
ierr);
1023 ierr = MatShellSetOperation(mat,MATOP_MULT_ADD,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult_add));
1024 LIBMESH_CHKERR(
ierr);
1025 ierr = MatShellSetOperation(mat,MATOP_GET_DIAGONAL,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_get_diagonal));
1026 LIBMESH_CHKERR(
ierr);
1030 if (_restrict_solve_to_is !=
nullptr)
1032 PetscInt is_local_size = this->_restrict_solve_to_is_local_size();
1034 ierr = VecCreate(this->comm().
get(),&subrhs);
1035 LIBMESH_CHKERR(
ierr);
1036 ierr = VecSetSizes(subrhs,is_local_size,PETSC_DECIDE);
1037 LIBMESH_CHKERR(
ierr);
1038 ierr = VecSetFromOptions(subrhs);
1039 LIBMESH_CHKERR(
ierr);
1041 ierr = VecCreate(this->comm().
get(),&subsolution);
1042 LIBMESH_CHKERR(
ierr);
1043 ierr = VecSetSizes(subsolution,is_local_size,PETSC_DECIDE);
1044 LIBMESH_CHKERR(
ierr);
1045 ierr = VecSetFromOptions(subsolution);
1046 LIBMESH_CHKERR(
ierr);
1048 ierr = LibMeshVecScatterCreate(rhs->vec(),_restrict_solve_to_is, subrhs,
nullptr, &scatter);
1049 LIBMESH_CHKERR(
ierr);
1051 ierr = VecScatterBegin(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
1052 LIBMESH_CHKERR(
ierr);
1053 ierr = VecScatterEnd(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
1054 LIBMESH_CHKERR(
ierr);
1056 ierr = VecScatterBegin(scatter,solution->
vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
1057 LIBMESH_CHKERR(
ierr);
1058 ierr = VecScatterEnd(scatter,solution->
vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
1059 LIBMESH_CHKERR(
ierr);
1061 #if !PETSC_VERSION_LESS_THAN(3,1,0)
1062 ierr = LibMeshCreateSubMatrix(mat,
1063 _restrict_solve_to_is,
1064 _restrict_solve_to_is,
1067 LIBMESH_CHKERR(
ierr);
1076 _create_complement_is(rhs_in);
1077 PetscInt is_complement_local_size =
1078 cast_int<PetscInt>(rhs_in.
local_size()-is_local_size);
1080 Vec subvec1 =
nullptr;
1081 Mat submat1 =
nullptr;
1082 VecScatter scatter1 =
nullptr;
1084 ierr = VecCreate(this->comm().
get(),&subvec1);
1085 LIBMESH_CHKERR(
ierr);
1086 ierr = VecSetSizes(subvec1,is_complement_local_size,PETSC_DECIDE);
1087 LIBMESH_CHKERR(
ierr);
1088 ierr = VecSetFromOptions(subvec1);
1089 LIBMESH_CHKERR(
ierr);
1091 ierr = LibMeshVecScatterCreate(rhs->vec(),_restrict_solve_to_is_complement, subvec1,
nullptr, &scatter1);
1092 LIBMESH_CHKERR(
ierr);
1094 ierr = VecScatterBegin(scatter1,_subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->
vec(),subvec1,INSERT_VALUES,SCATTER_FORWARD);
1095 LIBMESH_CHKERR(
ierr);
1096 ierr = VecScatterEnd(scatter1,_subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->
vec(),subvec1,INSERT_VALUES,SCATTER_FORWARD);
1097 LIBMESH_CHKERR(
ierr);
1099 ierr = VecScale(subvec1,-1.0);
1100 LIBMESH_CHKERR(
ierr);
1102 #if !PETSC_VERSION_LESS_THAN(3,1,0)
1103 ierr = LibMeshCreateSubMatrix(mat,
1104 _restrict_solve_to_is,
1105 _restrict_solve_to_is_complement,
1108 LIBMESH_CHKERR(
ierr);
1121 Vec subvec2 =
nullptr;
1122 ierr = VecCreate(this->comm().
get(),&subvec2);
1123 LIBMESH_CHKERR(
ierr);
1124 ierr = VecSetSizes(subvec2,is_local_size,PETSC_DECIDE);
1125 LIBMESH_CHKERR(
ierr);
1126 ierr = VecSetFromOptions(subvec2);
1127 LIBMESH_CHKERR(
ierr);
1128 ierr = MatMult(submat1,subvec1,subvec2);
1129 LIBMESH_CHKERR(
ierr);
1130 ierr = VecAXPY(subrhs,1.0,subvec2);
1132 ierr = LibMeshVecScatterDestroy(&scatter1);
1133 LIBMESH_CHKERR(
ierr);
1134 ierr = LibMeshVecDestroy(&subvec1);
1135 LIBMESH_CHKERR(
ierr);
1136 ierr = LibMeshMatDestroy(&submat1);
1137 LIBMESH_CHKERR(
ierr);
1139 #if PETSC_RELEASE_LESS_THAN(3,5,0)
1140 ierr = KSPSetOperators(_ksp, submat, submat,
1141 DIFFERENT_NONZERO_PATTERN);
1143 ierr = KSPSetOperators(_ksp, submat, submat);
1145 LIBMESH_CHKERR(
ierr);
1149 #if PETSC_RELEASE_LESS_THAN(3,5,0)
1150 ierr = KSPSetOperators(_ksp, mat, mat,
1151 DIFFERENT_NONZERO_PATTERN);
1153 ierr = KSPSetOperators(_ksp, mat, mat);
1155 LIBMESH_CHKERR(
ierr);
1160 ierr = KSPSetTolerances (_ksp, tol, PETSC_DEFAULT,
1161 PETSC_DEFAULT, max_its);
1162 LIBMESH_CHKERR(
ierr);
1165 ierr = KSPSetFromOptions(_ksp);
1166 LIBMESH_CHKERR(
ierr);
1169 if (_restrict_solve_to_is !=
nullptr)
1171 ierr = KSPSolve (_ksp, subrhs, subsolution);
1172 LIBMESH_CHKERR(
ierr);
1176 ierr = KSPSolve (_ksp, rhs->vec(), solution->
vec());
1177 LIBMESH_CHKERR(
ierr);
1181 ierr = KSPGetIterationNumber (_ksp, &its);
1182 LIBMESH_CHKERR(
ierr);
1185 ierr = KSPGetResidualNorm (_ksp, &final_resid);
1186 LIBMESH_CHKERR(
ierr);
1188 if (_restrict_solve_to_is !=
nullptr)
1190 switch(_subset_solve_mode)
1193 ierr = VecZeroEntries(solution->
vec());
1194 LIBMESH_CHKERR(
ierr);
1198 ierr = VecCopy(rhs->vec(),solution->
vec());
1199 LIBMESH_CHKERR(
ierr);
1207 libmesh_error_msg(
"Invalid subset solve mode = " << _subset_solve_mode);
1209 ierr = VecScatterBegin(scatter,subsolution,solution->
vec(),INSERT_VALUES,SCATTER_REVERSE);
1210 LIBMESH_CHKERR(
ierr);
1211 ierr = VecScatterEnd(scatter,subsolution,solution->
vec(),INSERT_VALUES,SCATTER_REVERSE);
1212 LIBMESH_CHKERR(
ierr);
1214 ierr = LibMeshVecScatterDestroy(&scatter);
1215 LIBMESH_CHKERR(
ierr);
1217 ierr = LibMeshVecDestroy(&subsolution);
1218 LIBMESH_CHKERR(
ierr);
1219 ierr = LibMeshVecDestroy(&subrhs);
1220 LIBMESH_CHKERR(
ierr);
1221 ierr = LibMeshMatDestroy(&submat);
1222 LIBMESH_CHKERR(
ierr);
1226 ierr = LibMeshMatDestroy(&mat);
1227 LIBMESH_CHKERR(
ierr);
1230 return std::make_pair(its, final_resid);
1235 template <
typename T>
1236 std::pair<unsigned int, Real>
1242 const unsigned int m_its)
1245 #if PETSC_VERSION_LESS_THAN(3,1,0)
1246 if (_restrict_solve_to_is !=
nullptr)
1247 libmesh_error_msg(
"The current implementation of subset solves with " \
1248 <<
"shell matrices requires PETSc version 3.1 or above. " \
1249 <<
"Older PETSc version do not support automatic " \
1250 <<
"submatrix generation of shell matrices.");
1253 LOG_SCOPE(
"solve()",
"PetscLinearSolver");
1256 const PetscMatrix<T> * precond = cast_ptr<const PetscMatrix<T> *>(&precond_matrix);
1257 PetscVector<T> * solution = cast_ptr<PetscVector<T> *>(&solution_in);
1262 PetscErrorCode
ierr=0;
1263 PetscInt its=0, max_its = static_cast<PetscInt>(m_its);
1264 PetscReal final_resid=0.;
1266 Mat submat =
nullptr;
1267 Mat subprecond =
nullptr;
1268 Vec subrhs =
nullptr;
1269 Vec subsolution =
nullptr;
1270 VecScatter scatter =
nullptr;
1271 std::unique_ptr<PetscMatrix<Number>> subprecond_matrix;
1279 ierr = MatCreateShell(this->comm().
get(),
1284 const_cast<void *>(static_cast<const void *>(&shell_matrix)),
1291 LIBMESH_CHKERR(
ierr);
1292 ierr = MatShellSetOperation(mat,MATOP_MULT,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult));
1293 LIBMESH_CHKERR(
ierr);
1294 ierr = MatShellSetOperation(mat,MATOP_MULT_ADD,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult_add));
1295 LIBMESH_CHKERR(
ierr);
1296 ierr = MatShellSetOperation(mat,MATOP_GET_DIAGONAL,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_get_diagonal));
1297 LIBMESH_CHKERR(
ierr);
1301 if (_restrict_solve_to_is !=
nullptr)
1303 PetscInt is_local_size = this->_restrict_solve_to_is_local_size();
1305 ierr = VecCreate(this->comm().
get(),&subrhs);
1306 LIBMESH_CHKERR(
ierr);
1307 ierr = VecSetSizes(subrhs,is_local_size,PETSC_DECIDE);
1308 LIBMESH_CHKERR(
ierr);
1309 ierr = VecSetFromOptions(subrhs);
1310 LIBMESH_CHKERR(
ierr);
1312 ierr = VecCreate(this->comm().
get(),&subsolution);
1313 LIBMESH_CHKERR(
ierr);
1314 ierr = VecSetSizes(subsolution,is_local_size,PETSC_DECIDE);
1315 LIBMESH_CHKERR(
ierr);
1316 ierr = VecSetFromOptions(subsolution);
1317 LIBMESH_CHKERR(
ierr);
1319 ierr = LibMeshVecScatterCreate(rhs->vec(),_restrict_solve_to_is, subrhs,
nullptr, &scatter);
1320 LIBMESH_CHKERR(
ierr);
1322 ierr = VecScatterBegin(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
1323 LIBMESH_CHKERR(
ierr);
1324 ierr = VecScatterEnd(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
1325 LIBMESH_CHKERR(
ierr);
1327 ierr = VecScatterBegin(scatter,solution->vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
1328 LIBMESH_CHKERR(
ierr);
1329 ierr = VecScatterEnd(scatter,solution->vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
1330 LIBMESH_CHKERR(
ierr);
1332 #if !PETSC_VERSION_LESS_THAN(3,1,0)
1333 ierr = LibMeshCreateSubMatrix(mat,
1334 _restrict_solve_to_is,
1335 _restrict_solve_to_is,
1338 LIBMESH_CHKERR(
ierr);
1341 _restrict_solve_to_is,
1342 _restrict_solve_to_is,
1345 LIBMESH_CHKERR(
ierr);
1354 _create_complement_is(rhs_in);
1355 PetscInt is_complement_local_size = rhs_in.
local_size()-is_local_size;
1357 Vec subvec1 =
nullptr;
1358 Mat submat1 =
nullptr;
1359 VecScatter scatter1 =
nullptr;
1361 ierr = VecCreate(this->comm().
get(),&subvec1);
1362 LIBMESH_CHKERR(
ierr);
1363 ierr = VecSetSizes(subvec1,is_complement_local_size,PETSC_DECIDE);
1364 LIBMESH_CHKERR(
ierr);
1365 ierr = VecSetFromOptions(subvec1);
1366 LIBMESH_CHKERR(
ierr);
1368 ierr = LibMeshVecScatterCreate(rhs->vec(),_restrict_solve_to_is_complement, subvec1,
nullptr, &scatter1);
1369 LIBMESH_CHKERR(
ierr);
1371 ierr = VecScatterBegin(scatter1,_subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->vec(),subvec1,INSERT_VALUES,SCATTER_FORWARD);
1372 LIBMESH_CHKERR(
ierr);
1373 ierr = VecScatterEnd(scatter1,_subset_solve_mode==
SUBSET_COPY_RHS ? rhs->vec() : solution->vec(),subvec1,INSERT_VALUES,SCATTER_FORWARD);
1374 LIBMESH_CHKERR(
ierr);
1376 ierr = VecScale(subvec1,-1.0);
1377 LIBMESH_CHKERR(
ierr);
1379 #if !PETSC_VERSION_LESS_THAN(3,1,0)
1380 ierr = LibMeshCreateSubMatrix(mat,
1381 _restrict_solve_to_is,
1382 _restrict_solve_to_is_complement,
1385 LIBMESH_CHKERR(
ierr);
1398 Vec subvec2 =
nullptr;
1399 ierr = VecCreate(this->comm().
get(),&subvec2);
1400 LIBMESH_CHKERR(
ierr);
1401 ierr = VecSetSizes(subvec2,is_local_size,PETSC_DECIDE);
1402 LIBMESH_CHKERR(
ierr);
1403 ierr = VecSetFromOptions(subvec2);
1404 LIBMESH_CHKERR(
ierr);
1405 ierr = MatMult(submat1,subvec1,subvec2);
1406 LIBMESH_CHKERR(
ierr);
1407 ierr = VecAXPY(subrhs,1.0,subvec2);
1408 LIBMESH_CHKERR(
ierr);
1410 ierr = LibMeshVecScatterDestroy(&scatter1);
1411 LIBMESH_CHKERR(
ierr);
1412 ierr = LibMeshVecDestroy(&subvec1);
1413 LIBMESH_CHKERR(
ierr);
1414 ierr = LibMeshMatDestroy(&submat1);
1415 LIBMESH_CHKERR(
ierr);
1418 #if PETSC_RELEASE_LESS_THAN(3,5,0)
1419 ierr = KSPSetOperators(_ksp, submat, subprecond,
1420 DIFFERENT_NONZERO_PATTERN);
1422 ierr = KSPSetOperators(_ksp, submat, subprecond);
1424 LIBMESH_CHKERR(
ierr);
1426 if (this->_preconditioner)
1428 subprecond_matrix = libmesh_make_unique<PetscMatrix<Number>>(subprecond, this->comm());
1429 this->_preconditioner->set_matrix(*subprecond_matrix);
1430 this->_preconditioner->init();
1435 #if PETSC_RELEASE_LESS_THAN(3,5,0)
1437 DIFFERENT_NONZERO_PATTERN);
1441 LIBMESH_CHKERR(
ierr);
1443 if (this->_preconditioner)
1446 this->_preconditioner->init();
1452 ierr = KSPSetTolerances (_ksp, tol, PETSC_DEFAULT,
1453 PETSC_DEFAULT, max_its);
1454 LIBMESH_CHKERR(
ierr);
1457 ierr = KSPSetFromOptions(_ksp);
1458 LIBMESH_CHKERR(
ierr);
1461 if (_restrict_solve_to_is !=
nullptr)
1463 ierr = KSPSolve (_ksp, subrhs, subsolution);
1464 LIBMESH_CHKERR(
ierr);
1468 ierr = KSPSolve (_ksp, rhs->vec(), solution->vec());
1469 LIBMESH_CHKERR(
ierr);
1473 ierr = KSPGetIterationNumber (_ksp, &its);
1474 LIBMESH_CHKERR(
ierr);
1477 ierr = KSPGetResidualNorm (_ksp, &final_resid);
1478 LIBMESH_CHKERR(
ierr);
1480 if (_restrict_solve_to_is !=
nullptr)
1482 switch(_subset_solve_mode)
1485 ierr = VecZeroEntries(solution->vec());
1486 LIBMESH_CHKERR(
ierr);
1490 ierr = VecCopy(rhs->vec(),solution->vec());
1491 LIBMESH_CHKERR(
ierr);
1499 libmesh_error_msg(
"Invalid subset solve mode = " << _subset_solve_mode);
1501 ierr = VecScatterBegin(scatter,subsolution,solution->vec(),INSERT_VALUES,SCATTER_REVERSE);
1502 LIBMESH_CHKERR(
ierr);
1503 ierr = VecScatterEnd(scatter,subsolution,solution->vec(),INSERT_VALUES,SCATTER_REVERSE);
1504 LIBMESH_CHKERR(
ierr);
1506 ierr = LibMeshVecScatterDestroy(&scatter);
1507 LIBMESH_CHKERR(
ierr);
1509 if (this->_preconditioner)
1514 this->_preconditioner->init();
1517 ierr = LibMeshVecDestroy(&subsolution);
1518 LIBMESH_CHKERR(
ierr);
1519 ierr = LibMeshVecDestroy(&subrhs);
1520 LIBMESH_CHKERR(
ierr);
1521 ierr = LibMeshMatDestroy(&submat);
1522 LIBMESH_CHKERR(
ierr);
1523 ierr = LibMeshMatDestroy(&subprecond);
1524 LIBMESH_CHKERR(
ierr);
1528 ierr = LibMeshMatDestroy(&mat);
1529 LIBMESH_CHKERR(
ierr);
1532 return std::make_pair(its, final_resid);
1537 template <
typename T>
1540 PetscErrorCode
ierr = 0;
1550 ierr = KSPGetResidualHistory(_ksp, &p, &its);
1551 LIBMESH_CHKERR(
ierr);
1554 if (its == 0)
return;
1560 for (PetscInt i=0; i<its; ++i)
1570 template <
typename T>
1573 PetscErrorCode
ierr = 0;
1583 ierr = KSPGetResidualHistory(_ksp, &p, &its);
1584 LIBMESH_CHKERR(
ierr);
1589 libMesh::err <<
"No iterations have been performed, returning 0." << std::endl;
1600 template <
typename T>
1603 PetscErrorCode
ierr = 0;
1605 switch (this->_solver_type)
1609 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPCG));
1610 LIBMESH_CHKERR(
ierr);
1614 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPCR));
1615 LIBMESH_CHKERR(
ierr);
1619 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPCGS));
1620 LIBMESH_CHKERR(
ierr);
1624 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPBICG));
1625 LIBMESH_CHKERR(
ierr);
1629 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPTCQMR));
1630 LIBMESH_CHKERR(
ierr);
1634 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPTFQMR));
1635 LIBMESH_CHKERR(
ierr);
1639 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPLSQR));
1640 LIBMESH_CHKERR(
ierr);
1644 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPBCGS));
1645 LIBMESH_CHKERR(
ierr);
1649 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPMINRES));
1650 LIBMESH_CHKERR(
ierr);
1654 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPGMRES));
1655 LIBMESH_CHKERR(
ierr);
1659 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPRICHARDSON));
1660 LIBMESH_CHKERR(
ierr);
1664 #if defined(LIBMESH_HAVE_PETSC) && PETSC_VERSION_LESS_THAN(3,3,0)
1665 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPCHEBYCHEV));
1666 LIBMESH_CHKERR(
ierr);
1669 ierr = KSPSetType (_ksp, const_cast<KSPType>(KSPCHEBYSHEV));
1670 LIBMESH_CHKERR(
ierr);
1678 <<
"Continuing with PETSC defaults" << std::endl;
1684 template <
typename T>
1687 KSPConvergedReason reason;
1688 KSPGetConvergedReason(_ksp, &reason);
1692 #if !PETSC_VERSION_LESS_THAN(3,2,0)
1710 #if PETSC_VERSION_LESS_THAN(3,4,0)
1717 #if !PETSC_VERSION_LESS_THAN(3,7,0)
1719 #if PETSC_VERSION_LESS_THAN(3,11,0) && PETSC_VERSION_RELEASE
1727 libMesh::err <<
"Unknown convergence flag!" << std::endl;
1733 template <
typename T>
1737 PetscErrorCode
ierr=0;
1739 ierr = MatShellGetContext(mat,&
ctx);
1743 CHKERRABORT(shell_matrix.
comm().get(),
ierr);
1757 template <
typename T>
1761 PetscErrorCode
ierr=0;
1763 ierr = MatShellGetContext(mat,&
ctx);
1767 CHKERRABORT(shell_matrix.
comm().get(),
ierr);
1776 arg_global = add_global;
1787 template <
typename T>
1791 PetscErrorCode
ierr=0;
1793 ierr = MatShellGetContext(mat,&
ctx);
1797 CHKERRABORT(shell_matrix.
comm().get(),
ierr);
1818 #endif // #ifdef LIBMESH_HAVE_PETSC