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); }
/*@C KSPLSQRDefaultConverged - Determines convergence of the LSQR Krylov method. This calls KSPConvergedDefault() 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 KSPConvergedDefaultCreate() 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(), KSPConvergedSkip(), KSPConvergedReason, KSPGetConvergedReason(), KSPConvergedDefaultSetUIRNorm(), KSPConvergedDefaultSetUMIRNorm(), KSPConvergedDefaultCreate(), KSPConvergedDefaultDestroy(), KSPConvergedDefault() @*/ PetscErrorCode KSPLSQRDefaultConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx) { PetscErrorCode ierr; KSP_LSQR *lsqr = (KSP_LSQR*)ksp->data; PetscFunctionBegin; ierr = KSPConvergedDefault(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); }
/* This convergence test determines if the two norm of the solution lies outside the trust region, if so it halts. */ static PetscErrorCode SNESTR_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_NEWTONTR *neP = (SNES_NEWTONTR*)snes->data; Vec x; PetscReal nrm; PetscErrorCode ierr; PetscFunctionBegin; ierr = KSPConvergedDefault(ksp,n,rnorm,reason,ctx->ctx);CHKERRQ(ierr); if (*reason) { ierr = PetscInfo2(snes,"default convergence test KSP iterations=%D, rnorm=%g\n",n,(double)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",(double)neP->delta,(double)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; }
PetscErrorCode KSPSolve_TSIRM(KSP ksp) { PetscErrorCode ierr; KSP_TSIRM *tsirm = (KSP_TSIRM*)ksp->data; KSP sub_ksp; PC pc; Mat AS; Vec x,b; PetscScalar *array; PetscReal norm = 20; PetscInt i,*ind_row,first_iteration = 1,its = 0,total = 0,col = 0; PetscInt restart = 30; KSP ksp_min; /* KSP for minimization */ PC pc_min; /* PC for minimization */ PetscFunctionBegin; x = ksp->vec_sol; /* Solution vector */ b = ksp->vec_rhs; /* Right-hand side vector */ /* Row indexes (these indexes are global) */ ierr = PetscMalloc1(tsirm->Iend-tsirm->Istart,&ind_row); CHKERRQ(ierr); for (i=0; i<tsirm->Iend-tsirm->Istart; i++) ind_row[i] = i+tsirm->Istart; /* Inner solver */ ierr = KSPGetPC(ksp,&pc); CHKERRQ(ierr); ierr = PCKSPGetKSP(pc,&sub_ksp); CHKERRQ(ierr); ierr = KSPSetTolerances(sub_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,restart); CHKERRQ(ierr); /* previously it seemed good but with SNES it seems not good... */ ierr = KSP_MatMult(sub_ksp,tsirm->A,x,tsirm->r); CHKERRQ(ierr); ierr = VecAXPY(tsirm->r,-1,b); CHKERRQ(ierr); ierr = VecNorm(tsirm->r,NORM_2,&norm); CHKERRQ(ierr); ksp->its = 0; ierr = KSPConvergedDefault(ksp,ksp->its,norm,&ksp->reason,ksp->cnvP); CHKERRQ(ierr); ierr = KSPSetInitialGuessNonzero(sub_ksp,PETSC_TRUE); CHKERRQ(ierr); do { for (col=0; col<tsirm->size_ls && ksp->reason==0; col++) { /* Solve (inner iteration) */ ierr = KSPSolve(sub_ksp,b,x); CHKERRQ(ierr); ierr = KSPGetIterationNumber(sub_ksp,&its); CHKERRQ(ierr); total += its; /* Build S^T */ ierr = VecGetArray(x,&array); CHKERRQ(ierr); ierr = MatSetValues(tsirm->S,tsirm->Iend-tsirm->Istart,ind_row,1,&col,array,INSERT_VALUES); CHKERRQ(ierr); ierr = VecRestoreArray(x,&array); CHKERRQ(ierr); ierr = KSPGetResidualNorm(sub_ksp,&norm); CHKERRQ(ierr); ksp->rnorm = norm; ksp->its ++; ierr = KSPConvergedDefault(ksp,ksp->its,norm,&ksp->reason,ksp->cnvP); CHKERRQ(ierr); ierr = KSPMonitor(ksp,ksp->its,norm); CHKERRQ(ierr); } /* Minimization step */ if (!ksp->reason) { ierr = MatAssemblyBegin(tsirm->S,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(tsirm->S,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); if (first_iteration) { ierr = MatMatMult(tsirm->A,tsirm->S,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AS); CHKERRQ(ierr); first_iteration = 0; } else { ierr = MatMatMult(tsirm->A,tsirm->S,MAT_REUSE_MATRIX,PETSC_DEFAULT,&AS); CHKERRQ(ierr); } /* CGLS or LSQR method to minimize the residuals*/ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp_min); CHKERRQ(ierr); if (tsirm->cgls) { ierr = KSPSetType(ksp_min,KSPCGLS); CHKERRQ(ierr); } else { ierr = KSPSetType(ksp_min,KSPLSQR); CHKERRQ(ierr); } ierr = KSPSetOperators(ksp_min,AS,AS); CHKERRQ(ierr); ierr = KSPSetTolerances(ksp_min,tsirm->tol_ls,PETSC_DEFAULT,PETSC_DEFAULT,tsirm->maxiter_ls); CHKERRQ(ierr); ierr = KSPGetPC(ksp_min,&pc_min); CHKERRQ(ierr); ierr = PCSetType(pc_min,PCNONE); CHKERRQ(ierr); ierr = KSPSolve(ksp_min,b,tsirm->Alpha); CHKERRQ(ierr); /* Find Alpha such that ||AS Alpha = b|| */ ierr = KSPDestroy(&ksp_min); CHKERRQ(ierr); /* Apply minimization */ ierr = MatMult(tsirm->S,tsirm->Alpha,x); CHKERRQ(ierr); /* x = S * Alpha */ } } while (ksp->its<ksp->max_it && !ksp->reason); ierr = MatDestroy(&AS); CHKERRQ(ierr); ierr = PetscFree(ind_row); CHKERRQ(ierr); ksp->its = total; PetscFunctionReturn(0); }
PETSC_EXTERN void kspconvergeddefault_(KSP *ksp,PetscInt *n,PetscReal *rnorm,KSPConvergedReason *flag,void *dummy,PetscErrorCode *ierr) { CHKFORTRANNULLOBJECT(dummy); *ierr = KSPConvergedDefault(*ksp,*n,*rnorm,flag,dummy); }