static PetscErrorCode SNESSolve_KSPONLY(SNES snes) { PetscErrorCode ierr; PetscInt lits; Vec Y,X,F; PetscFunctionBegin; if (snes->xl || snes->xu || snes->ops->computevariablebounds) { SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); } snes->numFailures = 0; snes->numLinearSolveFailures = 0; snes->reason = SNES_CONVERGED_ITERATING; snes->iter = 0; snes->norm = 0.0; X = snes->vec_sol; F = snes->vec_func; Y = snes->vec_sol_update; ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->numbermonitors) { PetscReal fnorm; ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); } /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, 0);CHKERRQ(ierr); } /* Solve J Y = F, where J is Jacobian matrix */ ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); ierr = KSPSolve(snes->ksp,F,Y);CHKERRQ(ierr); snes->reason = SNES_CONVERGED_ITS; SNESCheckKSPSolve(snes); ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); snes->linear_its += lits; ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); snes->iter++; /* Take the computed step. */ ierr = VecAXPY(X,-1.0,Y);CHKERRQ(ierr); if (snes->numbermonitors) { PetscReal fnorm; ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); ierr = SNESMonitor(snes,1,fnorm);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode SNESNASMComputeFinalJacobian_Private(SNES snes, Vec Xfinal) { Vec X = Xfinal; SNES_NASM *nasm = (SNES_NASM*)snes->data; SNES subsnes; PetscInt i,lag = 1; PetscErrorCode ierr; Vec Xlloc,Xl,Fl,F; VecScatter oscat,gscat; DM dm,subdm; MatStructure flg = DIFFERENT_NONZERO_PATTERN; PetscFunctionBegin; if (nasm->fjtype == 2) X = nasm->xinit; F = snes->vec_func; if (snes->normschedule == SNES_NORM_NONE) {ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);} ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); if (nasm->eventrestrictinterp) {ierr = PetscLogEventBegin(nasm->eventrestrictinterp,snes,0,0,0);CHKERRQ(ierr);} if (nasm->fjtype != 1) { for (i=0; i<nasm->n; i++) { Xlloc = nasm->xl[i]; gscat = nasm->gscatter[i]; oscat = nasm->oscatter[i]; ierr = VecScatterBegin(gscat,X,Xlloc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); } } if (nasm->eventrestrictinterp) {ierr = PetscLogEventEnd(nasm->eventrestrictinterp,snes,0,0,0);CHKERRQ(ierr);} for (i=0; i<nasm->n; i++) { Fl = nasm->subsnes[i]->vec_func; Xl = nasm->x[i]; Xlloc = nasm->xl[i]; subsnes = nasm->subsnes[i]; oscat = nasm->oscatter[i]; gscat = nasm->gscatter[i]; if (nasm->fjtype != 1) {ierr = VecScatterEnd(gscat,X,Xlloc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);} ierr = SNESGetDM(subsnes,&subdm);CHKERRQ(ierr); ierr = DMSubDomainRestrict(dm,oscat,gscat,subdm);CHKERRQ(ierr); if (nasm->fjtype != 1) { ierr = DMLocalToGlobalBegin(subdm,Xlloc,INSERT_VALUES,Xl);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(subdm,Xlloc,INSERT_VALUES,Xl);CHKERRQ(ierr); } if (subsnes->lagjacobian == -1) subsnes->lagjacobian = -2; else if (subsnes->lagjacobian > 1) lag = subsnes->lagjacobian; ierr = SNESComputeFunction(subsnes,Xl,Fl);CHKERRQ(ierr); ierr = SNESComputeJacobian(subsnes,Xl,&subsnes->jacobian,&subsnes->jacobian_pre,&flg);CHKERRQ(ierr); if (lag > 1) subsnes->lagjacobian = lag; ierr = KSPSetOperators(subsnes->ksp,subsnes->jacobian,subsnes->jacobian_pre,flg);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* X - initial state, updated in-place. F - residual, computed at the initial X on input */ static PetscErrorCode SNESMSStep_3Sstar(SNES snes,Vec X,Vec F) { PetscErrorCode ierr; SNES_MS *ms = (SNES_MS*)snes->data; SNESMSTableau t = ms->tableau; const PetscReal *gamma = t->gamma,*delta = t->delta,*betasub = t->betasub; Vec S1,S2,S3,Y; PetscInt i,nstages = t->nstages;; PetscFunctionBegin; Y = snes->work[0]; S1 = X; S2 = snes->work[1]; S3 = snes->work[2]; ierr = VecZeroEntries(S2);CHKERRQ(ierr); ierr = VecCopy(X,S3);CHKERRQ(ierr); for (i=0; i<nstages; i++) { Vec Ss[4] = {S1,S2,S3,Y}; PetscScalar scoeff[4] = {gamma[0*nstages+i]-1.0,gamma[1*nstages+i],gamma[2*nstages+i],-betasub[i]*ms->damping}; ierr = VecAXPY(S2,delta[i],S1);CHKERRQ(ierr); if (i>0) { ierr = SNESComputeFunction(snes,S1,F);CHKERRQ(ierr); if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } } ierr = SNES_KSPSolve(snes,snes->ksp,F,Y);CHKERRQ(ierr); ierr = VecMAXPY(S1,4,scoeff,Ss);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode KSPMonitorSNESLGResidualNorm(KSP ksp,PetscInt n,PetscReal rnorm,PetscObject *objs) { SNES snes = (SNES) objs[0]; PetscDrawLG lg = (PetscDrawLG) objs[1]; PetscErrorCode ierr; PetscReal y[2]; Vec snes_solution,work1,work2; PetscFunctionBegin; if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm); else y[0] = -15.0; ierr = SNESGetSolution(snes,&snes_solution);CHKERRQ(ierr); ierr = VecDuplicate(snes_solution,&work1);CHKERRQ(ierr); ierr = VecDuplicate(snes_solution,&work2);CHKERRQ(ierr); ierr = KSPBuildSolution(ksp,work1,NULL);CHKERRQ(ierr); ierr = VecAYPX(work1,-1.0,snes_solution);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,work1,work2);CHKERRQ(ierr); ierr = VecNorm(work2,NORM_2,y+1);CHKERRQ(ierr); if (y[1] > 0.0) y[1] = PetscLog10Real(y[1]); else y[1] = -15.0; ierr = VecDestroy(&work1);CHKERRQ(ierr); ierr = VecDestroy(&work2);CHKERRQ(ierr); ierr = PetscDrawLGAddPoint(lg,NULL,y);CHKERRQ(ierr); if (n < 20 || !(n % 5)) { ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@C KSPMonitorSNES - Print the residual norm of the nonlinear function at each iteration of the linear iterative solver. Collective on KSP Input Parameters: + ksp - iterative context . n - iteration number . rnorm - 2-norm (preconditioned) residual value (may be estimated). - dummy - unused monitor context Level: intermediate .keywords: KSP, default, monitor, residual .seealso: KSPMonitorSet(), KSPMonitorTrueResidualNorm(), KSPMonitorLGResidualNormCreate() @*/ PetscErrorCode KSPMonitorSNES(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy) { PetscErrorCode ierr; PetscViewer viewer; SNES snes = (SNES) dummy; Vec snes_solution,work1,work2; PetscReal snorm; PetscFunctionBegin; ierr = SNESGetSolution(snes,&snes_solution);CHKERRQ(ierr); ierr = VecDuplicate(snes_solution,&work1);CHKERRQ(ierr); ierr = VecDuplicate(snes_solution,&work2);CHKERRQ(ierr); ierr = KSPBuildSolution(ksp,work1,NULL);CHKERRQ(ierr); ierr = VecAYPX(work1,-1.0,snes_solution);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,work1,work2);CHKERRQ(ierr); ierr = VecNorm(work2,NORM_2,&snorm);CHKERRQ(ierr); ierr = VecDestroy(&work1);CHKERRQ(ierr); ierr = VecDestroy(&work2);CHKERRQ(ierr); ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ksp),&viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);CHKERRQ(ierr); if (n == 0 && ((PetscObject)ksp)->prefix) { ierr = PetscViewerASCIIPrintf(viewer," Residual norms for %s solve.\n",((PetscObject)ksp)->prefix);CHKERRQ(ierr); } ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES Residual norm %5.3e KSP Residual norm %5.3e \n",n,(double)snorm,(double)rnorm);CHKERRQ(ierr); ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ SNESGetNPCFunction - Gets the function from a preconditioner after SNESSolve() has been called. Collective on SNES Input Parameters: . snes - the SNES context Output Parameter: . F - function vector . fnorm - the norm of F Level: developer .keywords: SNES, nonlinear, function .seealso: SNESGetNPC(),SNESSetNPC(),SNESComputeFunction(),SNESApplyNPC(),SNESSolve() @*/ PetscErrorCode SNESGetNPCFunction(SNES snes,Vec F,PetscReal *fnorm) { PetscErrorCode ierr; PCSide npcside; SNESFunctionType functype; SNESNormSchedule normschedule; Vec FPC,XPC; PetscFunctionBegin; if (snes->pc) { ierr = SNESGetNPCSide(snes->pc,&npcside);CHKERRQ(ierr); ierr = SNESGetFunctionType(snes->pc,&functype);CHKERRQ(ierr); ierr = SNESGetNormSchedule(snes->pc,&normschedule);CHKERRQ(ierr); /* check if the function is valid based upon how the inner solver is preconditioned */ if (normschedule != SNES_NORM_NONE && normschedule != SNES_NORM_INITIAL_ONLY && (npcside == PC_RIGHT || functype == SNES_FUNCTION_UNPRECONDITIONED)) { ierr = SNESGetFunction(snes->pc,&FPC,NULL,NULL);CHKERRQ(ierr); if (FPC) { if (fnorm) {ierr = SNESGetFunctionNorm(snes->pc,fnorm);CHKERRQ(ierr);} ierr = VecCopy(FPC,F);CHKERRQ(ierr); } else { SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Preconditioner has no function"); } } else { ierr = SNESGetSolution(snes->pc,&XPC);CHKERRQ(ierr); if (XPC) { ierr = SNESComputeFunction(snes->pc,XPC,F);CHKERRQ(ierr); if (fnorm) {ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);} } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Preconditioner has no solution"); } } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No preconditioner set"); PetscFunctionReturn(0); }
EXTERN_C_END #undef __FUNCT__ #define __FUNCT__ "SNESNCGComputeYtJtF_Private" /* Assuming F = SNESComputeFunction(X) compute Y^tJ^tF using a simple secant approximation of the jacobian. */ PetscErrorCode SNESNCGComputeYtJtF_Private(SNES snes, Vec X, Vec F, Vec Y, Vec W, Vec G, PetscScalar * ytJtf) { PetscErrorCode ierr; PetscScalar ftf, ftg, fty, h; PetscFunctionBegin; ierr = VecDot(F, F, &ftf); CHKERRQ(ierr); ierr = VecDot(F, Y, &fty); CHKERRQ(ierr); h = 1e-5*fty / fty; ierr = VecCopy(X, W); CHKERRQ(ierr); ierr = VecAXPY(W, -h, Y); CHKERRQ(ierr); /* this is arbitrary */ ierr = SNESComputeFunction(snes, W, G); CHKERRQ(ierr); ierr = VecDot(G, F, &ftg); CHKERRQ(ierr); *ytJtf = (ftg - ftf) / h; PetscFunctionReturn(0); }
/* Performs the FAS coarse correction as: fine problem: F(x) = b coarse problem: F^c(x^c) = b^c b^c = F^c(Rx) - R(F(x) - b) */ PetscErrorCode SNESFASCoarseCorrection(SNES snes, Vec X, Vec F, Vec X_new) { PetscErrorCode ierr; Vec X_c, Xo_c, F_c, B_c; SNESConvergedReason reason; SNES next; Mat restrct, interpolate; SNES_FAS *fasc; PetscFunctionBegin; ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); if (next) { fasc = (SNES_FAS*)next->data; ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); X_c = next->vec_sol; Xo_c = next->work[0]; F_c = next->vec_func; B_c = next->vec_rhs; if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} ierr = SNESFASRestrict(snes,X,Xo_c);CHKERRQ(ierr); /* restrict the defect: R(F(x) - b) */ ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} /* F_c = F^c(Rx) - R(F(x) - b) since the second term was sitting in next->vec_rhs */ ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} /* solve the coarse problem corresponding to F^c(x^c) = b^c = F^c(Rx) - R(F(x) - b) */ ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); /* set initial guess of the coarse problem to the projected fine solution */ ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); /* recurse to the next level */ ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } /* correct as x <- x + I(x^c - Rx)*/ ierr = VecAXPY(X_c, -1.0, Xo_c);CHKERRQ(ierr); if (fasc->eventinterprestrict) {ierr = PetscLogEventBegin(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} ierr = MatInterpolateAdd(interpolate, X_c, X, X_new);CHKERRQ(ierr); if (fasc->eventinterprestrict) {ierr = PetscLogEventEnd(fasc->eventinterprestrict,0,0,0,0);CHKERRQ(ierr);} } PetscFunctionReturn(0); }
int main(int argc, char **argv) { SNES snes; /* nonlinear solver */ Mat A,J; /* Jacobian,preconditioner matrix */ Vec u,r; /* solution, residual vectors */ AppCtx user; /* user-defined work context */ PetscReal error = 0.0; /* L_2 error in the solution */ PetscErrorCode ierr; ierr = PetscInitialize(&argc, &argv, NULL, help);CHKERRQ(ierr); ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD, &snes);CHKERRQ(ierr); ierr = CreateMesh(PETSC_COMM_WORLD, &user, &user.dm);CHKERRQ(ierr); ierr = SNESSetDM(snes, user.dm);CHKERRQ(ierr); ierr = SetupExactSolution(&user);CHKERRQ(ierr); ierr = SetupQuadrature(&user);CHKERRQ(ierr); ierr = SetupSection(user.dm, &user);CHKERRQ(ierr); ierr = DMCreateGlobalVector(user.dm, &u);CHKERRQ(ierr); ierr = VecDuplicate(u, &r);CHKERRQ(ierr); ierr = DMSetMatType(user.dm,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(user.dm, &J);CHKERRQ(ierr); A = J; ierr = DMSNESSetFunctionLocal(user.dm, (PetscErrorCode (*)(DM,Vec,Vec,void*))FormFunctionLocal,&user);CHKERRQ(ierr); ierr = DMSNESSetJacobianLocal(user.dm, (PetscErrorCode (*)(DM,Vec,Mat,Mat,void*))FormJacobianLocal,&user);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); { PetscReal res; /* Check discretization error */ ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial guess\n");CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); /* ierr = ComputeError(u, &error, &user);CHKERRQ(ierr); */ ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %g\n", error);CHKERRQ(ierr); /* Check residual */ ierr = SNESComputeFunction(snes,u,r);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial Residual\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecView(r, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Residual: %g\n", res);CHKERRQ(ierr); } ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&user.dm);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
PetscErrorCode SNESLineSearchApply_NCGLinear(SNESLineSearch linesearch) { PetscScalar alpha, ptAp; Vec X, Y, F, W; SNES snes; PetscErrorCode ierr; PetscReal *fnorm, *xnorm, *ynorm; MatStructure flg = DIFFERENT_NONZERO_PATTERN; PetscFunctionBegin; ierr = SNESLineSearchGetSNES(linesearch, &snes); CHKERRQ(ierr); X = linesearch->vec_sol; W = linesearch->vec_sol_new; F = linesearch->vec_func; Y = linesearch->vec_update; fnorm = &linesearch->fnorm; xnorm = &linesearch->xnorm; ynorm = &linesearch->ynorm; /* The exact step size for unpreconditioned linear CG is just: alpha = (r, r) / (p, Ap) = (f, f) / (y, Jy) */ ierr = SNESComputeJacobian(snes, X, &snes->jacobian, &snes->jacobian_pre, &flg); CHKERRQ(ierr); ierr = VecDot(F, F, &alpha); CHKERRQ(ierr); ierr = MatMult(snes->jacobian, Y, W); CHKERRQ(ierr); ierr = VecDot(Y, W, &ptAp); CHKERRQ(ierr); alpha = alpha / ptAp; ierr = PetscPrintf(((PetscObject)snes)->comm, "alpha: %G\n", PetscRealPart(alpha)); CHKERRQ(ierr); ierr = VecAXPY(X, alpha, Y); CHKERRQ(ierr); ierr = SNESComputeFunction(snes, X, F); CHKERRQ(ierr); ierr = VecNorm(F, NORM_2, fnorm); CHKERRQ(ierr); ierr = VecNorm(X, NORM_2, xnorm); CHKERRQ(ierr); ierr = VecNorm(Y, NORM_2, ynorm); CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Assuming F = SNESComputeFunction(X) compute Y^tJ^tF using a simple secant approximation of the jacobian. */ PetscErrorCode SNESNCGComputeYtJtF_Private(SNES snes, Vec X, Vec F, Vec Y, Vec W, Vec G, PetscScalar * ytJtf) { PetscErrorCode ierr; PetscScalar ftf, ftg, fty, h; PetscFunctionBegin; ierr = VecDot(F, F, &ftf);CHKERRQ(ierr); ierr = VecDot(F, Y, &fty);CHKERRQ(ierr); h = 1e-5*fty / fty; ierr = VecCopy(X, W);CHKERRQ(ierr); ierr = VecAXPY(W, -h, Y);CHKERRQ(ierr); /* this is arbitrary */ ierr = SNESComputeFunction(snes, W, G);CHKERRQ(ierr); ierr = VecDot(G, F, &ftg);CHKERRQ(ierr); *ytJtf = (ftg - ftf) / h; PetscFunctionReturn(0); }
PetscErrorCode SNESComputeFunctionDefaultNPC(SNES snes,Vec X,Vec F) { /* This is to be used as an argument to SNESMF -- NOT as a "function" */ SNESConvergedReason reason; PetscErrorCode ierr; PetscFunctionBegin; if (snes->pc) { ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { ierr = SNESSetFunctionDomainError(snes);CHKERRQ(ierr); } } else { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode SNESLineSearchApply_NCGLinear(SNESLineSearch linesearch) { PetscScalar alpha, ptAp; Vec X, Y, F, W; SNES snes; PetscErrorCode ierr; PetscReal *fnorm, *xnorm, *ynorm; PetscFunctionBegin; ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); X = linesearch->vec_sol; W = linesearch->vec_sol_new; F = linesearch->vec_func; Y = linesearch->vec_update; fnorm = &linesearch->fnorm; xnorm = &linesearch->xnorm; ynorm = &linesearch->ynorm; if (!snes->jacobian) { ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); } /* The exact step size for unpreconditioned linear CG is just: alpha = (r, r) / (p, Ap) = (f, f) / (y, Jy) */ ierr = SNESComputeJacobian(snes, X, snes->jacobian, snes->jacobian_pre);CHKERRQ(ierr); ierr = VecDot(F, F, &alpha);CHKERRQ(ierr); ierr = MatMult(snes->jacobian, Y, W);CHKERRQ(ierr); ierr = VecDot(Y, W, &ptAp);CHKERRQ(ierr); alpha = alpha / ptAp; ierr = VecAXPY(X,-alpha,Y);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr); ierr = VecNorm(X,NORM_2,xnorm);CHKERRQ(ierr); ierr = VecNorm(Y,NORM_2,ynorm);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C SNESLineSearchNo - This routine is not a line search at all; it simply uses the full Newton step. Thus, this routine is intended to serve as a template and is not recommended for general use. Collective on SNES and Vec Input Parameters: + snes - nonlinear context . lsctx - optional context for line search (not used here) . x - current iterate . f - residual evaluated at x . y - search direction . fnorm - 2-norm of f - xnorm - norm of x if known, otherwise 0 Output Parameters: + g - residual evaluated at new iterate y . w - new iterate . gnorm - 2-norm of g . ynorm - 2-norm of search length - flag - PETSC_TRUE on success, PETSC_FALSE on failure Options Database Key: . -snes_ls basic - Activates SNESLineSearchNo() Level: advanced .keywords: SNES, nonlinear, line search, cubic .seealso: SNESLineSearchCubic(), SNESLineSearchQuadratic(), SNESLineSearchSet(), SNESLineSearchNoNorms() @*/ PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchNo(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscTruth *flag) { PetscErrorCode ierr; SNES_LS *neP = (SNES_LS*)snes->data; PetscTruth changed_w = PETSC_FALSE,changed_y = PETSC_FALSE; PetscFunctionBegin; *flag = PETSC_TRUE; ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr); ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr); /* ynorm = || y || */ ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ if (neP->postcheckstep) { ierr = (*neP->postcheckstep)(snes,x,y,w,neP->postcheck,&changed_y,&changed_w);CHKERRQ(ierr); } if (changed_y) { ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr); /* w <- x - y */ } ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr); if (!snes->domainerror) { ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr); /* gnorm = || g || */ if PetscIsInfOrNanReal(*gnorm) SETERRQ(PETSC_ERR_FP,"User provided compute function generated a Not-a-Number"); }
/* X - initial state, updated in-place. F - residual, computed at the initial X on input */ static PetscErrorCode SNESMSStep_3Sstar(SNES snes,Vec X,Vec F) { PetscErrorCode ierr; SNES_MS *ms = (SNES_MS*)snes->data; SNESMSTableau t = ms->tableau; const PetscReal *gamma = t->gamma,*delta = t->delta,*betasub = t->betasub; Vec S1,S2,S3,Y; PetscInt i,nstages = t->nstages;; PetscFunctionBegin; Y = snes->work[0]; S1 = X; S2 = snes->work[1]; S3 = snes->work[2]; ierr = VecZeroEntries(S2);CHKERRQ(ierr); ierr = VecCopy(X,S3);CHKERRQ(ierr); for (i=0; i<nstages; i++) { Vec Ss[4]; PetscScalar scoeff[4]; Ss[0] = S1; Ss[1] = S2; Ss[2] = S3; Ss[3] = Y; scoeff[0] = gamma[0*nstages+i]-(PetscReal)1.0; scoeff[1] = gamma[1*nstages+i]; scoeff[2] = gamma[2*nstages+i]; scoeff[3] = -betasub[i]*ms->damping; ierr = VecAXPY(S2,delta[i],S1);CHKERRQ(ierr); if (i>0) { ierr = SNESComputeFunction(snes,S1,F);CHKERRQ(ierr); } ierr = KSPSolve(snes->ksp,F,Y);CHKERRQ(ierr); ierr = VecMAXPY(S1,4,scoeff,Ss);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode SNESNGMRESFormCombinedSolution_Private(SNES snes,PetscInt l,Vec XM,Vec FM,PetscReal fMnorm,Vec X,Vec XA,Vec FA) { SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; PetscInt i,j; Vec *Fdot = ngmres->Fdot; Vec *Xdot = ngmres->Xdot; PetscScalar *beta = ngmres->beta; PetscScalar *xi = ngmres->xi; PetscScalar alph_total = 0.; PetscErrorCode ierr; PetscReal nu; Vec Y = snes->work[2]; PetscBool changed_y,changed_w; PetscFunctionBegin; nu = fMnorm*fMnorm; /* construct the right hand side and xi factors */ ierr = VecMDot(FM,l,Fdot,xi);CHKERRQ(ierr); for (i = 0; i < l; i++) beta[i] = nu - xi[i]; /* construct h */ for (j = 0; j < l; j++) { for (i = 0; i < l; i++) { H(i,j) = Q(i,j)-xi[i]-xi[j]+nu; } } if (l == 1) { /* simply set alpha[0] = beta[0] / H[0, 0] */ if (H(0,0) != 0.) beta[0] = beta[0]/H(0,0); else beta[0] = 0.; } else { #if defined(PETSC_MISSING_LAPACK_GELSS) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"NGMRES with LS requires the LAPACK GELSS routine."); #else ierr = PetscBLASIntCast(l,&ngmres->m);CHKERRQ(ierr); ierr = PetscBLASIntCast(l,&ngmres->n);CHKERRQ(ierr); ngmres->info = 0; ngmres->rcond = -1.; ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); #if defined(PETSC_USE_COMPLEX) PetscStackCall("LAPACKgelss",LAPACKgelss_(&ngmres->m,&ngmres->n,&ngmres->nrhs,ngmres->h,&ngmres->lda,ngmres->beta,&ngmres->ldb,ngmres->s,&ngmres->rcond,&ngmres->rank,ngmres->work,&ngmres->lwork,ngmres->rwork,&ngmres->info)); #else PetscStackCall("LAPACKgelss",LAPACKgelss_(&ngmres->m,&ngmres->n,&ngmres->nrhs,ngmres->h,&ngmres->lda,ngmres->beta,&ngmres->ldb,ngmres->s,&ngmres->rcond,&ngmres->rank,ngmres->work,&ngmres->lwork,&ngmres->info)); #endif ierr = PetscFPTrapPop();CHKERRQ(ierr); if (ngmres->info < 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"Bad argument to GELSS"); if (ngmres->info > 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"SVD failed to converge"); #endif } for (i=0; i<l; i++) { if (PetscIsInfOrNanScalar(beta[i])) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"SVD generated inconsistent output"); } alph_total = 0.; for (i = 0; i < l; i++) alph_total += beta[i]; ierr = VecCopy(XM,XA);CHKERRQ(ierr); ierr = VecScale(XA,1.-alph_total);CHKERRQ(ierr); ierr = VecMAXPY(XA,l,beta,Xdot);CHKERRQ(ierr); /* check the validity of the step */ ierr = VecCopy(XA,Y);CHKERRQ(ierr); ierr = VecAXPY(Y,-1.0,X);CHKERRQ(ierr); ierr = SNESLineSearchPostCheck(snes->linesearch,X,Y,XA,&changed_y,&changed_w);CHKERRQ(ierr); if (!ngmres->approxfunc) {ierr = SNESComputeFunction(snes,XA,FA);CHKERRQ(ierr);} else { ierr = VecCopy(FM,FA);CHKERRQ(ierr); ierr = VecScale(FA,1.-alph_total);CHKERRQ(ierr); ierr = VecMAXPY(FA,l,beta,Fdot);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_Composite(SNES snes) { Vec F; Vec X; Vec B; PetscInt i; PetscReal fnorm = 0.0, xnorm = 0.0, snorm = 0.0; PetscErrorCode ierr; SNESNormSchedule normtype; SNES_Composite *comp = (SNES_Composite*)snes->data; PetscFunctionBegin; X = snes->vec_sol; F = snes->vec_func; B = snes->vec_rhs; ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; comp->innerFailures = 0; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESSetWorkVecs(snes, 1);CHKERRQ(ierr); snes->reason = SNES_CONVERGED_ITERATING; ierr = SNESGetNormSchedule(snes, &normtype);CHKERRQ(ierr); if (normtype == SNES_NORM_ALWAYS || normtype == SNES_NORM_INITIAL_ONLY || normtype == SNES_NORM_INITIAL_FINAL_ONLY) { if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); } else snes->vec_func_init_set = PETSC_FALSE; if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, &fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ } SNESCheckFunctionNorm(snes,fnorm); ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); } else { ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,snes->norm);CHKERRQ(ierr); } /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } for (i = 0; i < snes->max_its; i++) { /* Copy the state before modification by application of the composite solver; we will subtract the new state after application */ ierr = VecCopy(X, snes->work[0]);CHKERRQ(ierr); if (comp->type == SNES_COMPOSITE_ADDITIVE) { ierr = SNESCompositeApply_Additive(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else if (comp->type == SNES_COMPOSITE_MULTIPLICATIVE) { ierr = SNESCompositeApply_Multiplicative(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else if (comp->type == SNES_COMPOSITE_ADDITIVEOPTIMAL) { ierr = SNESCompositeApply_AdditiveOptimal(snes,X,B,F,&fnorm);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Unsupported SNESComposite type"); if (snes->reason < 0) break; /* Compute the solution update for convergence testing */ ierr = VecAXPY(snes->work[0], -1.0, X);CHKERRQ(ierr); ierr = VecScale(snes->work[0], -1.0);CHKERRQ(ierr); if ((i == snes->max_its - 1) && (normtype == SNES_NORM_INITIAL_FINAL_ONLY || normtype == SNES_NORM_FINAL_ONLY)) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->xl && snes->xu) { ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, &fnorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } else { ierr = VecNormBegin(F, NORM_2, &fnorm);CHKERRQ(ierr); ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = VecNormEnd(F, NORM_2, &fnorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,fnorm); } else if (normtype == SNES_NORM_ALWAYS) { ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormBegin(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); ierr = VecNormEnd(snes->work[0], NORM_2, &snorm);CHKERRQ(ierr); } /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence */ if (normtype == SNES_NORM_ALWAYS) {ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,snorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);} if (snes->reason) break; /* Call general purpose update function */ if (snes->ops->update) {ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);} } if (normtype == SNES_NORM_ALWAYS) { if (i == snes->max_its) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",snes->max_its);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } } else if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; PetscFunctionReturn(0); }
static PetscErrorCode SNESCompositeApply_Multiplicative(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) { PetscErrorCode ierr; SNES_Composite *jac = (SNES_Composite*)snes->data; SNES_CompositeLink next = jac->head; Vec FSub; SNESConvergedReason reason; PetscFunctionBegin; if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); } ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } while (next->next) { /* only copy the function over in the case where the functions correspond */ if (next->snes->pcside == PC_RIGHT && next->snes->normschedule != SNES_NORM_NONE) { ierr = SNESGetFunction(next->snes,&FSub,NULL,NULL);CHKERRQ(ierr); next = next->next; ierr = SNESSetInitialFunction(next->snes,FSub);CHKERRQ(ierr); } else { next = next->next; } ierr = SNESSolve(next->snes,B,X);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } } if (next->snes->pcside == PC_RIGHT) { ierr = SNESGetFunction(next->snes,&FSub,NULL,NULL);CHKERRQ(ierr); ierr = VecCopy(FSub,F);CHKERRQ(ierr); if (fnorm) { if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,*fnorm); } } else if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (fnorm) { if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,*fnorm); } } PetscFunctionReturn(0); }
/* approximately solve the overdetermined system: 2*F(x_i)\cdot F(\x_j)\alpha_i = 0 \alpha_i = 1 Which minimizes the L2 norm of the linearization of: ||F(\sum_i \alpha_i*x_i)||^2 With the constraint that \sum_i\alpha_i = 1 Where x_i is the solution from the ith subsolver. */ static PetscErrorCode SNESCompositeApply_AdditiveOptimal(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) { PetscErrorCode ierr; SNES_Composite *jac = (SNES_Composite*)snes->data; SNES_CompositeLink next = jac->head; Vec *Xes = jac->Xes,*Fes = jac->Fes; PetscInt i,j; PetscScalar tot,total,ftf; PetscReal min_fnorm; PetscInt min_i; SNESConvergedReason reason; PetscFunctionBegin; if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); if (snes->normschedule == SNES_NORM_ALWAYS) { next = jac->head; ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); while (next->next) { next = next->next; ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); } } next = jac->head; i = 0; ierr = VecCopy(X,Xes[i]);CHKERRQ(ierr); ierr = SNESSolve(next->snes,B,Xes[i]);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } while (next->next) { i++; next = next->next; ierr = VecCopy(X,Xes[i]);CHKERRQ(ierr); ierr = SNESSolve(next->snes,B,Xes[i]);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } } /* all the solutions are collected; combine optimally */ for (i=0;i<jac->n;i++) { for (j=0;j<i+1;j++) { ierr = VecDotBegin(Fes[i],Fes[j],&jac->h[i + j*jac->n]);CHKERRQ(ierr); } ierr = VecDotBegin(Fes[i],F,&jac->g[i]);CHKERRQ(ierr); } for (i=0;i<jac->n;i++) { for (j=0;j<i+1;j++) { ierr = VecDotEnd(Fes[i],Fes[j],&jac->h[i + j*jac->n]);CHKERRQ(ierr); if (i == j) jac->fnorms[i] = PetscSqrtReal(PetscRealPart(jac->h[i + j*jac->n])); } ierr = VecDotEnd(Fes[i],F,&jac->g[i]);CHKERRQ(ierr); } ftf = (*fnorm)*(*fnorm); for (i=0; i<jac->n; i++) { for (j=i+1;j<jac->n;j++) { jac->h[i + j*jac->n] = jac->h[j + i*jac->n]; } } for (i=0; i<jac->n; i++) { for (j=0; j<jac->n; j++) { jac->h[i + j*jac->n] = jac->h[i + j*jac->n] - jac->g[j] - jac->g[i] + ftf; } jac->beta[i] = ftf - jac->g[i]; } #if defined(PETSC_MISSING_LAPACK_GELSS) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"SNESCOMPOSITE with ADDITIVEOPTIMAL requires the LAPACK GELSS routine."); #else jac->info = 0; jac->rcond = -1.; ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); #if defined(PETSC_USE_COMPLEX) PetscStackCall("LAPACKgelss",LAPACKgelss_(&jac->n,&jac->n,&jac->nrhs,jac->h,&jac->lda,jac->beta,&jac->lda,jac->s,&jac->rcond,&jac->rank,jac->work,&jac->lwork,jac->rwork,&jac->info)); #else PetscStackCall("LAPACKgelss",LAPACKgelss_(&jac->n,&jac->n,&jac->nrhs,jac->h,&jac->lda,jac->beta,&jac->lda,jac->s,&jac->rcond,&jac->rank,jac->work,&jac->lwork,&jac->info)); #endif ierr = PetscFPTrapPop();CHKERRQ(ierr); if (jac->info < 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"Bad argument to GELSS"); if (jac->info > 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"SVD failed to converge"); #endif tot = 0.; total = 0.; for (i=0; i<jac->n; i++) { if (snes->errorifnotconverged && PetscIsInfOrNanScalar(jac->beta[i])) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"SVD generated inconsistent output"); ierr = PetscInfo2(snes,"%D: %g\n",i,(double)PetscRealPart(jac->beta[i]));CHKERRQ(ierr); tot += jac->beta[i]; total += PetscAbsScalar(jac->beta[i]); } ierr = VecScale(X,(1. - tot));CHKERRQ(ierr); ierr = VecMAXPY(X,jac->n,jac->beta,Xes);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } /* take the minimum-normed candidate if it beats the combination by a factor of rtol or the combination has stagnated */ min_fnorm = jac->fnorms[0]; min_i = 0; for (i=0; i<jac->n; i++) { if (jac->fnorms[i] < min_fnorm) { min_fnorm = jac->fnorms[i]; min_i = i; } } /* stagnation or divergence restart to the solution of the solver that failed the least */ if (PetscRealPart(total) < jac->stol || min_fnorm*jac->rtol < *fnorm) { ierr = VecCopy(jac->Xes[min_i],X);CHKERRQ(ierr); ierr = VecCopy(jac->Fes[min_i],F);CHKERRQ(ierr); *fnorm = min_fnorm; } PetscFunctionReturn(0); }
static PetscErrorCode SNESCompositeApply_Additive(SNES snes,Vec X,Vec B,Vec F,PetscReal *fnorm) { PetscErrorCode ierr; SNES_Composite *jac = (SNES_Composite*)snes->data; SNES_CompositeLink next = jac->head; Vec Y,Xorig; SNESConvergedReason reason; PetscFunctionBegin; Y = snes->vec_sol_update; if (!jac->Xorig) {ierr = VecDuplicate(X,&jac->Xorig);CHKERRQ(ierr);} Xorig = jac->Xorig; ierr = VecCopy(X,Xorig);CHKERRQ(ierr); if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses"); if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); while (next->next) { next = next->next; ierr = SNESSetInitialFunction(next->snes,F);CHKERRQ(ierr); } } next = jac->head; ierr = VecCopy(Xorig,Y);CHKERRQ(ierr); ierr = SNESSolve(next->snes,B,Y);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } ierr = VecAXPY(Y,-1.0,Xorig);CHKERRQ(ierr); ierr = VecAXPY(X,next->dmp,Y);CHKERRQ(ierr); while (next->next) { next = next->next; ierr = VecCopy(Xorig,Y);CHKERRQ(ierr); ierr = SNESSolve(next->snes,B,Y);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next->snes,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { jac->innerFailures++; if (jac->innerFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } ierr = VecAXPY(Y,-1.0,Xorig);CHKERRQ(ierr); ierr = VecAXPY(X,next->dmp,Y);CHKERRQ(ierr); } if (snes->normschedule == SNES_NORM_ALWAYS) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (fnorm) { if (snes->xl && snes->xu) { ierr = SNESVIComputeInactiveSetFnorm(snes, F, X, fnorm);CHKERRQ(ierr); } else { ierr = VecNorm(F, NORM_2, fnorm);CHKERRQ(ierr); } SNESCheckFunctionNorm(snes,*fnorm); } } PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_Anderson(SNES snes) { SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; /* present solution, residual, and preconditioned residual */ Vec X,F,B,D; /* candidate linear combination answers */ Vec XA,FA,XM,FM; /* coefficients and RHS to the minimization problem */ PetscReal fnorm,fMnorm,fAnorm; PetscReal xnorm,ynorm; PetscReal dnorm,dminnorm=0.0,fminnorm; PetscInt restart_count=0; PetscInt k,k_restart,l,ivec; PetscBool selectRestart; SNESConvergedReason reason; PetscErrorCode ierr; PetscFunctionBegin; if (snes->xl || snes->xu || snes->ops->computevariablebounds) { SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); } ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); /* variable initialization */ snes->reason = SNES_CONVERGED_ITERATING; X = snes->vec_sol; F = snes->vec_func; B = snes->vec_rhs; XA = snes->vec_sol_update; FA = snes->work[0]; D = snes->work[1]; /* work for the line search */ XM = snes->work[3]; FM = snes->work[4]; ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); /* initialization */ /* r = F(x) */ if (snes->pc && snes->pcside == PC_LEFT) { ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); } else { if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); } else snes->vec_func_init_set = PETSC_FALSE; ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); SNESCheckFunctionNorm(snes,fnorm); } fminnorm = fnorm; ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); k_restart = 0; l = 0; ivec = 0; for (k=1; k < snes->max_its+1; k++) { /* select which vector of the stored subspace will be updated */ if (snes->pc && snes->pcside == PC_RIGHT) { ierr = VecCopy(X,XM);CHKERRQ(ierr); ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr); ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetNPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr); if (ngmres->andersonBeta != 1.0) { VecAXPBY(XM,(1.0 - ngmres->andersonBeta),ngmres->andersonBeta,X);CHKERRQ(ierr); } } else { ierr = VecCopy(F,FM);CHKERRQ(ierr); ierr = VecCopy(X,XM);CHKERRQ(ierr); ierr = VecAXPY(XM,-ngmres->andersonBeta,FM);CHKERRQ(ierr); fMnorm = fnorm; } ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr); ivec = k_restart % ngmres->msize; if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,NULL,NULL,NULL,&xnorm,&fAnorm,&ynorm);CHKERRQ(ierr); ierr = SNESNGMRESSelectRestart_Private(snes,l,fMnorm,fnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr); /* if the restart conditions persist for more than restart_it iterations, restart. */ if (selectRestart) restart_count++; else restart_count = 0; } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,NULL,NULL,NULL,&xnorm,&fAnorm,&ynorm);CHKERRQ(ierr); if (k_restart > ngmres->restart_periodic) { if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr); restart_count = ngmres->restart_it; } } else { ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,NULL,NULL,NULL,&xnorm,&fAnorm,&ynorm);CHKERRQ(ierr); } /* restart after restart conditions have persisted for a fixed number of iterations */ if (restart_count >= ngmres->restart_it) { if (ngmres->monitor) { ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr); } restart_count = 0; k_restart = 0; l = 0; ivec = 0; } else { if (l < ngmres->msize) l++; k_restart++; ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fnorm,XM);CHKERRQ(ierr); } fnorm = fAnorm; if (fminnorm > fnorm) fminnorm = fnorm; ierr = VecCopy(XA,X);CHKERRQ(ierr); ierr = VecCopy(FA,F);CHKERRQ(ierr); ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = k; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); } snes->reason = SNES_DIVERGED_MAX_IT; PetscFunctionReturn(0); }
/* SNESSolve_NEWTONTR - Implements Newton's Method with a very simple trust region approach for solving systems of nonlinear equations. */ static PetscErrorCode SNESSolve_NEWTONTR(SNES snes) { SNES_NEWTONTR *neP = (SNES_NEWTONTR*)snes->data; Vec X,F,Y,G,Ytmp; PetscErrorCode ierr; PetscInt maxits,i,lits; PetscReal rho,fnorm,gnorm,gpnorm,xnorm=0,delta,nrm,ynorm,norm1; PetscScalar cnorm; KSP ksp; SNESConvergedReason reason = SNES_CONVERGED_ITERATING; PetscBool conv = PETSC_FALSE,breakout = PETSC_FALSE; PetscFunctionBegin; if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* solution vector */ F = snes->vec_func; /* residual vector */ Y = snes->work[0]; /* work vectors */ G = snes->work[1]; Ytmp = snes->work[2]; ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); /* F(X) */ } else snes->vec_func_init_set = PETSC_FALSE; ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- || F || */ SNESCheckFunctionNorm(snes,fnorm); ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); /* fnorm <- || F || */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); delta = xnorm ? neP->delta0*xnorm : neP->delta0; neP->delta = delta; ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* Set the stopping criteria to use the More' trick. */ ierr = PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_tr_ksp_regular_convergence_test",&conv,NULL);CHKERRQ(ierr); if (!conv) { SNES_TR_KSPConverged_Ctx *ctx; ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); ierr = PetscNew(&ctx);CHKERRQ(ierr); ctx->snes = snes; ierr = KSPConvergedDefaultCreate(&ctx->ctx);CHKERRQ(ierr); ierr = KSPSetConvergenceTest(ksp,SNESTR_KSPConverged_Private,ctx,SNESTR_KSPConverged_Destroy);CHKERRQ(ierr); ierr = PetscInfo(snes,"Using Krylov convergence test SNESTR_KSPConverged_Private\n");CHKERRQ(ierr); } for (i=0; i<maxits; i++) { /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } /* Solve J Y = F, where J is Jacobian matrix */ ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); SNESCheckJacobianDomainerror(snes); ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); ierr = KSPSolve(snes->ksp,F,Ytmp);CHKERRQ(ierr); ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); snes->linear_its += lits; ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); ierr = VecNorm(Ytmp,NORM_2,&nrm);CHKERRQ(ierr); norm1 = nrm; while (1) { ierr = VecCopy(Ytmp,Y);CHKERRQ(ierr); nrm = norm1; /* Scale Y if need be and predict new value of F norm */ if (nrm >= delta) { nrm = delta/nrm; gpnorm = (1.0 - nrm)*fnorm; cnorm = nrm; ierr = PetscInfo1(snes,"Scaling direction by %g\n",(double)nrm);CHKERRQ(ierr); ierr = VecScale(Y,cnorm);CHKERRQ(ierr); nrm = gpnorm; ynorm = delta; } else { gpnorm = 0.0; ierr = PetscInfo(snes,"Direction is in Trust Region\n");CHKERRQ(ierr); ynorm = nrm; } ierr = VecAYPX(Y,-1.0,X);CHKERRQ(ierr); /* Y <- X - Y */ ierr = VecCopy(X,snes->vec_sol_update);CHKERRQ(ierr); ierr = SNESComputeFunction(snes,Y,G);CHKERRQ(ierr); /* F(X) */ ierr = VecNorm(G,NORM_2,&gnorm);CHKERRQ(ierr); /* gnorm <- || g || */ if (fnorm == gpnorm) rho = 0.0; else rho = (fnorm*fnorm - gnorm*gnorm)/(fnorm*fnorm - gpnorm*gpnorm); /* Update size of trust region */ if (rho < neP->mu) delta *= neP->delta1; else if (rho < neP->eta) delta *= neP->delta2; else delta *= neP->delta3; ierr = PetscInfo3(snes,"fnorm=%g, gnorm=%g, ynorm=%g\n",(double)fnorm,(double)gnorm,(double)ynorm);CHKERRQ(ierr); ierr = PetscInfo3(snes,"gpred=%g, rho=%g, delta=%g\n",(double)gpnorm,(double)rho,(double)delta);CHKERRQ(ierr); neP->delta = delta; if (rho > neP->sigma) break; ierr = PetscInfo(snes,"Trying again in smaller region\n");CHKERRQ(ierr); /* check to see if progress is hopeless */ neP->itflag = PETSC_FALSE; ierr = SNESTR_Converged_Private(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); if (!reason) { ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); } if (reason) { /* We're not progressing, so return with the current iterate */ ierr = SNESMonitor(snes,i+1,fnorm);CHKERRQ(ierr); breakout = PETSC_TRUE; break; } snes->numFailures++; } if (!breakout) { /* Update function and solution vectors */ fnorm = gnorm; ierr = VecCopy(G,F);CHKERRQ(ierr); ierr = VecCopy(Y,X);CHKERRQ(ierr); /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; snes->xnorm = xnorm; snes->ynorm = ynorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,lits);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence, xnorm = || X || */ neP->itflag = PETSC_TRUE; if (snes->ops->converged != SNESConvergedSkip) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); } ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&reason,snes->cnvP);CHKERRQ(ierr); if (reason) break; } else break; } if (i == maxits) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); if (!reason) reason = SNES_DIVERGED_MAX_IT; } ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->reason = reason; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_FAS(SNES snes) { PetscErrorCode ierr; PetscInt i, maxits; Vec X, F; PetscReal fnorm; SNES_FAS *fas = (SNES_FAS*)snes->data,*ffas; DM dm; PetscBool isFine; PetscFunctionBegin; ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); maxits = snes->max_its; /* maximum number of iterations */ snes->reason = SNES_CONVERGED_ITERATING; X = snes->vec_sol; F = snes->vec_func; ierr = SNESFASCycleIsFine(snes, &isFine);CHKERRQ(ierr); /*norm setup */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); if (!snes->vec_func_init_set) { if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } } else snes->vec_func_init_set = PETSC_FALSE; ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ if (PetscIsInfOrNanReal(fnorm)) { snes->reason = SNES_DIVERGED_FNORM_NAN; PetscFunctionReturn(0); } ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); if (isFine) { /* propagate scale-dependent data up the hierarchy */ ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); for (ffas=fas; ffas->next; ffas=(SNES_FAS*)ffas->next->data) { DM dmcoarse; ierr = SNESGetDM(ffas->next,&dmcoarse);CHKERRQ(ierr); ierr = DMRestrict(dm,ffas->restrct,ffas->rscale,ffas->inject,dmcoarse);CHKERRQ(ierr); dm = dmcoarse; } } for (i = 0; i < maxits; i++) { /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } if (fas->fastype == SNES_FAS_MULTIPLICATIVE) { ierr = SNESFASCycle_Multiplicative(snes, X);CHKERRQ(ierr); } else if (fas->fastype == SNES_FAS_ADDITIVE) { ierr = SNESFASCycle_Additive(snes, X);CHKERRQ(ierr); } else if (fas->fastype == SNES_FAS_FULL) { ierr = SNESFASCycle_Full(snes, X);CHKERRQ(ierr); } else if (fas->fastype ==SNES_FAS_KASKADE) { ierr = SNESFASCycle_Kaskade(snes, X);CHKERRQ(ierr); } else { SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"Unsupported FAS type"); } /* check for FAS cycle divergence */ if (snes->reason != SNES_CONVERGED_ITERATING) PetscFunctionReturn(0); /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i+1; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence */ if (isFine) { ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,snes->norm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) break; } } if (i == maxits) { ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } PetscFunctionReturn(0); }
static PetscErrorCode SNESSolve_MS(SNES snes) { SNES_MS *ms = (SNES_MS*)snes->data; Vec X = snes->vec_sol,F = snes->vec_func; PetscReal fnorm; MatStructure mstruct; PetscInt i; PetscErrorCode ierr; PetscFunctionBegin; snes->reason = SNES_CONVERGED_ITERATING; ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } } else { snes->vec_func_init_set = PETSC_FALSE; } if (snes->jacobian) { /* This method does not require a Jacobian, but it is usually preconditioned by PBJacobi */ ierr = SNESComputeJacobian(snes,snes->vec_sol,&snes->jacobian,&snes->jacobian_pre,&mstruct);CHKERRQ(ierr); ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,mstruct);CHKERRQ(ierr); } if (ms->norms) { if (!snes->norm_init_set) { ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); } else { fnorm = snes->norm_init; snes->norm_init_set = PETSC_FALSE; } /* Monitor convergence */ ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); SNESLogConvHistory(snes,snes->norm,0); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* set parameter for default relative tolerance convergence test */ snes->ttol = fnorm*snes->rtol; /* Test for convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); } /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes,snes->iter);CHKERRQ(ierr); } for (i = 0; i < snes->max_its; i++) { ierr = SNESMSStep_3Sstar(snes,X,F);CHKERRQ(ierr); if (i+1 < snes->max_its || ms->norms) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } } if (ms->norms) { ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); /* Monitor convergence */ ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); SNESLogConvHistory(snes,snes->norm,0); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); } /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } } if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_NCG(SNES snes) { SNES_NCG *ncg = (SNES_NCG*)snes->data; Vec X,dX,lX,F,dXold; PetscReal fnorm, ynorm, xnorm, beta = 0.0; PetscScalar dXdotdX, dXolddotdXold, dXdotdXold, lXdotdX, lXdotdXold; PetscInt maxits, i; PetscErrorCode ierr; PetscBool lsSuccess = PETSC_TRUE; SNESLineSearch linesearch; SNESConvergedReason reason; PetscFunctionBegin; ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); snes->reason = SNES_CONVERGED_ITERATING; maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* X^n */ dXold = snes->work[0]; /* The previous iterate of X */ dX = snes->work[1]; /* the preconditioned direction */ lX = snes->vec_sol_update; /* the conjugate direction */ F = snes->vec_func; /* residual vector */ ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); /* compute the initial function and preconditioned update dX */ if (snes->pc && snes->functype == SNES_FUNCTION_PRECONDITIONED) { ierr = SNESApplyNPC(snes,X,NULL,dX);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = VecCopy(dX,F);CHKERRQ(ierr); ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); } else { if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } } else snes->vec_func_init_set = PETSC_FALSE; /* convergence test */ ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); if (PetscIsInfOrNanReal(fnorm)) { snes->reason = SNES_DIVERGED_FNORM_NAN; PetscFunctionReturn(0); } ierr = VecCopy(F,dX);CHKERRQ(ierr); } if (snes->pc) { if (snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { ierr = SNESApplyNPC(snes,X,F,dX);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } } ierr = VecCopy(dX,lX);CHKERRQ(ierr); ierr = VecDot(dX, dX, &dXdotdX);CHKERRQ(ierr); ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */ for (i = 1; i < maxits + 1; i++) { lsSuccess = PETSC_TRUE; /* some update types require the old update direction or conjugate direction */ if (ncg->type != SNES_NCG_FR) { ierr = VecCopy(dX, dXold);CHKERRQ(ierr); } ierr = SNESLineSearchApply(linesearch,X,F,&fnorm,lX);CHKERRQ(ierr); ierr = SNESLineSearchGetSuccess(linesearch, &lsSuccess);CHKERRQ(ierr); if (!lsSuccess) { if (++snes->numFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_LINE_SEARCH; PetscFunctionReturn(0); } } if (snes->nfuncs >= snes->max_funcs) { snes->reason = SNES_DIVERGED_FUNCTION_COUNT; PetscFunctionReturn(0); } if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } if (snes->pc) { if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { ierr = SNESApplyNPC(snes,X,NULL,dX);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = VecCopy(dX,F);CHKERRQ(ierr); } else { ierr = SNESApplyNPC(snes,X,F,dX);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } } else { ierr = VecCopy(F,dX);CHKERRQ(ierr); } /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/ switch (ncg->type) { case SNES_NCG_FR: /* Fletcher-Reeves */ dXolddotdXold= dXdotdX; ierr = VecDot(dX, dX, &dXdotdX);CHKERRQ(ierr); beta = PetscRealPart(dXdotdX / dXolddotdXold); break; case SNES_NCG_PRP: /* Polak-Ribiere-Poylak */ dXolddotdXold= dXdotdX; ierr = VecDotBegin(dX, dX, &dXdotdXold);CHKERRQ(ierr); ierr = VecDotBegin(dXold, dX, &dXdotdXold);CHKERRQ(ierr); ierr = VecDotEnd(dX, dX, &dXdotdX);CHKERRQ(ierr); ierr = VecDotEnd(dXold, dX, &dXdotdXold);CHKERRQ(ierr); beta = PetscRealPart(((dXdotdX - dXdotdXold) / dXolddotdXold)); if (beta < 0.0) beta = 0.0; /* restart */ break; case SNES_NCG_HS: /* Hestenes-Stiefel */ ierr = VecDotBegin(dX, dX, &dXdotdX);CHKERRQ(ierr); ierr = VecDotBegin(dX, dXold, &dXdotdXold);CHKERRQ(ierr); ierr = VecDotBegin(lX, dX, &lXdotdX);CHKERRQ(ierr); ierr = VecDotBegin(lX, dXold, &lXdotdXold);CHKERRQ(ierr); ierr = VecDotEnd(dX, dX, &dXdotdX);CHKERRQ(ierr); ierr = VecDotEnd(dX, dXold, &dXdotdXold);CHKERRQ(ierr); ierr = VecDotEnd(lX, dX, &lXdotdX);CHKERRQ(ierr); ierr = VecDotEnd(lX, dXold, &lXdotdXold);CHKERRQ(ierr); beta = PetscRealPart((dXdotdX - dXdotdXold) / (lXdotdX - lXdotdXold)); break; case SNES_NCG_DY: /* Dai-Yuan */ ierr = VecDotBegin(dX, dX, &dXdotdX);CHKERRQ(ierr); ierr = VecDotBegin(lX, dX, &lXdotdX);CHKERRQ(ierr); ierr = VecDotBegin(lX, dXold, &lXdotdXold);CHKERRQ(ierr); ierr = VecDotEnd(dX, dX, &dXdotdX);CHKERRQ(ierr); ierr = VecDotEnd(lX, dX, &lXdotdX);CHKERRQ(ierr); ierr = VecDotEnd(lX, dXold, &lXdotdXold);CHKERRQ(ierr); beta = PetscRealPart(dXdotdX / (lXdotdXold - lXdotdX));CHKERRQ(ierr); break; case SNES_NCG_CD: /* Conjugate Descent */ ierr = VecDotBegin(dX, dX, &dXdotdX);CHKERRQ(ierr); ierr = VecDotBegin(lX, dXold, &lXdotdXold);CHKERRQ(ierr); ierr = VecDotEnd(dX, dX, &dXdotdX);CHKERRQ(ierr); ierr = VecDotEnd(lX, dXold, &lXdotdXold);CHKERRQ(ierr); beta = PetscRealPart(dXdotdX / lXdotdXold);CHKERRQ(ierr); break; } if (ncg->monitor) { ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", (double)beta);CHKERRQ(ierr); } ierr = VecAYPX(lX, beta, dX);CHKERRQ(ierr); } ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; PetscFunctionReturn(0); }
EXTERN_C_END /* SNESSolve_NCG - Solves a nonlinear system with the Nonlinear Conjugate Gradient method. Input Parameters: . snes - the SNES context Output Parameter: . outits - number of iterations until termination Application Interface Routine: SNESSolve() */ #undef __FUNCT__ #define __FUNCT__ "SNESSolve_NCG" PetscErrorCode SNESSolve_NCG(SNES snes) { SNES_NCG *ncg = (SNES_NCG *)snes->data; Vec X, dX, lX, F, B, Fold; PetscReal fnorm, ynorm, xnorm, beta = 0.0; PetscScalar dXdotF, dXolddotFold, dXdotFold, lXdotF, lXdotFold; PetscInt maxits, i; PetscErrorCode ierr; SNESConvergedReason reason; PetscBool lsSuccess = PETSC_TRUE; SNESLineSearch linesearch; PetscFunctionBegin; snes->reason = SNES_CONVERGED_ITERATING; maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* X^n */ Fold = snes->work[0]; /* The previous iterate of X */ dX = snes->work[1]; /* the preconditioned direction */ lX = snes->vec_sol_update; /* the conjugate direction */ F = snes->vec_func; /* residual vector */ B = snes->vec_rhs; /* the right hand side */ ierr = SNESGetSNESLineSearch(snes, &linesearch); CHKERRQ(ierr); ierr = PetscObjectTakeAccess(snes); CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; ierr = PetscObjectGrantAccess(snes); CHKERRQ(ierr); /* compute the initial function and preconditioned update dX */ if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr); if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } } else { snes->vec_func_init_set = PETSC_FALSE; } if (!snes->norm_init_set) { /* convergence test */ ierr = VecNorm(F, NORM_2, &fnorm); CHKERRQ(ierr); /* fnorm <- ||F|| */ if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); } else { fnorm = snes->norm_init; snes->norm_init_set = PETSC_FALSE; } ierr = PetscObjectTakeAccess(snes); CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes); CHKERRQ(ierr); SNESLogConvHistory(snes,fnorm,0); ierr = SNESMonitor(snes,0,fnorm); CHKERRQ(ierr); /* set parameter for default relative tolerance convergence test */ snes->ttol = fnorm*snes->rtol; /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP); CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter); CHKERRQ(ierr); } /* first update -- just use the (preconditioned) residual direction for the initial conjugate direction */ if (snes->pc && snes->pcside == PC_RIGHT) { ierr = VecCopy(X, dX); CHKERRQ(ierr); ierr = SNESSetInitialFunction(snes->pc, F); CHKERRQ(ierr); ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm); CHKERRQ(ierr); ierr = SNESSolve(snes->pc, B, dX); CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason); CHKERRQ(ierr); if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = VecAYPX(dX,-1.0,X); CHKERRQ(ierr); } else { ierr = VecCopy(F, dX); CHKERRQ(ierr); } ierr = VecCopy(dX, lX); CHKERRQ(ierr); ierr = VecDot(F, dX, &dXdotF); CHKERRQ(ierr); /* } else { ierr = SNESNCGComputeYtJtF_Private(snes, X, F, dX, W, G, &dXdotF);CHKERRQ(ierr); } */ for (i = 1; i < maxits + 1; i++) { lsSuccess = PETSC_TRUE; /* some update types require the old update direction or conjugate direction */ if (ncg->type != SNES_NCG_FR) { ierr = VecCopy(F, Fold); CHKERRQ(ierr); } ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, lX); CHKERRQ(ierr); ierr = SNESLineSearchGetSuccess(linesearch, &lsSuccess); CHKERRQ(ierr); if (!lsSuccess) { if (++snes->numFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_LINE_SEARCH; PetscFunctionReturn(0); } } if (snes->nfuncs >= snes->max_funcs) { snes->reason = SNES_DIVERGED_FUNCTION_COUNT; PetscFunctionReturn(0); } if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm); CHKERRQ(ierr); /* Monitor convergence */ ierr = PetscObjectTakeAccess(snes); CHKERRQ(ierr); snes->iter = i; snes->norm = fnorm; ierr = PetscObjectGrantAccess(snes); CHKERRQ(ierr); SNESLogConvHistory(snes,snes->norm,0); ierr = SNESMonitor(snes,snes->iter,snes->norm); CHKERRQ(ierr); /* Test for convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP); CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter); CHKERRQ(ierr); } if (snes->pc && snes->pcside == PC_RIGHT) { ierr = VecCopy(X,dX); CHKERRQ(ierr); ierr = SNESSetInitialFunction(snes->pc, F); CHKERRQ(ierr); ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm); CHKERRQ(ierr); ierr = SNESSolve(snes->pc, B, dX); CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason); CHKERRQ(ierr); if (reason < 0 && (reason != SNES_DIVERGED_MAX_IT)) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = VecAYPX(dX,-1.0,X); CHKERRQ(ierr); } else { ierr = VecCopy(F, dX); CHKERRQ(ierr); } /* compute the conjugate direction lX = dX + beta*lX with beta = ((dX, dX) / (dX_old, dX_old) (Fletcher-Reeves update)*/ switch(ncg->type) { case SNES_NCG_FR: /* Fletcher-Reeves */ dXolddotFold = dXdotF; ierr = VecDot(dX, dX, &dXdotF); CHKERRQ(ierr); beta = PetscRealPart(dXdotF / dXolddotFold); break; case SNES_NCG_PRP: /* Polak-Ribiere-Poylak */ dXolddotFold = dXdotF; ierr = VecDotBegin(F, dX, &dXdotF); CHKERRQ(ierr); ierr = VecDotBegin(Fold, dX, &dXdotFold); CHKERRQ(ierr); ierr = VecDotEnd(F, dX, &dXdotF); CHKERRQ(ierr); ierr = VecDotEnd(Fold, dX, &dXdotFold); CHKERRQ(ierr); beta = PetscRealPart(((dXdotF - dXdotFold) / dXolddotFold)); if (beta < 0.0) beta = 0.0; /* restart */ break; case SNES_NCG_HS: /* Hestenes-Stiefel */ ierr = VecDotBegin(dX, F, &dXdotF); CHKERRQ(ierr); ierr = VecDotBegin(dX, Fold, &dXdotFold); CHKERRQ(ierr); ierr = VecDotBegin(lX, F, &lXdotF); CHKERRQ(ierr); ierr = VecDotBegin(lX, Fold, &lXdotFold); CHKERRQ(ierr); ierr = VecDotEnd(dX, F, &dXdotF); CHKERRQ(ierr); ierr = VecDotEnd(dX, Fold, &dXdotFold); CHKERRQ(ierr); ierr = VecDotEnd(lX, F, &lXdotF); CHKERRQ(ierr); ierr = VecDotEnd(lX, Fold, &lXdotFold); CHKERRQ(ierr); beta = PetscRealPart((dXdotF - dXdotFold) / (lXdotF - lXdotFold)); break; case SNES_NCG_DY: /* Dai-Yuan */ ierr = VecDotBegin(dX, F, &dXdotF); CHKERRQ(ierr); ierr = VecDotBegin(lX, F, &lXdotF); CHKERRQ(ierr); ierr = VecDotBegin(lX, Fold, &lXdotFold); CHKERRQ(ierr); ierr = VecDotEnd(dX, F, &dXdotF); CHKERRQ(ierr); ierr = VecDotEnd(lX, F, &lXdotF); CHKERRQ(ierr); ierr = VecDotEnd(lX, Fold, &lXdotFold); CHKERRQ(ierr); beta = PetscRealPart(dXdotF / (lXdotFold - lXdotF)); CHKERRQ(ierr); break; case SNES_NCG_CD: /* Conjugate Descent */ ierr = VecDotBegin(dX, F, &dXdotF); CHKERRQ(ierr); ierr = VecDotBegin(lX, Fold, &lXdotFold); CHKERRQ(ierr); ierr = VecDotEnd(dX, F, &dXdotF); CHKERRQ(ierr); ierr = VecDotEnd(lX, Fold, &lXdotFold); CHKERRQ(ierr); beta = PetscRealPart(dXdotF / lXdotFold); CHKERRQ(ierr); break; } if (ncg->monitor) { ierr = PetscViewerASCIIPrintf(ncg->monitor, "beta = %e\n", beta); CHKERRQ(ierr); } ierr = VecAYPX(lX, beta, dX); CHKERRQ(ierr); } ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits); CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; PetscFunctionReturn(0); }
/* The additive cycle looks like: xhat = x xhat = dS(x, b) x = coarsecorrection(xhat, b_d) x = x + nu*(xhat - x); (optional) x = uS(x, b) With the coarse RHS (defect correction) as below. */ PetscErrorCode SNESFASCycle_Additive(SNES snes, Vec X) { Vec F, B, Xhat; Vec X_c, Xo_c, F_c, B_c; PetscErrorCode ierr; SNESConvergedReason reason; PetscReal xnorm, fnorm, ynorm; PetscBool lssuccess; SNES next; Mat restrct, interpolate; SNES_FAS *fas = (SNES_FAS*)snes->data,*fasc; PetscFunctionBegin; ierr = SNESFASCycleGetCorrection(snes, &next);CHKERRQ(ierr); F = snes->vec_func; B = snes->vec_rhs; Xhat = snes->work[1]; ierr = VecCopy(X, Xhat);CHKERRQ(ierr); /* recurse first */ if (next) { fasc = (SNES_FAS*)next->data; ierr = SNESFASCycleGetRestriction(snes, &restrct);CHKERRQ(ierr); ierr = SNESFASCycleGetInterpolation(snes, &interpolate);CHKERRQ(ierr); if (fas->eventresidual) {ierr = PetscLogEventBegin(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = SNESComputeFunction(snes, Xhat, F);CHKERRQ(ierr); if (fas->eventresidual) {ierr = PetscLogEventEnd(fas->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); X_c = next->vec_sol; Xo_c = next->work[0]; F_c = next->vec_func; B_c = next->vec_rhs; ierr = SNESFASRestrict(snes,Xhat,Xo_c);CHKERRQ(ierr); /* restrict the defect */ ierr = MatRestrict(restrct, F, B_c);CHKERRQ(ierr); /* solve the coarse problem corresponding to F^c(x^c) = b^c = Rb + F^c(Rx) - RF(x) */ if (fasc->eventresidual) {ierr = PetscLogEventBegin(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = SNESComputeFunction(next, Xo_c, F_c);CHKERRQ(ierr); if (fasc->eventresidual) {ierr = PetscLogEventEnd(fasc->eventresidual,0,0,0,0);CHKERRQ(ierr);} ierr = VecCopy(B_c, X_c);CHKERRQ(ierr); ierr = VecCopy(F_c, B_c);CHKERRQ(ierr); ierr = VecCopy(X_c, F_c);CHKERRQ(ierr); /* set initial guess of the coarse problem to the projected fine solution */ ierr = VecCopy(Xo_c, X_c);CHKERRQ(ierr); /* recurse */ ierr = SNESSetInitialFunction(next, F_c);CHKERRQ(ierr); ierr = SNESSolve(next, B_c, X_c);CHKERRQ(ierr); /* smooth on this level */ ierr = SNESFASDownSmooth_Private(snes, B, X, F, &fnorm);CHKERRQ(ierr); ierr = SNESGetConvergedReason(next,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } /* correct as x <- x + I(x^c - Rx)*/ ierr = VecAYPX(X_c, -1.0, Xo_c);CHKERRQ(ierr); ierr = MatInterpolate(interpolate, X_c, Xhat);CHKERRQ(ierr); /* additive correction of the coarse direction*/ ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Xhat);CHKERRQ(ierr); ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssuccess);CHKERRQ(ierr); if (!lssuccess) { if (++snes->numFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_LINE_SEARCH; PetscFunctionReturn(0); } } ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &snes->norm, &ynorm);CHKERRQ(ierr); } else { ierr = SNESFASDownSmooth_Private(snes, B, X, F, &snes->norm);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_NEWTONLS(SNES snes) { PetscErrorCode ierr; PetscInt maxits,i,lits; SNESLineSearchReason lssucceed; PetscReal fnorm,gnorm,xnorm,ynorm; Vec Y,X,F; SNESLineSearch linesearch; SNESConvergedReason reason; PetscFunctionBegin; if (snes->xl || snes->xu || snes->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); snes->numFailures = 0; snes->numLinearSolveFailures = 0; snes->reason = SNES_CONVERGED_ITERATING; maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* solution vector */ F = snes->vec_func; /* residual vector */ Y = snes->vec_sol_update; /* newton step */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.0; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); /* compute the preconditioned function first in the case of left preconditioning with preconditioned function */ if (snes->pc && snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = VecNormBegin(F,NORM_2,&fnorm);CHKERRQ(ierr); ierr = VecNormEnd(F,NORM_2,&fnorm);CHKERRQ(ierr); } else { if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); } else snes->vec_func_init_set = PETSC_FALSE; } ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ SNESCheckFunctionNorm(snes,fnorm); ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); for (i=0; i<maxits; i++) { /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } /* apply the nonlinear preconditioner */ if (snes->pc) { if (snes->pcside == PC_RIGHT) { ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr); ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,X,snes->vec_rhs,0);CHKERRQ(ierr); ierr = SNESSolve(snes->pc, snes->vec_rhs, X);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,X,snes->vec_rhs,0);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = SNESGetNPCFunction(snes,F,&fnorm);CHKERRQ(ierr); } else if (snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { ierr = SNESApplyNPC(snes,X,F,F);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } } /* Solve J Y = F, where J is Jacobian matrix */ ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); ierr = KSPSolve(snes->ksp,F,Y);CHKERRQ(ierr); SNESCheckKSPSolve(snes); ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr); snes->linear_its += lits; ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr); if (PetscLogPrintInfo) { ierr = SNESNEWTONLSCheckResidual_Private(snes,snes->jacobian,F,Y);CHKERRQ(ierr); } /* Compute a (scaled) negative update in the line search routine: X <- X - lambda*Y and evaluate F = function(X) (depends on the line search). */ gnorm = fnorm; ierr = SNESLineSearchApply(linesearch, X, F, &fnorm, Y);CHKERRQ(ierr); ierr = SNESLineSearchGetReason(linesearch, &lssucceed);CHKERRQ(ierr); ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)gnorm,(double)fnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr); if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break; SNESCheckFunctionNorm(snes,fnorm); if (lssucceed) { if (snes->stol*xnorm > ynorm) { snes->reason = SNES_CONVERGED_SNORM_RELATIVE; PetscFunctionReturn(0); } if (++snes->numFailures >= snes->maxFailures) { PetscBool ismin; snes->reason = SNES_DIVERGED_LINE_SEARCH; ierr = SNESNEWTONLSCheckLocalMin_Private(snes,snes->jacobian,F,fnorm,&ismin);CHKERRQ(ierr); if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN; break; } } /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,lits);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) break; } if (i == maxits) { ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_NRichardson(SNES snes) { Vec X, Y, F; PetscReal xnorm, fnorm, ynorm; PetscInt maxits, i; PetscErrorCode ierr; SNESLineSearchReason lsresult; SNESConvergedReason reason; PetscFunctionBegin; if (snes->xl || snes->xu || snes->ops->computevariablebounds) { SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); } snes->reason = SNES_CONVERGED_ITERATING; maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* X^n */ Y = snes->vec_sol_update; /* \tilde X */ F = snes->vec_func; /* residual vector */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes); CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes); CHKERRQ(ierr); if (snes->pc && snes->functype == SNES_FUNCTION_PRECONDITIONED) { ierr = SNESApplyNPC(snes,X,NULL,F); CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason); CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr); } else { if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr); } else snes->vec_func_init_set = PETSC_FALSE; ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr); SNESCheckFunctionNorm(snes,fnorm); } if (snes->pc && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { ierr = SNESApplyNPC(snes,X,F,Y); CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason); CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } else { ierr = VecCopy(F,Y); CHKERRQ(ierr); } ierr = PetscObjectSAWsTakeAccess((PetscObject)snes); CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes); CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,fnorm,0); CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm); CHKERRQ(ierr); /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP); CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter); CHKERRQ(ierr); } /* set parameter for default relative tolerance convergence test */ snes->ttol = fnorm*snes->rtol; /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP); CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); for (i = 1; i < maxits+1; i++) { ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Y); CHKERRQ(ierr); ierr = SNESLineSearchGetReason(snes->linesearch, &lsresult); CHKERRQ(ierr); ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &fnorm, &ynorm); CHKERRQ(ierr); if (lsresult) { if (++snes->numFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_LINE_SEARCH; break; } } if (snes->nfuncs >= snes->max_funcs) { snes->reason = SNES_DIVERGED_FUNCTION_COUNT; break; } /* Monitor convergence */ ierr = PetscObjectSAWsTakeAccess((PetscObject)snes); CHKERRQ(ierr); snes->iter = i; snes->norm = fnorm; ierr = PetscObjectSAWsGrantAccess((PetscObject)snes); CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0); CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm); CHKERRQ(ierr); /* Test for convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP); CHKERRQ(ierr); if (snes->reason) break; /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter); CHKERRQ(ierr); } if (snes->pc) { if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { ierr = SNESApplyNPC(snes,X,NULL,Y); CHKERRQ(ierr); ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr); ierr = VecCopy(Y,F); CHKERRQ(ierr); } else { ierr = SNESApplyNPC(snes,X,F,Y); CHKERRQ(ierr); } ierr = SNESGetConvergedReason(snes->pc,&reason); CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } } else { ierr = VecCopy(F,Y); CHKERRQ(ierr); } } if (i == maxits+1) { ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits); CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } PetscFunctionReturn(0); }
PetscErrorCode SNESSolve_NRichardson(SNES snes) { Vec X, Y, F; PetscReal xnorm, fnorm, ynorm; PetscInt maxits, i; PetscErrorCode ierr; PetscBool lsSuccess; SNESConvergedReason reason; PetscFunctionBegin; snes->reason = SNES_CONVERGED_ITERATING; maxits = snes->max_its; /* maximum number of iterations */ X = snes->vec_sol; /* X^n */ Y = snes->vec_sol_update; /* \tilde X */ F = snes->vec_func; /* residual vector */ ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = 0; snes->norm = 0.; ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); if (!snes->vec_func_init_set) { ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } } else snes->vec_func_init_set = PETSC_FALSE; if (!snes->norm_init_set) { ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ if (PetscIsInfOrNanReal(fnorm)) { snes->reason = SNES_DIVERGED_FNORM_NAN; PetscFunctionReturn(0); } } else { fnorm = snes->norm_init; snes->norm_init_set = PETSC_FALSE; } ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->norm = fnorm; ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); /* set parameter for default relative tolerance convergence test */ snes->ttol = fnorm*snes->rtol; /* test convergence */ ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) PetscFunctionReturn(0); for (i = 0; i < maxits; i++) { lsSuccess = PETSC_TRUE; /* Call general purpose update function */ if (snes->ops->update) { ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); } if (snes->pc && snes->pcside == PC_RIGHT) { ierr = VecCopy(X,Y);CHKERRQ(ierr); ierr = SNESSetInitialFunction(snes->pc, F);CHKERRQ(ierr); ierr = SNESSetInitialFunctionNorm(snes->pc, fnorm);CHKERRQ(ierr); ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,Y,snes->vec_rhs,0);CHKERRQ(ierr); ierr = SNESSolve(snes->pc, snes->vec_rhs, Y);CHKERRQ(ierr); ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,Y,snes->vec_rhs,0);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { snes->reason = SNES_DIVERGED_INNER; PetscFunctionReturn(0); } ierr = VecAYPX(Y,-1.0,X);CHKERRQ(ierr); } else { ierr = VecCopy(F,Y);CHKERRQ(ierr); } ierr = SNESLineSearchApply(snes->linesearch, X, F, &fnorm, Y);CHKERRQ(ierr); ierr = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); ierr = SNESLineSearchGetSuccess(snes->linesearch, &lsSuccess);CHKERRQ(ierr); if (!lsSuccess) { if (++snes->numFailures >= snes->maxFailures) { snes->reason = SNES_DIVERGED_LINE_SEARCH; break; } } if (snes->nfuncs >= snes->max_funcs) { snes->reason = SNES_DIVERGED_FUNCTION_COUNT; break; } if (snes->domainerror) { snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; PetscFunctionReturn(0); } /* Monitor convergence */ ierr = PetscObjectAMSTakeAccess((PetscObject)snes);CHKERRQ(ierr); snes->iter = i+1; snes->norm = fnorm; ierr = PetscObjectAMSGrantAccess((PetscObject)snes);CHKERRQ(ierr); ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); /* Test for convergence */ ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); if (snes->reason) break; } if (i == maxits) { ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRQ(ierr); if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT; } PetscFunctionReturn(0); }