コード例 #1
0
ファイル: mgfunc.c プロジェクト: pombredanne/petsc
/*@
   PCMGGetSmootherUp - Gets the KSP context to be used as smoother after
   coarse grid correction (post-smoother).

   Not Collective, KSP returned is parallel if PC is

   Input Parameters:
+  pc - the multigrid context
-  l  - the level (0 is coarsest) to supply

   Ouput Parameters:
.  ksp - the smoother

   Level: advanced

   Notes: calling this will result in a different pre and post smoother so you may need to
         set options on the pre smoother also

.keywords: MG, multigrid, get, smoother, up, post-smoother, level

.seealso: PCMGGetSmootherUp(), PCMGGetSmootherDown()
@*/
PetscErrorCode  PCMGGetSmootherUp(PC pc,PetscInt l,KSP *ksp)
{
  PC_MG          *mg        = (PC_MG*)pc->data;
  PC_MG_Levels   **mglevels = mg->levels;
  PetscErrorCode ierr;
  const char     *prefix;
  MPI_Comm       comm;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(pc,PC_CLASSID,1);
  /*
     This is called only if user wants a different pre-smoother from post.
     Thus we check if a different one has already been allocated,
     if not we allocate it.
  */
  if (!l) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"There is no such thing as a up smoother on the coarse grid");
  if (mglevels[l]->smoothu == mglevels[l]->smoothd) {
    KSPType     ksptype;
    PCType      pctype;
    PC          ipc;
    PetscReal   rtol,abstol,dtol;
    PetscInt    maxits;
    KSPNormType normtype;
    ierr = PetscObjectGetComm((PetscObject)mglevels[l]->smoothd,&comm);CHKERRQ(ierr);
    ierr = KSPGetOptionsPrefix(mglevels[l]->smoothd,&prefix);CHKERRQ(ierr);
    ierr = KSPGetTolerances(mglevels[l]->smoothd,&rtol,&abstol,&dtol,&maxits);CHKERRQ(ierr);
    ierr = KSPGetType(mglevels[l]->smoothd,&ksptype);CHKERRQ(ierr);
    ierr = KSPGetNormType(mglevels[l]->smoothd,&normtype);CHKERRQ(ierr);
    ierr = KSPGetPC(mglevels[l]->smoothd,&ipc);CHKERRQ(ierr);
    ierr = PCGetType(ipc,&pctype);CHKERRQ(ierr);

    ierr = KSPCreate(comm,&mglevels[l]->smoothu);CHKERRQ(ierr);
    ierr = KSPSetErrorIfNotConverged(mglevels[l]->smoothu,pc->erroriffailure);CHKERRQ(ierr);
    ierr = PetscObjectIncrementTabLevel((PetscObject)mglevels[l]->smoothu,(PetscObject)pc,mglevels[0]->levels-l);CHKERRQ(ierr);
    ierr = KSPSetOptionsPrefix(mglevels[l]->smoothu,prefix);CHKERRQ(ierr);
    ierr = KSPSetTolerances(mglevels[l]->smoothu,rtol,abstol,dtol,maxits);CHKERRQ(ierr);
    ierr = KSPSetType(mglevels[l]->smoothu,ksptype);CHKERRQ(ierr);
    ierr = KSPSetNormType(mglevels[l]->smoothu,normtype);CHKERRQ(ierr);
    ierr = KSPSetConvergenceTest(mglevels[l]->smoothu,KSPConvergedSkip,NULL,NULL);CHKERRQ(ierr);
    ierr = KSPGetPC(mglevels[l]->smoothu,&ipc);CHKERRQ(ierr);
    ierr = PCSetType(ipc,pctype);CHKERRQ(ierr);
    ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mglevels[l]->smoothu);CHKERRQ(ierr);
    ierr = PetscObjectComposedDataSetInt((PetscObject) mglevels[l]->smoothu, PetscMGLevelId, mglevels[l]->level);CHKERRQ(ierr);
  }
  if (ksp) *ksp = mglevels[l]->smoothu;
  PetscFunctionReturn(0);
}
コード例 #2
0
ファイル: iterativ.c プロジェクト: mchandra/petsc
/*@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;
      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)) {
    ierr    = PetscInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n");CHKERRQ(ierr);
    *reason = KSP_DIVERGED_NANORINF;
  } 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);
}
コード例 #3
0
PetscErrorCode BSSCR_KSPNormInfConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx)
{
    PetscErrorCode         ierr;
    KSPPWConvergedCtx     *cctx = (KSPPWConvergedCtx*)ctx;
    KSPNormType            normtype;
    PetscReal              min, max, R_max, R_min, R_Ninf;
    Vec                    R, work, w1,w2;
        
    PetscFunctionBegin;
    PetscValidHeaderSpecific(ksp,KSP_COOKIE,1);
    PetscValidPointer(reason,4);
    *reason = KSP_CONVERGED_ITERATING;
                        
    ierr = VecDuplicate(ksp->vec_rhs,&work);CHKERRQ(ierr);
    ierr = VecDuplicate(ksp->vec_rhs,&w1);CHKERRQ(ierr);
    ierr = VecDuplicate(ksp->vec_rhs,&w2);CHKERRQ(ierr);      
                
    KSPBuildResidual( ksp, w1,w2, &R );
    VecNorm( R, NORM_INFINITY, &R_Ninf );
                
    //PetscPrintf( PETSC_COMM_WORLD, "Norm inf convergence %s\n ", ksp->prefix);
        
    cctx->pointwise_max = R_Ninf;
        
    ierr = KSPGetNormType(ksp,&normtype); 
        
    CHKERRQ(ierr);
    if (normtype == KSP_NORM_NO) 
        Stg_SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Use BSSCR_KSPSkipConverged() with KSPNormType of KSP_NORM_NO");
        
    if (!cctx) 
        Stg_SETERRQ(PETSC_ERR_ARG_NULL,"Convergence context must have been created with BSSCR_KSPDefaultConvergedCreate()");
        
    if (!n) {
        /* if user gives initial guess need to compute norm of b */
        if (!ksp->guess_zero && !cctx->initialrtol) {
            PetscReal      snorm;
            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_INFINITY,&snorm);CHKERRQ(ierr);        /*     <- b'*b */       
                                
                PetscPrintf( PETSC_COMM_WORLD,  "Non Zero Guess; RHS - %g\n", snorm);
                                                
            } 
            else {
                Vec z;
                if (!cctx->work) {
                    ierr = VecDuplicate(ksp->vec_rhs,&cctx->work);CHKERRQ(ierr);
                }
                z = cctx->work;
                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_INFINITY,&snorm);CHKERRQ(ierr);                 /*    dp <- b'*B'*B*b */

                } 
                else if (ksp->normtype == KSP_NORM_NATURAL) {
                    PetscScalar norm;
                    Vec bz;
                    ierr = PetscInfo(ksp,"user has provided nonzero initial guess, computing natural norm of RHS\n");CHKERRQ(ierr);
                    //        ierr  = VecDot(ksp->vec_rhs,z,&norm);
                    //        snorm = sqrt(PetscAbsScalar(norm));                            /*    dp <- b'*B*b */
                    VecDuplicate( z, &bz );
                    VecPointwiseMult( bz, ksp->vec_rhs, z );
                    ierr = VecNorm(bz,NORM_INFINITY,&snorm);CHKERRQ(ierr);                 
                    Stg_VecDestroy(&bz);
                }
            }
            /* 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 ( R_Ninf != R_Ninf ) {
        ierr = PetscInfo(ksp,"Linear solver has created a not a number (NaN) as the pointwise residual norm, declaring divergence \n");CHKERRQ(ierr);
        *reason = KSP_DIVERGED_NAN;
    } 
    else 
        if (R_Ninf <= ksp->ttol) {
            if (R_Ninf < ksp->abstol) {
                ierr = PetscInfo3(ksp,"Linear solver has converged. Pointwise residual %G is less than absolute tolerance %G at iteration %D\n",R_Ninf,ksp->abstol,n);
                CHKERRQ(ierr);
                *reason = KSP_CONVERGED_ATOL;
            } 
            else {
                if (cctx->initialrtol) {
                    ierr = PetscInfo4(ksp,"Linear solver has converged. Norm_infinity %G is less than relative tolerance %G times initial Norm_infinity %G at iteration %D\n",R_Ninf,ksp->rtol,ksp->rnorm0,n);
                    CHKERRQ(ierr);
                } 
                else {
                    ierr = PetscInfo4(ksp,"Linear solver has converged. Norm_infinity %G is less than relative tolerance %G times initial norm_infinity right hand side %G at iteration %D\n",R_Ninf,ksp->rtol,ksp->rnorm0,n);CHKERRQ(ierr);
                }
                *reason = KSP_CONVERGED_RTOL;
            }
        } 
        else 
            if (R_Ninf >= ksp->divtol*ksp->rnorm0) {
                ierr = PetscInfo3(ksp,"Linear solver is diverging. Initial right hand size Norm_infinity value %G, current residual norm %G at iteration %D\n",ksp->rnorm0,R_Ninf,n);CHKERRQ(ierr);
                *reason = KSP_DIVERGED_DTOL;
            }
                        
    /* trash all work vectors here */

    Stg_VecDestroy(&work);
    Stg_VecDestroy(&w1);
    Stg_VecDestroy(&w2);
        
    PetscFunctionReturn(0);
}
コード例 #4
0
PETSC_EXTERN void PETSC_STDCALL  kspgetnormtype_(KSP ksp,KSPNormType *normtype, int *__ierr ){
*__ierr = KSPGetNormType(
	(KSP)PetscToPointer((ksp) ),
	(KSPNormType* )PetscToPointer((normtype) ));
}