13 #include "libmesh/petsc_nonlinear_solver.h" 14 #include "libmesh/petsc_solver_exception.h" 28 _solver =
dynamic_cast<PetscNonlinearSolver<Real> *
>(
32 "This line search operates only with Petsc, so Petsc must be your nonlinear solver.");
38 PetscBool changed_y = PETSC_FALSE, changed_w = PETSC_FALSE;
39 Vec
X,
F,
Y, W,
G, W1;
40 SNESLineSearch line_search;
41 PetscReal fnorm, xnorm, ynorm, gnorm;
42 PetscReal ksp_rtol, ksp_abstol, ksp_dtol;
47 LibmeshPetscCall(SNESGetLineSearch(snes, &line_search));
48 LibmeshPetscCall(SNESLineSearchGetVecs(line_search, &
X, &
F, &
Y, &W, &
G));
49 LibmeshPetscCall(SNESLineSearchGetNorms(line_search, &xnorm, &fnorm, &ynorm));
50 LibmeshPetscCall(SNESLineSearchGetSNES(line_search, &snes));
51 LibmeshPetscCall(SNESLineSearchSetReason(line_search, SNES_LINESEARCH_SUCCEEDED));
52 LibmeshPetscCall(SNESGetKSP(snes, &ksp));
53 LibmeshPetscCall(KSPGetTolerances(ksp, &ksp_rtol, &ksp_abstol, &ksp_dtol, &ksp_maxits));
54 LibmeshPetscCall(VecDuplicate(W, &W1));
65 LibmeshPetscCall(SNESLineSearchPreCheck(line_search,
X,
Y, &changed_y));
74 LibmeshPetscCall(SNESComputeFunction(snes, W,
F));
75 #if PETSC_VERSION_LESS_THAN(3, 25, 0) 76 PetscBool domainerror;
77 LibmeshPetscCall(SNESGetFunctionDomainError(snes, &domainerror));
79 LibmeshPetscCall(SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_DOMAIN));
81 SNESConvergedReason reason;
82 LibmeshPetscCall(SNESGetConvergedReason(snes, &reason));
83 if (reason == SNES_DIVERGED_FUNCTION_DOMAIN)
84 LibmeshPetscCall(SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_FUNCTION_DOMAIN));
87 LibmeshPetscCall(VecNorm(
F, NORM_2, &fnorm));
96 LibmeshPetscCall(KSPSetTolerances(ksp,
_contact_ltol, ksp_abstol, ksp_dtol, ksp_maxits));
97 _console <<
"Contact set changed since previous non-linear iteration!" << std::endl;
100 LibmeshPetscCall(KSPSetTolerances(ksp,
_user_ksp_rtol, ksp_abstol, ksp_dtol, ksp_maxits));
110 LibmeshPetscCall(SNESComputeFunction(snes, W1,
G));
111 #if PETSC_VERSION_LESS_THAN(3, 25, 0) 112 LibmeshPetscCall(SNESGetFunctionDomainError(snes, &domainerror));
114 LibmeshPetscCall(SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_DOMAIN));
116 LibmeshPetscCall(SNESGetConvergedReason(snes, &reason));
117 if (reason == SNES_DIVERGED_FUNCTION_DOMAIN)
119 SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_FUNCTION_DOMAIN));
122 LibmeshPetscCall(VecNorm(
G, NORM_2, &gnorm));
125 LibmeshPetscCall(VecCopy(
G,
F));
126 LibmeshPetscCall(VecCopy(W1, W));
139 LibmeshPetscCall(SNESLineSearchPostCheck(line_search,
X,
Y, W, &changed_y, &changed_w));
142 LibmeshPetscCall(VecWAXPY(W, -1.,
Y,
X));
144 if (changed_w || changed_y)
146 LibmeshPetscCall(SNESComputeFunction(snes, W,
F));
147 #if PETSC_VERSION_LESS_THAN(3, 25, 0) 148 LibmeshPetscCall(SNESGetFunctionDomainError(snes, &domainerror));
150 LibmeshPetscCall(SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_DOMAIN));
152 LibmeshPetscCall(SNESGetConvergedReason(snes, &reason));
153 if (reason == SNES_DIVERGED_FUNCTION_DOMAIN)
155 SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_FUNCTION_DOMAIN));
163 LibmeshPetscCall(VecCopy(W,
X));
165 LibmeshPetscCall(SNESLineSearchComputeNorms(line_search));
167 LibmeshPetscCall(VecDestroy(&W1));
SNES snes(const char *name=nullptr)
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver() override
static const std::string F
static const std::string G
void mooseError(Args &&... args) const
const ConsoleStream _console
virtual NonlinearSystem & getNonlinearSystem(const unsigned int nl_sys_num) override