Actual source code: rich.c

  1: #define PETSCKSP_DLL

  3: /*          
  4:             This implements Richardson Iteration.       
  5: */
 6:  #include private/kspimpl.h
 7:  #include ../src/ksp/ksp/impls/rich/richardsonimpl.h

 11: PetscErrorCode KSPSetUp_Richardson(KSP ksp)
 12: {

 16:   if (ksp->pc_side == PC_RIGHT) {SETERRQ(PETSC_ERR_SUP,"no right preconditioning for KSPRICHARDSON");}
 17:   else if (ksp->pc_side == PC_SYMMETRIC) {SETERRQ(PETSC_ERR_SUP,"no symmetric preconditioning for KSPRICHARDSON");}
 18:   KSPDefaultGetWork(ksp,2);
 19:   return(0);
 20: }

 24: PetscErrorCode  KSPSolve_Richardson(KSP ksp)
 25: {
 27:   PetscInt       i,maxit;
 28:   MatStructure   pflag;
 29:   PetscReal      rnorm = 0.0;
 30:   PetscScalar    scale;
 31:   Vec            x,b,r,z;
 32:   PetscInt       xs, ws;
 33:   Mat            Amat,Pmat;
 34:   KSP_Richardson *richardsonP = (KSP_Richardson*)ksp->data;
 35:   PetscTruth     exists,diagonalscale;

 38:   if (ksp->normtype == KSP_NORM_NATURAL) SETERRQ(PETSC_ERR_SUP,"Cannot use natural residual norm for KSPRICHARDSON");

 40:   PCDiagonalScale(ksp->pc,&diagonalscale);
 41:   if (diagonalscale) SETERRQ1(PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);

 43:   ksp->its = 0;

 45:   PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
 46:   x       = ksp->vec_sol;
 47:   b       = ksp->vec_rhs;
 48:   VecGetSize(x,&xs);
 49:   VecGetSize(ksp->work[0],&ws);
 50:   if (xs != ws) {
 51:     KSPDefaultFreeWork(ksp);
 52:     KSPDefaultGetWork(ksp,2);
 53:   }
 54:   r       = ksp->work[0];
 55:   z       = ksp->work[1];
 56:   maxit   = ksp->max_it;

 58:   /* if user has provided fast Richardson code use that */
 59:   PCApplyRichardsonExists(ksp->pc,&exists);
 60:   if (exists && !ksp->numbermonitors && !ksp->transpose_solve) {
 61:     PCRichardsonConvergedReason reason;
 62:     PCApplyRichardson(ksp->pc,b,x,r,ksp->rtol,ksp->abstol,ksp->divtol,maxit,ksp->guess_zero,&ksp->its,&reason);
 63:     ksp->reason = (KSPConvergedReason)reason;
 64:     return(0);
 65:   }

 67:   scale   = richardsonP->scale;

 69:   if (!ksp->guess_zero) {                          /*   r <- b - A x     */
 70:     KSP_MatMult(ksp,Amat,x,r);
 71:     VecAYPX(r,-1.0,b);
 72:   } else {
 73:     VecCopy(b,r);
 74:   }

 76:   ksp->its = 0;
 77:   for (i=0; i<maxit; i++) {

 79:     if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
 80:       VecNorm(r,NORM_2,&rnorm); /*   rnorm <- r'*r     */
 81:       KSPMonitor(ksp,i,rnorm);
 82:       ksp->rnorm = rnorm;
 83:       KSPLogResidualHistory(ksp,rnorm);
 84:       (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);
 85:       if (ksp->reason) break;
 86:     }

 88:     KSP_PCApply(ksp,r,z);    /*   z <- B r          */

 90:     if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
 91:       VecNorm(z,NORM_2,&rnorm); /*   rnorm <- z'*z     */
 92:       KSPMonitor(ksp,i,rnorm);
 93:       ksp->rnorm = rnorm;
 94:       KSPLogResidualHistory(ksp,rnorm);
 95:       (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);
 96:       if (ksp->reason) break;
 97:     }
 98: 
 99:     VecAXPY(x,scale,z);    /*   x  <- x + scale z */
100:     ksp->its++;

102:     KSP_MatMult(ksp,Amat,x,r);      /*   r  <- b - Ax      */
103:     VecAYPX(r,-1.0,b);
104:   }
105:   if (!ksp->reason) {
106:     if (ksp->normtype != KSP_NORM_NO) {
107:       if (ksp->normtype == KSP_NORM_UNPRECONDITIONED){
108:         VecNorm(r,NORM_2,&rnorm);     /*   rnorm <- r'*r     */
109:       } else {
110:         KSP_PCApply(ksp,r,z);   /*   z <- B r          */
111:         VecNorm(z,NORM_2,&rnorm);     /*   rnorm <- z'*z     */
112:       }
113:       PetscObjectTakeAccess(ksp);
114:       ksp->rnorm = rnorm;
115:       PetscObjectGrantAccess(ksp);
116:       KSPLogResidualHistory(ksp,rnorm);
117:       KSPMonitor(ksp,i,rnorm);
118:     }
119:     if (ksp->its >= ksp->max_it) {
120:       if (ksp->normtype != KSP_NORM_NO) {
121:         (*ksp->converged)(ksp,i,rnorm,&ksp->reason,ksp->cnvP);
122:         if (!ksp->reason) ksp->reason = KSP_DIVERGED_ITS;
123:       } else {
124:         ksp->reason = KSP_CONVERGED_ITS;
125:       }
126:     }
127:   }
128:   return(0);
129: }

133: PetscErrorCode KSPView_Richardson(KSP ksp,PetscViewer viewer)
134: {
135:   KSP_Richardson *richardsonP = (KSP_Richardson*)ksp->data;
137:   PetscTruth     iascii;

140:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
141:   if (iascii) {
142:     PetscViewerASCIIPrintf(viewer,"  Richardson: damping factor=%G\n",richardsonP->scale);
143:   } else {
144:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for KSP Richardson",((PetscObject)viewer)->type_name);
145:   }
146:   return(0);
147: }

151: PetscErrorCode KSPSetFromOptions_Richardson(KSP ksp)
152: {
153:   KSP_Richardson *rich = (KSP_Richardson*)ksp->data;
155:   PetscReal      tmp;
156:   PetscTruth     flg;

159:   PetscOptionsHead("KSP Richardson Options");
160:     PetscOptionsReal("-ksp_richardson_scale","damping factor","KSPRichardsonSetScale",rich->scale,&tmp,&flg);
161:     if (flg) { KSPRichardsonSetScale(ksp,tmp); }
162:   PetscOptionsTail();
163:   return(0);
164: }

168: PetscErrorCode KSPDestroy_Richardson(KSP ksp)
169: {

173:   KSPDefaultDestroy(ksp);
174:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPRichardsonSetScale_C","",PETSC_NULL);
175:   return(0);
176: }

181: PetscErrorCode  KSPRichardsonSetScale_Richardson(KSP ksp,PetscReal scale)
182: {
183:   KSP_Richardson *richardsonP;

186:   richardsonP = (KSP_Richardson*)ksp->data;
187:   richardsonP->scale = scale;
188:   return(0);
189: }

192: /*MC
193:      KSPRICHARDSON - The preconditioned Richardson iterative method

195:    Options Database Keys:
196: .   -ksp_richardson_scale - damping factor on the correction (defaults to 1.0)

198:    Level: beginner

200:    Notes: x^{n+1} = x^{n} + scale*B(b - A x^{n})
201:  
202:           Here B is the application of the preconditioner

204:           This method often (usually) will not converge unless scale is very small. It
205: is described in

207:   "The Approximate Arithmetical Solution by Finite Differences of Physical Problems Involving
208:    Differential Equations, with an Application to the Stresses in a Masonry Dam",
209:   L. F. Richardson, Philosophical Transactions of the Royal Society of London. Series A,
210:   Containing Papers of a Mathematical or Physical Character, Vol. 210, 1911 (1911), pp. 307-357.

212:    Notes: For some preconditioners, currently SOR, the convergence test is skipped to improve speed,
213:     thus it always iterates the maximum number of iterations you've selected. When -ksp_monitor 
214:     (or any other monitor) is turned on, the norm is computed at each iteration and so the convergence test is run unless
215:     you specifically call KSPSetNormType(ksp,KSP_NORM_NO);

217:          For some preconditioners, currently PCMG and PCHYPRE with BoomerAMG if -ksp_monitor (and also
218:     any other monitor) is not turned on then the convergence test is done by the preconditioner itself and
219:     so the solver may run more or fewer iterations then if -ksp_monitor is selected.

221: .seealso:  KSPCreate(), KSPSetType(), KSPType (for list of available types), KSP,
222:            KSPRichardsonSetScale()

224: M*/

229: PetscErrorCode  KSPCreate_Richardson(KSP ksp)
230: {
232:   KSP_Richardson *richardsonP;

235:   PetscNewLog(ksp,KSP_Richardson,&richardsonP);
236:   ksp->data                        = (void*)richardsonP;

238:   ksp->normtype                    = KSP_NORM_PRECONDITIONED;
239:   ksp->pc_side                     = PC_LEFT;

241:   ksp->ops->setup                  = KSPSetUp_Richardson;
242:   ksp->ops->solve                  = KSPSolve_Richardson;
243:   ksp->ops->destroy                = KSPDestroy_Richardson;
244:   ksp->ops->buildsolution          = KSPDefaultBuildSolution;
245:   ksp->ops->buildresidual          = KSPDefaultBuildResidual;
246:   ksp->ops->view                   = KSPView_Richardson;
247:   ksp->ops->setfromoptions         = KSPSetFromOptions_Richardson;

249:   PetscObjectComposeFunctionDynamic((PetscObject)ksp,"KSPRichardsonSetScale_C",
250:                                     "KSPRichardsonSetScale_Richardson",
251:                                     KSPRichardsonSetScale_Richardson);
252:   richardsonP->scale               = 1.0;
253:   return(0);
254: }