PetscErrorCode BSSCR_KSPConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *cctx) { PetscErrorCode ierr; #if(PETSC_VERSION_MAJOR == 3) BSSCR_KSPConverged_Ctx *ctx = (BSSCR_KSPConverged_Ctx *)cctx; KSP_BSSCR *bsscr = ctx->bsscr; #else KSP_BSSCR *bsscr = (KSP_BSSCR*)cctx; #endif PetscFunctionBegin; #if ( (PETSC_VERSION_MAJOR == 3) && (PETSC_VERSION_MINOR >=5 ) ) ierr = KSPConvergedDefault(ksp,n,rnorm,reason,ctx->ctx);CHKERRQ(ierr); #endif #if ( (PETSC_VERSION_MAJOR == 3) && (PETSC_VERSION_MINOR <=4 ) ) ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx->ctx);CHKERRQ(ierr); #endif #if ( PETSC_VERSION_MAJOR < 3) ierr = KSPDefaultConverged(ksp,n,rnorm,reason,cctx);CHKERRQ(ierr); #endif if (*reason) { ierr = PetscInfo2(ksp,"default convergence test KSP iterations=%D, rnorm=%G\n",n,rnorm);CHKERRQ(ierr); } if(ksp->its < bsscr->min_it){ ksp->reason = KSP_CONVERGED_ITERATING; } PetscFunctionReturn(0); }
MGSolver_Status _GetSolveStatus( MGSolver_PETScData* mgData ) { PC pc; const KSPType kspType; const PCType pcType; KSPConvergedReason reason; PetscErrorCode ec; ec = KSPGetType( mgData->ksp, &kspType ); CheckPETScError( ec ); ec = KSPGetPC( mgData->ksp, &pc ); CheckPETScError( ec ); ec = PCGetType( pc, &pcType ); CheckPETScError( ec ); if( !strcmp( kspType, KSPRICHARDSON ) && !strcmp( pcType, PCSOR ) ) { double rnorm; PetscInt curIt; //rnorm = PETScMatrixSolver_GetResidualNorm( self ); //curIt = PETScMatrixSolver_GetIterations( self ); rnorm = _GetResidualNorm( mgData ); KSPGetIterationNumber( mgData->ksp, &curIt ); //PETScMatrixSolver_SetNormType( self, MultigridSolver_NormType_Preconditioned ); KSPSetNormType( mgData->ksp, MultigridSolver_NormType_Preconditioned ); ec = KSPDefaultConverged( mgData->ksp, curIt, (PetscScalar)rnorm, &reason, PETSC_NULL ); CheckPETScError( ec ); } else { ec = KSPGetConvergedReason( mgData->ksp, &reason ); CheckPETScError( ec ); } return reason; }
/*@C KSPLSQRDefaultConverged - Determines convergence of the LSQR Krylov method. This calls KSPDefaultConverged() and if that does not determine convergence then checks convergence for the least squares problem. Collective on KSP Input Parameters: + ksp - iterative context . n - iteration number . rnorm - 2-norm residual value (may be estimated) - ctx - convergence context which must be created by KSPDefaultConvergedCreate() reason is set to: + positive - if the iteration has converged; . negative - if residual norm exceeds divergence threshold; - 0 - otherwise. Notes: Possible convergence for the least squares problem (which is based on the residual of the normal equations) are KSP_CONVERGED_RTOL_NORMAL norm and KSP_CONVERGED_ATOL_NORMAL. Level: intermediate .keywords: KSP, default, convergence, residual .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged(), KSPConvergedReason, KSPGetConvergedReason(), KSPDefaultConvergedSetUIRNorm(), KSPDefaultConvergedSetUMIRNorm(), KSPDefaultConvergedCreate(), KSPDefaultConvergedDestroy(), KSPDefaultConverged() @*/ PetscErrorCode KSPLSQRDefaultConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx) { PetscErrorCode ierr; KSP_LSQR *lsqr = (KSP_LSQR*)ksp->data; PetscFunctionBegin; ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx);CHKERRQ(ierr); if (!n || *reason) PetscFunctionReturn(0); if (lsqr->arnorm/lsqr->rhs_norm < ksp->rtol) *reason = KSP_CONVERGED_RTOL_NORMAL; if (lsqr->arnorm < ksp->abstol) *reason = KSP_CONVERGED_ATOL_NORMAL; PetscFunctionReturn(0); }
EXTERN_C_BEGIN /* These are not usually called from Fortran but allow Fortran users to transparently set these monitors from .F code functions, hence no STDCALL */ void kspdefaultconverged_(KSP *ksp,PetscInt *n,PetscReal *rnorm,KSPConvergedReason *flag,void *dummy,PetscErrorCode *ierr) { CHKFORTRANNULLOBJECT(dummy); *ierr = KSPDefaultConverged(*ksp,*n,*rnorm,flag,dummy); }
PetscErrorCode SNES_TR_KSPConverged_Private(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *cctx) { SNES_TR_KSPConverged_Ctx *ctx = (SNES_TR_KSPConverged_Ctx *)cctx; SNES snes = ctx->snes; SNES_TR *neP = (SNES_TR*)snes->data; Vec x; PetscReal nrm; PetscErrorCode ierr; PetscFunctionBegin; ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx->ctx);CHKERRQ(ierr); if (*reason) { ierr = PetscInfo2(snes,"default convergence test KSP iterations=%D, rnorm=%G\n",n,rnorm);CHKERRQ(ierr); } /* Determine norm of solution */ ierr = KSPBuildSolution(ksp,0,&x);CHKERRQ(ierr); ierr = VecNorm(x,NORM_2,&nrm);CHKERRQ(ierr); if (nrm >= neP->delta) { ierr = PetscInfo2(snes,"Ending linear iteration early, delta=%G, length=%G\n",neP->delta,nrm);CHKERRQ(ierr); *reason = KSP_CONVERGED_STEP_LENGTH; } PetscFunctionReturn(0); }
PetscErrorCode petscConverged(KSP ksp, PetscInt n, PetscReal rnorm, KSPConvergedReason * reason, void * ctx) { // Cast the context pointer coming from PETSc to an FEProblem& and // get a reference to the System from it. FEProblem & problem = *static_cast<FEProblem *>(ctx); // Let's be nice and always check PETSc error codes. PetscErrorCode ierr = 0; // We want the default behavior of the KSPDefaultConverged test, but // we don't want PETSc to die in that function with a CHKERRQ // call... that is probably extremely unlikely/impossible, but just // to be on the safe side, we push a different error handler before // calling KSPDefaultConverged(). ierr = PetscPushErrorHandler(PetscReturnErrorHandler, /*void* ctx=*/ PETSC_NULL); CHKERRABORT(problem.comm().get(),ierr); #if PETSC_VERSION_LESS_THAN(3,0,0) // Prior to PETSc 3.0.0, you could call KSPDefaultConverged with a NULL context // pointer, as it was unused. KSPDefaultConverged(ksp, n, rnorm, reason, PETSC_NULL); #elif PETSC_RELEASE_LESS_THAN(3,5,0) // As of PETSc 3.0.0, you must call KSPDefaultConverged with a // non-NULL context pointer which must be created with // KSPDefaultConvergedCreate(), and destroyed with // KSPDefaultConvergedDestroy(). void* default_ctx = NULL; KSPDefaultConvergedCreate(&default_ctx); KSPDefaultConverged(ksp, n, rnorm, reason, default_ctx); KSPDefaultConvergedDestroy(default_ctx); #else // As of PETSc 3.5.0, use KSPConvergedDefaultXXX void* default_ctx = NULL; KSPConvergedDefaultCreate(&default_ctx); KSPConvergedDefault(ksp, n, rnorm, reason, default_ctx); KSPConvergedDefaultDestroy(default_ctx); #endif // Pop the Error handler we pushed on the stack to go back // to default PETSc error handling behavior. ierr = PetscPopErrorHandler(); CHKERRABORT(problem.comm().get(),ierr); // Get tolerances from the KSP object PetscReal rtol = 0.; PetscReal atol = 0.; PetscReal dtol = 0.; PetscInt maxits = 0; ierr = KSPGetTolerances(ksp, &rtol, &atol, &dtol, &maxits); CHKERRABORT(problem.comm().get(),ierr); // Now do some additional MOOSE-specific tests... std::string msg; MooseLinearConvergenceReason moose_reason = problem.checkLinearConvergence(msg, n, rnorm, rtol, atol, dtol, maxits); switch (moose_reason) { case MOOSE_CONVERGED_RTOL: *reason = KSP_CONVERGED_RTOL; break; case MOOSE_CONVERGED_ITS: *reason = KSP_CONVERGED_ITS; break; default: { // If it's not either of the two specific cases we handle, just go // with whatever PETSc decided in KSPDefaultConverged. break; } } return 0; }