static PetscErrorCode SNESComputeFunction_DMDA(SNES snes,Vec X,Vec F,void *ctx) { PetscErrorCode ierr; DM dm; DMSNES_DA *dmdasnes = (DMSNES_DA*)ctx; DMDALocalInfo info; Vec Xloc; void *x,*f; PetscFunctionBegin; PetscValidHeaderSpecific(snes,SNES_CLASSID,1); PetscValidHeaderSpecific(X,VEC_CLASSID,2); PetscValidHeaderSpecific(F,VEC_CLASSID,3); if (!dmdasnes->residuallocal) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Corrupt context"); ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); ierr = DMDAGetLocalInfo(dm,&info);CHKERRQ(ierr); ierr = DMDAVecGetArray(dm,Xloc,&x);CHKERRQ(ierr); switch (dmdasnes->residuallocalimode) { case INSERT_VALUES: { ierr = DMDAVecGetArray(dm,F,&f);CHKERRQ(ierr); ierr = PetscLogEventBegin(SNES_FunctionEval,snes,X,F,0);CHKERRQ(ierr); CHKMEMQ; ierr = (*dmdasnes->residuallocal)(&info,x,f,dmdasnes->residuallocalctx);CHKERRQ(ierr); CHKMEMQ; ierr = PetscLogEventEnd(SNES_FunctionEval,snes,X,F,0);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(dm,F,&f);CHKERRQ(ierr); } break; case ADD_VALUES: { Vec Floc; ierr = DMGetLocalVector(dm,&Floc);CHKERRQ(ierr); ierr = VecZeroEntries(Floc);CHKERRQ(ierr); ierr = DMDAVecGetArray(dm,Floc,&f);CHKERRQ(ierr); ierr = PetscLogEventBegin(SNES_FunctionEval,snes,X,F,0);CHKERRQ(ierr); CHKMEMQ; ierr = (*dmdasnes->residuallocal)(&info,x,f,dmdasnes->residuallocalctx);CHKERRQ(ierr); CHKMEMQ; ierr = PetscLogEventEnd(SNES_FunctionEval,snes,X,F,0);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(dm,Floc,&f);CHKERRQ(ierr); ierr = VecZeroEntries(F);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dm,&Floc);CHKERRQ(ierr); } break; default: SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"Cannot use imode=%d",(int)dmdasnes->residuallocalimode); } ierr = DMDAVecRestoreArray(dm,Xloc,&x);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr); if (snes->domainerror) { ierr = VecSetInf(F);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode PCApply_MyShell(PC pc,Vec x,Vec y) { PetscErrorCode ierr; static PetscInt fail = 0; PetscFunctionBegin; ierr = VecCopy(x,y);CHKERRQ(ierr); if (fail++ > 3) { PetscMPIInt rank; ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr); if (!rank) {ierr = VecSetInf(y);CHKERRQ(ierr);} } PetscFunctionReturn(0); }
PetscErrorCode MatMult_MyShell(Mat A,Vec x,Vec y) { PetscErrorCode ierr; MatShellCtx *matshellctx; static PetscInt fail = 0; PetscFunctionBegin; ierr = MatShellGetContext(A,&matshellctx);CHKERRQ(ierr); ierr = MatMult(matshellctx->Jmf,x,y);CHKERRQ(ierr); if (fail++ > 5) { PetscMPIInt rank; ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr); if (!rank) {ierr = VecSetInf(y);CHKERRQ(ierr);} } PetscFunctionReturn(0); }
/*@C KSPConvergedDefault - Determines convergence of the linear iterative solvers by default Collective on KSP Input Parameters: + ksp - iterative context . n - iteration number . rnorm - residual norm (may be estimated, depending on the method may be the preconditioned residual norm) - ctx - convergence context which must be created by KSPConvergedDefaultCreate() Output Parameter: + positive - if the iteration has converged; . negative - if residual norm exceeds divergence threshold; - 0 - otherwise. Notes: KSPConvergedDefault() reaches convergence when rnorm < MAX (rtol * rnorm_0, abstol); Divergence is detected if rnorm > dtol * rnorm_0, where: + rtol = relative tolerance, . abstol = absolute tolerance. . dtol = divergence tolerance, - rnorm_0 is the two norm of the right hand side. When initial guess is non-zero you can call KSPConvergedDefaultSetUIRNorm() to use the norm of (b - A*(initial guess)) as the starting point for relative norm convergence testing, that is as rnorm_0 Use KSPSetTolerances() to alter the defaults for rtol, abstol, dtol. Use KSPSetNormType() (or -ksp_norm_type <none,preconditioned,unpreconditioned,natural>) to change the norm used for computing rnorm The precise values of reason are macros such as KSP_CONVERGED_RTOL, which are defined in petscksp.h. This routine is used by KSP by default so the user generally never needs call it directly. Use KSPSetConvergenceTest() to provide your own test instead of using this one. Level: intermediate .keywords: KSP, default, convergence, residual .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPConvergedSkip(), KSPConvergedReason, KSPGetConvergedReason(), KSPConvergedDefaultSetUIRNorm(), KSPConvergedDefaultSetUMIRNorm(), KSPConvergedDefaultCreate(), KSPConvergedDefaultDestroy() @*/ PetscErrorCode KSPConvergedDefault(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx) { PetscErrorCode ierr; KSPConvergedDefaultCtx *cctx = (KSPConvergedDefaultCtx*) ctx; KSPNormType normtype; PetscFunctionBegin; PetscValidHeaderSpecific(ksp,KSP_CLASSID,1); PetscValidPointer(reason,4); *reason = KSP_CONVERGED_ITERATING; ierr = KSPGetNormType(ksp,&normtype); CHKERRQ(ierr); if (normtype == KSP_NORM_NONE) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_WRONGSTATE,"Use KSPConvergedSkip() with KSPNormType of KSP_NORM_NONE"); if (!cctx) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_NULL,"Convergence context must have been created with KSPConvergedDefaultCreate()"); if (!n) { /* if user gives initial guess need to compute norm of b */ if (!ksp->guess_zero && !cctx->initialrtol) { PetscReal snorm = 0.0; if (ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->pc_side == PC_RIGHT) { ierr = PetscInfo(ksp,"user has provided nonzero initial guess, computing 2-norm of RHS\n"); CHKERRQ(ierr); ierr = VecNorm(ksp->vec_rhs,NORM_2,&snorm); CHKERRQ(ierr); /* <- b'*b */ } else { Vec z; /* Should avoid allocating the z vector each time but cannot stash it in cctx because if KSPReset() is called the vector size might change */ ierr = VecDuplicate(ksp->vec_rhs,&z); CHKERRQ(ierr); ierr = KSP_PCApply(ksp,ksp->vec_rhs,z); CHKERRQ(ierr); if (ksp->normtype == KSP_NORM_PRECONDITIONED) { ierr = PetscInfo(ksp,"user has provided nonzero initial guess, computing 2-norm of preconditioned RHS\n"); CHKERRQ(ierr); ierr = VecNorm(z,NORM_2,&snorm); CHKERRQ(ierr); /* dp <- b'*B'*B*b */ } else if (ksp->normtype == KSP_NORM_NATURAL) { PetscScalar norm; ierr = PetscInfo(ksp,"user has provided nonzero initial guess, computing natural norm of RHS\n"); CHKERRQ(ierr); ierr = VecDot(ksp->vec_rhs,z,&norm); CHKERRQ(ierr); snorm = PetscSqrtReal(PetscAbsScalar(norm)); /* dp <- b'*B*b */ } ierr = VecDestroy(&z); CHKERRQ(ierr); } /* handle special case of zero RHS and nonzero guess */ if (!snorm) { ierr = PetscInfo(ksp,"Special case, user has provided nonzero initial guess and zero RHS\n"); CHKERRQ(ierr); snorm = rnorm; } if (cctx->mininitialrtol) ksp->rnorm0 = PetscMin(snorm,rnorm); else ksp->rnorm0 = snorm; } else { ksp->rnorm0 = rnorm; } ksp->ttol = PetscMax(ksp->rtol*ksp->rnorm0,ksp->abstol); } if (n <= ksp->chknorm) PetscFunctionReturn(0); if (PetscIsInfOrNanReal(rnorm)) { PCFailedReason pcreason; PetscInt sendbuf,pcreason_max; ierr = PCGetSetUpFailedReason(ksp->pc,&pcreason); CHKERRQ(ierr); sendbuf = (PetscInt)pcreason; ierr = MPI_Allreduce(&sendbuf,&pcreason_max,1,MPIU_INT,MPIU_MAX,PetscObjectComm((PetscObject)ksp)); CHKERRQ(ierr); if (pcreason_max) { *reason = KSP_DIVERGED_PCSETUP_FAILED; ierr = VecSetInf(ksp->vec_sol); CHKERRQ(ierr); ierr = PetscInfo(ksp,"Linear solver pcsetup fails, declaring divergence \n"); CHKERRQ(ierr); } else { *reason = KSP_DIVERGED_NANORINF; ierr = PetscInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n"); CHKERRQ(ierr); } } else if (rnorm <= ksp->ttol) { if (rnorm < ksp->abstol) { ierr = PetscInfo3(ksp,"Linear solver has converged. Residual norm %14.12e is less than absolute tolerance %14.12e at iteration %D\n",(double)rnorm,(double)ksp->abstol,n); CHKERRQ(ierr); *reason = KSP_CONVERGED_ATOL; } else { if (cctx->initialrtol) { ierr = PetscInfo4(ksp,"Linear solver has converged. Residual norm %14.12e is less than relative tolerance %14.12e times initial residual norm %14.12e at iteration %D\n",(double)rnorm,(double)ksp->rtol,(double)ksp->rnorm0,n); CHKERRQ(ierr); } else { ierr = PetscInfo4(ksp,"Linear solver has converged. Residual norm %14.12e is less than relative tolerance %14.12e times initial right hand side norm %14.12e at iteration %D\n",(double)rnorm,(double)ksp->rtol,(double)ksp->rnorm0,n); CHKERRQ(ierr); } *reason = KSP_CONVERGED_RTOL; } } else if (rnorm >= ksp->divtol*ksp->rnorm0) { ierr = PetscInfo3(ksp,"Linear solver is diverging. Initial right hand size norm %14.12e, current residual norm %14.12e at iteration %D\n",(double)ksp->rnorm0,(double)rnorm,n); CHKERRQ(ierr); *reason = KSP_DIVERGED_DTOL; } PetscFunctionReturn(0); }