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: }