22 #ifdef LIBMESH_HAVE_PETSC 40 #if PETSC_VERSION_LESS_THAN(3,4,0) 41 # define SNESGETLINESEARCH SNESGetSNESLineSearch 43 # define SNESGETLINESEARCH SNESGetLineSearch 52 PetscErrorCode ierr_in) :
66 LOG_SCOPE(
"residual()",
"PetscNonlinearSolver");
68 PetscErrorCode
ierr = 0;
81 PetscInt n_iterations = 0;
82 ierr = SNESGetIterationNumber(snes, &n_iterations);
128 << std::setw(2) << its
130 <<
", |residual|_2 = " << fnorm
137 #ifdef LIBMESH_ENABLE_DEPRECATED 141 libmesh_deprecated();
164 libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the Residual!");
167 libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
182 libmesh_error_msg(
"Error! Unable to compute residual and/or Jacobian!");
189 #ifdef LIBMESH_ENABLE_DEPRECATED 193 libmesh_deprecated();
218 libmesh_error_msg(
"Error! Unable to compute residual for forming finite difference Jacobian!");
225 #ifdef LIBMESH_ENABLE_DEPRECATED 229 libmesh_deprecated();
255 libmesh_error_msg(
"Error! Unable to compute residual for forming finite differenced" 256 "Jacobian-vector products!");
276 #ifdef LIBMESH_ENABLE_DEPRECATED 280 libmesh_deprecated();
289 #
if PETSC_RELEASE_LESS_THAN(3,5,0)
290 SNES snes, Vec x, Mat * jac, Mat * pc, MatStructure * msflag,
void * ctx
292 SNES snes, Vec x, Mat jac, Mat pc,
void * ctx
296 LOG_SCOPE(
"jacobian()",
"PetscNonlinearSolver");
298 PetscErrorCode
ierr=0;
310 PetscInt n_iterations = 0;
311 ierr = SNESGetIterationNumber(snes, &n_iterations);
317 #if PETSC_RELEASE_LESS_THAN(3,5,0) 332 X_global.
swap(X_sys);
334 X_global.swap(X_sys);
349 libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the Jacobian!");
352 libmesh_error_msg(
"ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!");
360 else if (solver->
matvec !=
nullptr)
367 libmesh_error_msg(
"Error! Unable to compute residual and/or Jacobian!");
371 #if PETSC_RELEASE_LESS_THAN(3,5,0) 372 *msflag = SAME_NONZERO_PATTERN;
394 #ifdef LIBMESH_ENABLE_DEPRECATED 397 #
if PETSC_RELEASE_LESS_THAN(3,5,0)
398 SNES snes, Vec x, Mat * jac, Mat * pc, MatStructure * msflag,
void * ctx
400 SNES snes, Vec x, Mat jac, Mat pc,
void * ctx
404 libmesh_deprecated();
406 #
if PETSC_RELEASE_LESS_THAN(3,5,0)
407 snes, x, jac, pc, msflag, ctx
409 snes, x, jac, pc, ctx
426 #
if PETSC_VERSION_LESS_THAN(3,3,0)
427 SNES, Vec x, Vec y, Vec w,
void * context,
PetscBool * changed_y,
PetscBool * changed_w
429 SNESLineSearch, Vec x, Vec y, Vec w,
PetscBool * changed_y,
PetscBool * changed_w,
void * context
433 LOG_SCOPE(
"postcheck()",
"PetscNonlinearSolver");
435 PetscErrorCode
ierr = 0;
439 *changed_w = PETSC_FALSE;
440 *changed_y = PETSC_FALSE;
442 libmesh_assert(context);
451 libmesh_error_msg(
"ERROR: cannot specify both a function and object for performing the solve postcheck!");
467 changed_search_direction =
false,
468 changed_new_soln =
false;
479 changed_search_direction,
487 changed_search_direction,
493 if (changed_search_direction)
494 *changed_y = PETSC_TRUE;
496 if (changed_new_soln)
497 *changed_w = PETSC_TRUE;
504 petsc_w.
swap(system_soln);
512 *changed_w = PETSC_TRUE;
515 petsc_w.swap(system_soln);
521 #ifdef LIBMESH_ENABLE_DEPRECATED 523 #
if PETSC_VERSION_LESS_THAN(3,3,0)
524 SNES, Vec x, Vec y, Vec w,
void * context,
PetscBool * changed_y,
PetscBool * changed_w
526 SNESLineSearch, Vec x, Vec y, Vec w,
PetscBool * changed_y,
PetscBool * changed_w,
void * context
530 libmesh_deprecated();
532 #
if PETSC_VERSION_LESS_THAN(3,3,0)
533 nullptr, x, y, w, context, changed_y, changed_w
535 nullptr, x, y, w, changed_y, changed_w, context
546 template <
typename T>
549 linesearch_object(nullptr),
550 _reason(SNES_CONVERGED_ITERATING),
551 _n_linear_iterations(0),
552 _current_nonlinear_iteration_number(0),
553 _zero_out_residual(true),
554 _zero_out_jacobian(true),
555 _default_monitor(true),
556 _snesmf_reuse_base(true)
562 template <
typename T>
570 template <
typename T>
577 PetscErrorCode
ierr=0;
579 ierr = LibMeshSNESDestroy(&_snes);
580 LIBMESH_CHKERR(
ierr);
585 _current_nonlinear_iteration_number = 0;
591 template <
typename T>
599 PetscErrorCode
ierr=0;
601 ierr = SNESCreate(this->comm().
get(),&_snes);
602 LIBMESH_CHKERR(
ierr);
606 ierr = SNESSetOptionsPrefix(_snes,
name);
607 LIBMESH_CHKERR(
ierr);
610 #if !PETSC_RELEASE_LESS_THAN(3,3,0) 613 ierr = DMCreate(this->comm().
get(), &dm);LIBMESH_CHKERR(
ierr);
614 ierr = DMSetType(dm,DMLIBMESH);LIBMESH_CHKERR(
ierr);
618 ierr = DMSetOptionsPrefix(dm,
name); LIBMESH_CHKERR(
ierr);
620 ierr = DMSetFromOptions(dm); LIBMESH_CHKERR(
ierr);
621 ierr = DMSetUp(dm); LIBMESH_CHKERR(
ierr);
622 ierr = SNESSetDM(this->_snes, dm); LIBMESH_CHKERR(
ierr);
624 ierr = DMDestroy(&dm); LIBMESH_CHKERR(
ierr);
628 if (_default_monitor)
632 LIBMESH_CHKERR(
ierr);
637 if (this->_solver_configuration)
639 this->_solver_configuration->set_options_during_init();
642 #if PETSC_VERSION_LESS_THAN(3,1,0) 645 ierr = SNESSetFromOptions(_snes);
646 LIBMESH_CHKERR(
ierr);
649 if (this->_preconditioner)
652 ierr = SNESGetKSP (_snes, &ksp);
653 LIBMESH_CHKERR(
ierr);
655 ierr = KSPGetPC(ksp,&pc);
656 LIBMESH_CHKERR(
ierr);
658 this->_preconditioner->init();
660 PCSetType(pc, PCSHELL);
661 PCShellSetContext(pc,(
void *)this->_preconditioner);
674 if (this->postcheck || this->postcheck_object)
676 #if PETSC_VERSION_LESS_THAN(3,3,0) 678 LIBMESH_CHKERR(
ierr);
681 SNESLineSearch linesearch;
682 PetscErrorCode
ierr = SNESGETLINESEARCH(_snes, &linesearch);
683 LIBMESH_CHKERR(
ierr);
686 LIBMESH_CHKERR(
ierr);
691 #if !PETSC_VERSION_LESS_THAN(3,3,0) 692 template <
typename T>
699 std::vector<NumericVector<Number> *> sp;
700 if (computeSubspaceObject)
701 (*computeSubspaceObject)(sp, this->system());
703 (*computeSubspace)(sp, this->system());
710 PetscInt nmodes = cast_int<PetscInt>(sp.size());
712 #if PETSC_RELEASE_LESS_THAN(3,5,0) 713 ierr = PetscMalloc2(nmodes,Vec,&modes,nmodes,PetscScalar,&dots);
715 ierr = PetscMalloc2(nmodes,&modes,nmodes,&dots);
717 LIBMESH_CHKERR(
ierr);
719 for (PetscInt i=0; i<nmodes; ++i)
724 ierr = VecDuplicate(v, modes+i);
725 LIBMESH_CHKERR(
ierr);
727 ierr = VecCopy(v,modes[i]);
728 LIBMESH_CHKERR(
ierr);
732 ierr = VecNormalize(modes[0],PETSC_NULL);
733 LIBMESH_CHKERR(
ierr);
735 for (PetscInt i=1; i<nmodes; i++)
738 ierr = VecMDot(modes[i],i,modes,dots);
739 LIBMESH_CHKERR(
ierr);
741 for (PetscInt j=0; j<i; j++)
744 ierr = VecMAXPY(modes[i],i,dots,modes);
745 LIBMESH_CHKERR(
ierr);
747 ierr = VecNormalize(modes[i],PETSC_NULL);
748 LIBMESH_CHKERR(
ierr);
751 ierr = MatNullSpaceCreate(this->comm().
get(), PETSC_FALSE, nmodes, modes, msp);
752 LIBMESH_CHKERR(
ierr);
754 for (PetscInt i=0; i<nmodes; ++i)
756 ierr = VecDestroy(modes+i);
757 LIBMESH_CHKERR(
ierr);
760 ierr = PetscFree2(modes,dots);
761 LIBMESH_CHKERR(
ierr);
766 template <
typename T>
767 std::pair<unsigned int, Real>
774 LOG_SCOPE(
"solve()",
"PetscNonlinearSolver");
782 PetscErrorCode
ierr=0;
783 PetscInt n_iterations =0;
785 Real final_residual_norm=0.;
788 LIBMESH_CHKERR(
ierr);
792 if (this->jacobian || this->jacobian_object || this->residual_and_jacobian_object)
795 LIBMESH_CHKERR(
ierr);
799 #if !PETSC_VERSION_LESS_THAN(3,3,0) 801 if (this->nullspace || this->nullspace_object)
804 this->build_mat_null_space(this->nullspace_object, this->nullspace, &msp);
807 ierr = MatSetNullSpace(pre->
mat(), msp);
808 LIBMESH_CHKERR(
ierr);
809 ierr = MatNullSpaceDestroy(&msp);
810 LIBMESH_CHKERR(
ierr);
815 if (this->transpose_nullspace || this->transpose_nullspace_object)
817 #if PETSC_VERSION_LESS_THAN(3,6,0) 818 libmesh_warning(
"MatSetTransposeNullSpace is only supported for PETSc >= 3.6, transpose nullspace will be ignored.");
820 MatNullSpace msp = PETSC_NULL;
821 this->build_mat_null_space(this->transpose_nullspace_object, this->transpose_nullspace, &msp);
824 ierr = MatSetTransposeNullSpace(pre->
mat(), msp);
825 LIBMESH_CHKERR(
ierr);
826 ierr = MatNullSpaceDestroy(&msp);
827 LIBMESH_CHKERR(
ierr);
833 if (this->nearnullspace || this->nearnullspace_object)
835 MatNullSpace msp = PETSC_NULL;
836 this->build_mat_null_space(this->nearnullspace_object, this->nearnullspace, &msp);
840 ierr = MatSetNearNullSpace(pre->
mat(), msp);
841 LIBMESH_CHKERR(
ierr);
842 ierr = MatNullSpaceDestroy(&msp);
843 LIBMESH_CHKERR(
ierr);
850 ierr = SNESGetKSP (_snes, &ksp);
851 LIBMESH_CHKERR(
ierr);
855 ierr = KSPSetTolerances (ksp, this->initial_linear_tolerance, PETSC_DEFAULT,
856 PETSC_DEFAULT, this->max_linear_iterations);
857 LIBMESH_CHKERR(
ierr);
860 ierr = SNESSetTolerances(_snes, this->absolute_residual_tolerance, this->relative_residual_tolerance,
861 this->relative_step_tolerance, this->max_nonlinear_iterations, this->max_function_evaluations);
862 LIBMESH_CHKERR(
ierr);
865 #if PETSC_VERSION_LESS_THAN(3,7,0) 866 KSPSetFromOptions(ksp);
868 SNESSetFromOptions(_snes);
870 if (this->user_presolve)
871 this->user_presolve(this->system());
874 if (this->_preconditioner)
876 this->_preconditioner->set_matrix(pre_in);
877 this->_preconditioner->init();
882 if (this->_solver_configuration)
884 this->_solver_configuration->configure_solver();
899 #if !PETSC_VERSION_LESS_THAN(3,5,0) 900 #if !PETSC_VERSION_LESS_THAN(3,6,0) 901 ierr = SNESSetSolution(_snes, x->vec());
902 LIBMESH_CHKERR(
ierr);
904 ierr = SNESSetUp(_snes);
905 LIBMESH_CHKERR(
ierr);
908 ierr = SNESGetJacobian(_snes,&J,PETSC_NULL,PETSC_NULL,PETSC_NULL);
909 LIBMESH_CHKERR(
ierr);
911 LIBMESH_CHKERR(
ierr);
912 #if !PETSC_VERSION_LESS_THAN(3, 8, 4) 914 ierr = MatSNESMFSetReuseBase(J, static_cast<PetscBool>(_snesmf_reuse_base));
915 LIBMESH_CHKERR(
ierr);
919 #if PETSC_VERSION_LESS_THAN(3, 3, 0) 920 if (linesearch_object)
921 libmesh_error_msg(
"Line search setter interface introduced in petsc version 3.3!");
923 SNESLineSearch linesearch;
924 if (linesearch_object)
926 ierr = SNESGETLINESEARCH(_snes, &linesearch);
927 LIBMESH_CHKERR(
ierr);
928 ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHSHELL);
929 LIBMESH_CHKERR(
ierr);
931 LIBMESH_CHKERR(
ierr);
935 ierr = SNESSolve (_snes, PETSC_NULL, x->vec());
936 LIBMESH_CHKERR(
ierr);
938 ierr = SNESGetIterationNumber(_snes,&n_iterations);
939 LIBMESH_CHKERR(
ierr);
941 ierr = SNESGetLinearSolveIterations(_snes, &_n_linear_iterations);
942 LIBMESH_CHKERR(
ierr);
948 this->system().get_dof_map().enforce_constraints_exactly(this->system());
955 ierr = SNESGetFunction(_snes, &f, 0, 0);
956 LIBMESH_CHKERR(
ierr);
957 ierr = VecNorm(f, NORM_2, &final_residual_norm);
958 LIBMESH_CHKERR(
ierr);
961 SNESGetConvergedReason(_snes, &_reason);
964 this->converged = (_reason >= 0);
969 return std::make_pair(n_iterations, final_residual_norm);
974 template <
typename T>
978 libMesh::out <<
"Nonlinear solver convergence/divergence reason: " 979 << SNESConvergedReasons[this->get_converged_reason()] << std::endl;
984 template <
typename T>
987 PetscErrorCode
ierr=0;
991 ierr = SNESGetConvergedReason(_snes, &_reason);
992 LIBMESH_CHKERR(
ierr);
998 template <
typename T>
1001 return _n_linear_iterations;
1013 #endif // #ifdef LIBMESH_HAVE_PETSC unsigned _current_nonlinear_iteration_number
std::string name(const ElemQuality q)
PetscNonlinearSolver< Number > * solver
NumericVector interface to PETSc Vec.
PetscErrorCode libmesh_petsc_snes_postcheck(#if PETSC_VERSION_LESS_THAN(3, 3, 0) SNES, Vec x, Vec y, Vec w, void *context, PetscBool *changed_y, PetscBool *changed_w #else SNESLineSearch, Vec x, Vec y, Vec w, PetscBool *changed_y, PetscBool *changed_w, void *context #endif)
void(* residual)(const NumericVector< Number > &X, NumericVector< Number > &R, sys_type &S)
NonlinearImplicitSystem::ComputeResidualandJacobian * residual_and_jacobian_object
virtual void residual(const NumericVector< Number > &X, NumericVector< Number > &R, sys_type &S)=0
virtual void zero() override
PetscNonlinearSolver(sys_type &system)
PetscErrorCode __libmesh_petsc_snes_residual(SNES snes, Vec x, Vec r, void *ctx)
NonlinearImplicitSystem & sys
PetscErrorCode __libmesh_petsc_snes_monitor(SNES, PetscInt its, PetscReal fnorm, void *)
const Parallel::Communicator & comm() const
NonlinearImplicitSystem::ComputeResidual * residual_object
void(* jacobian)(const NumericVector< Number > &X, SparseMatrix< Number > &J, sys_type &S)
PetscErrorCode libmesh_petsc_snes_monitor(SNES, PetscInt its, PetscReal fnorm, void *)
PetscErrorCode __libmesh_petsc_snes_mffd_interface(void *ctx, Vec x, Vec r)
virtual void postcheck(const NumericVector< Number > &old_soln, NumericVector< Number > &search_direction, NumericVector< Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln, sys_type &S)=0
virtual void swap(NumericVector< T > &v) override
PetscErrorCode libmesh_petsc_snes_mffd_residual(SNES snes, Vec x, Vec r, void *ctx)
Manages the degrees of freedom (DOFs) in a simulation.
PetscErrorCode __libmesh_petsc_snes_jacobian(#if PETSC_RELEASE_LESS_THAN(3, 5, 0) SNES snes, Vec x, Mat *jac, Mat *pc, MatStructure *msflag, void *ctx #else SNES snes, Vec x, Mat jac, Mat pc, void *ctx #endif)
const sys_type & system() const
NonlinearImplicitSystem::ComputeJacobian * jacobian_object
PetscErrorCode libmesh_petsc_snes_residual(SNES snes, Vec x, Vec r, void *ctx)
PetscErrorCode libmesh_petsc_preconditioner_setup(void *ctx)
ResidualContext(PetscNonlinearSolver< Number > *solver_in, NonlinearImplicitSystem &sys_in, PetscErrorCode ierr_in)
virtual void jacobian(const NumericVector< Number > &X, SparseMatrix< Number > &J, sys_type &S)=0
std::unique_ptr< NumericVector< Number > > solution
void init(triangulateio &t)
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
ResidualContext libmesh_petsc_snes_residual_helper(SNES snes, Vec x, void *ctx)
PetscErrorCode libmesh_petsc_snes_jacobian(#if PETSC_RELEASE_LESS_THAN(3, 5, 0) SNES snes, Vec x, Mat *jac, Mat *pc, MatStructure *msflag, void *ctx #else SNES snes, Vec x, Mat jac, Mat pc, void *ctx #endif)
PetscErrorCode libmesh_petsc_snes_fd_residual(SNES snes, Vec x, Vec r, void *ctx)
PetscErrorCode libmesh_petsc_snes_mffd_interface(void *ctx, Vec x, Vec r)
PetscErrorCode DMlibMeshSetSystem(DM dm, libMesh::NonlinearImplicitSystem &sys)
PetscErrorCode libmesh_petsc_linesearch_shellfunc(SNESLineSearch linesearch, void *ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::unique_ptr< ComputeLineSearchObject > linesearch_object
NonlinearImplicitSystem::ComputePostCheck * postcheck_object
dof_id_type n_constrained_dofs() const
PetscErrorCode __libmesh_petsc_snes_postcheck(#if PETSC_VERSION_LESS_THAN(3, 3, 0) SNES, Vec x, Vec y, Vec w, void *context, PetscBool *changed_y, PetscBool *changed_w #else SNESLineSearch, Vec x, Vec y, Vec w, PetscBool *changed_y, PetscBool *changed_w, void *context #endif)
PetscErrorCode libmesh_petsc_preconditioner_apply(void *ctx, Vec x, Vec y)
NonlinearImplicitSystem::ComputeResidual * mffd_residual_object
SparseMatrix interface to PETSc Mat.
std::unique_ptr< NumericVector< Number > > current_local_solution
void(* postcheck)(const NumericVector< Number > &old_soln, NumericVector< Number > &search_direction, NumericVector< Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln, sys_type &S)
OStreamProxy out(std::cout)
const DofMap & get_dof_map() const
virtual void residual_and_jacobian(const NumericVector< Number > &X, NumericVector< Number > *R, SparseMatrix< Number > *J, sys_type &S)=0
PetscErrorCode __libmesh_petsc_snes_fd_residual(SNES snes, Vec x, Vec r, void *ctx)
void(* matvec)(const NumericVector< Number > &X, NumericVector< Number > *R, SparseMatrix< Number > *J, sys_type &S)
NonlinearImplicitSystem::ComputeResidual * fd_residual_object
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const