Actual source code: ex3.c
petsc-3.10.5 2019-03-28
1: static char help[] = "Newton methods to solve u'' + u^{2} = f in parallel.\n\
2: This example employs a user-defined monitoring routine and optionally a user-defined\n\
3: routine to check candidate iterates produced by line search routines.\n\
4: The command line options include:\n\
5: -pre_check_iterates : activate checking of iterates\n\
6: -post_check_iterates : activate checking of iterates\n\
7: -check_tol <tol>: set tolerance for iterate checking\n\
8: -user_precond : activate a (trivial) user-defined preconditioner\n\n";
10: /*T
11: Concepts: SNES^basic parallel example
12: Concepts: SNES^setting a user-defined monitoring routine
13: Processors: n
14: T*/
18: /*
19: Include "petscdm.h" so that we can use data management objects (DMs)
20: Include "petscdmda.h" so that we can use distributed arrays (DMDAs).
21: Include "petscsnes.h" so that we can use SNES solvers. Note that this
22: file automatically includes:
23: petscsys.h - base PETSc routines
24: petscvec.h - vectors
25: petscmat.h - matrices
26: petscis.h - index sets
27: petscksp.h - Krylov subspace methods
28: petscviewer.h - viewers
29: petscpc.h - preconditioners
30: petscksp.h - linear solvers
31: */
33: #include <petscdm.h>
34: #include <petscdmda.h>
35: #include <petscsnes.h>
37: /*
38: User-defined routines.
39: */
40: PetscErrorCode FormJacobian(SNES,Vec,Mat,Mat,void*);
41: PetscErrorCode FormFunction(SNES,Vec,Vec,void*);
42: PetscErrorCode FormInitialGuess(Vec);
43: PetscErrorCode Monitor(SNES,PetscInt,PetscReal,void*);
44: PetscErrorCode PreCheck(SNESLineSearch,Vec,Vec,PetscBool*,void*);
45: PetscErrorCode PostCheck(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*);
46: PetscErrorCode PostSetSubKSP(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*);
47: PetscErrorCode MatrixFreePreconditioner(PC,Vec,Vec);
49: /*
50: User-defined application context
51: */
52: typedef struct {
53: DM da; /* distributed array */
54: Vec F; /* right-hand-side of PDE */
55: PetscMPIInt rank; /* rank of processor */
56: PetscMPIInt size; /* size of communicator */
57: PetscReal h; /* mesh spacing */
58: } ApplicationCtx;
60: /*
61: User-defined context for monitoring
62: */
63: typedef struct {
64: PetscViewer viewer;
65: } MonitorCtx;
67: /*
68: User-defined context for checking candidate iterates that are
69: determined by line search methods
70: */
71: typedef struct {
72: Vec last_step; /* previous iterate */
73: PetscReal tolerance; /* tolerance for changes between successive iterates */
74: ApplicationCtx *user;
75: } StepCheckCtx;
77: typedef struct {
78: PetscInt its0; /* num of prevous outer KSP iterations */
79: } SetSubKSPCtx;
81: int main(int argc,char **argv)
82: {
83: SNES snes; /* SNES context */
84: SNESLineSearch linesearch; /* SNESLineSearch context */
85: Mat J; /* Jacobian matrix */
86: ApplicationCtx ctx; /* user-defined context */
87: Vec x,r,U,F; /* vectors */
88: MonitorCtx monP; /* monitoring context */
89: StepCheckCtx checkP; /* step-checking context */
90: SetSubKSPCtx checkP1;
91: PetscBool pre_check,post_check,post_setsubksp; /* flag indicating whether we're checking candidate iterates */
92: PetscScalar xp,*FF,*UU,none = -1.0;
94: PetscInt its,N = 5,i,maxit,maxf,xs,xm;
95: PetscReal abstol,rtol,stol,norm;
96: PetscBool flg;
98: PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
99: MPI_Comm_rank(PETSC_COMM_WORLD,&ctx.rank);
100: MPI_Comm_size(PETSC_COMM_WORLD,&ctx.size);
101: PetscOptionsGetInt(NULL,NULL,"-n",&N,NULL);
102: ctx.h = 1.0/(N-1);
104: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
105: Create nonlinear solver context
106: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
108: SNESCreate(PETSC_COMM_WORLD,&snes);
110: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111: Create vector data structures; set function evaluation routine
112: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
114: /*
115: Create distributed array (DMDA) to manage parallel grid and vectors
116: */
117: DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,N,1,1,NULL,&ctx.da);
118: DMSetFromOptions(ctx.da);
119: DMSetUp(ctx.da);
121: /*
122: Extract global and local vectors from DMDA; then duplicate for remaining
123: vectors that are the same types
124: */
125: DMCreateGlobalVector(ctx.da,&x);
126: VecDuplicate(x,&r);
127: VecDuplicate(x,&F); ctx.F = F;
128: VecDuplicate(x,&U);
130: /*
131: Set function evaluation routine and vector. Whenever the nonlinear
132: solver needs to compute the nonlinear function, it will call this
133: routine.
134: - Note that the final routine argument is the user-defined
135: context that provides application-specific data for the
136: function evaluation routine.
137: */
138: SNESSetFunction(snes,r,FormFunction,&ctx);
140: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
141: Create matrix data structure; set Jacobian evaluation routine
142: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
144: MatCreate(PETSC_COMM_WORLD,&J);
145: MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,N,N);
146: MatSetFromOptions(J);
147: MatSeqAIJSetPreallocation(J,3,NULL);
148: MatMPIAIJSetPreallocation(J,3,NULL,3,NULL);
150: /*
151: Set Jacobian matrix data structure and default Jacobian evaluation
152: routine. Whenever the nonlinear solver needs to compute the
153: Jacobian matrix, it will call this routine.
154: - Note that the final routine argument is the user-defined
155: context that provides application-specific data for the
156: Jacobian evaluation routine.
157: */
158: SNESSetJacobian(snes,J,J,FormJacobian,&ctx);
160: /*
161: Optionally allow user-provided preconditioner
162: */
163: PetscOptionsHasName(NULL,NULL,"-user_precond",&flg);
164: if (flg) {
165: KSP ksp;
166: PC pc;
167: SNESGetKSP(snes,&ksp);
168: KSPGetPC(ksp,&pc);
169: PCSetType(pc,PCSHELL);
170: PCShellSetApply(pc,MatrixFreePreconditioner);
171: }
173: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174: Customize nonlinear solver; set runtime options
175: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
177: /*
178: Set an optional user-defined monitoring routine
179: */
180: PetscViewerDrawOpen(PETSC_COMM_WORLD,0,0,0,0,400,400,&monP.viewer);
181: SNESMonitorSet(snes,Monitor,&monP,0);
183: /*
184: Set names for some vectors to facilitate monitoring (optional)
185: */
186: PetscObjectSetName((PetscObject)x,"Approximate Solution");
187: PetscObjectSetName((PetscObject)U,"Exact Solution");
189: /*
190: Set SNES/KSP/KSP/PC runtime options, e.g.,
191: -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
192: */
193: SNESSetFromOptions(snes);
195: /*
196: Set an optional user-defined routine to check the validity of candidate
197: iterates that are determined by line search methods
198: */
199: SNESGetLineSearch(snes, &linesearch);
200: PetscOptionsHasName(NULL,NULL,"-post_check_iterates",&post_check);
202: if (post_check) {
203: PetscPrintf(PETSC_COMM_WORLD,"Activating post step checking routine\n");
204: SNESLineSearchSetPostCheck(linesearch,PostCheck,&checkP);
205: VecDuplicate(x,&(checkP.last_step));
207: checkP.tolerance = 1.0;
208: checkP.user = &ctx;
210: PetscOptionsGetReal(NULL,NULL,"-check_tol",&checkP.tolerance,NULL);
211: }
213: PetscOptionsHasName(NULL,NULL,"-post_setsubksp",&post_setsubksp);
214: if (post_setsubksp) {
215: PetscPrintf(PETSC_COMM_WORLD,"Activating post setsubksp\n");
216: SNESLineSearchSetPostCheck(linesearch,PostSetSubKSP,&checkP1);
217: }
219: PetscOptionsHasName(NULL,NULL,"-pre_check_iterates",&pre_check);
220: if (pre_check) {
221: PetscPrintf(PETSC_COMM_WORLD,"Activating pre step checking routine\n");
222: SNESLineSearchSetPreCheck(linesearch,PreCheck,&checkP);
223: }
225: /*
226: Print parameters used for convergence testing (optional) ... just
227: to demonstrate this routine; this information is also printed with
228: the option -snes_view
229: */
230: SNESGetTolerances(snes,&abstol,&rtol,&stol,&maxit,&maxf);
231: PetscPrintf(PETSC_COMM_WORLD,"atol=%g, rtol=%g, stol=%g, maxit=%D, maxf=%D\n",(double)abstol,(double)rtol,(double)stol,maxit,maxf);
233: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
234: Initialize application:
235: Store right-hand-side of PDE and exact solution
236: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
238: /*
239: Get local grid boundaries (for 1-dimensional DMDA):
240: xs, xm - starting grid index, width of local grid (no ghost points)
241: */
242: DMDAGetCorners(ctx.da,&xs,NULL,NULL,&xm,NULL,NULL);
244: /*
245: Get pointers to vector data
246: */
247: DMDAVecGetArray(ctx.da,F,&FF);
248: DMDAVecGetArray(ctx.da,U,&UU);
250: /*
251: Compute local vector entries
252: */
253: xp = ctx.h*xs;
254: for (i=xs; i<xs+xm; i++) {
255: FF[i] = 6.0*xp + PetscPowScalar(xp+1.e-12,6.0); /* +1.e-12 is to prevent 0^6 */
256: UU[i] = xp*xp*xp;
257: xp += ctx.h;
258: }
260: /*
261: Restore vectors
262: */
263: DMDAVecRestoreArray(ctx.da,F,&FF);
264: DMDAVecRestoreArray(ctx.da,U,&UU);
266: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
267: Evaluate initial guess; then solve nonlinear system
268: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
270: /*
271: Note: The user should initialize the vector, x, with the initial guess
272: for the nonlinear solver prior to calling SNESSolve(). In particular,
273: to employ an initial guess of zero, the user should explicitly set
274: this vector to zero by calling VecSet().
275: */
276: FormInitialGuess(x);
277: SNESSolve(snes,NULL,x);
278: SNESGetIterationNumber(snes,&its);
279: PetscPrintf(PETSC_COMM_WORLD,"Number of SNES iterations = %D\n",its);
281: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
282: Check solution and clean up
283: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
285: /*
286: Check the error
287: */
288: VecAXPY(x,none,U);
289: VecNorm(x,NORM_2,&norm);
290: PetscPrintf(PETSC_COMM_WORLD,"Norm of error %g Iterations %D\n",(double)norm,its);
292: /*
293: Free work space. All PETSc objects should be destroyed when they
294: are no longer needed.
295: */
296: PetscViewerDestroy(&monP.viewer);
297: if (post_check) {VecDestroy(&checkP.last_step);}
298: VecDestroy(&x);
299: VecDestroy(&r);
300: VecDestroy(&U);
301: VecDestroy(&F);
302: MatDestroy(&J);
303: SNESDestroy(&snes);
304: DMDestroy(&ctx.da);
305: PetscFinalize();
306: return ierr;
307: }
309: /* ------------------------------------------------------------------- */
310: /*
311: FormInitialGuess - Computes initial guess.
313: Input/Output Parameter:
314: . x - the solution vector
315: */
316: PetscErrorCode FormInitialGuess(Vec x)
317: {
319: PetscScalar pfive = .50;
322: VecSet(x,pfive);
323: return(0);
324: }
326: /* ------------------------------------------------------------------- */
327: /*
328: FormFunction - Evaluates nonlinear function, F(x).
330: Input Parameters:
331: . snes - the SNES context
332: . x - input vector
333: . ctx - optional user-defined context, as set by SNESSetFunction()
335: Output Parameter:
336: . f - function vector
338: Note:
339: The user-defined context can contain any application-specific
340: data needed for the function evaluation.
341: */
342: PetscErrorCode FormFunction(SNES snes,Vec x,Vec f,void *ctx)
343: {
344: ApplicationCtx *user = (ApplicationCtx*) ctx;
345: DM da = user->da;
346: PetscScalar *xx,*ff,*FF,d;
348: PetscInt i,M,xs,xm;
349: Vec xlocal;
352: DMGetLocalVector(da,&xlocal);
353: /*
354: Scatter ghost points to local vector, using the 2-step process
355: DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
356: By placing code between these two statements, computations can
357: be done while messages are in transition.
358: */
359: DMGlobalToLocalBegin(da,x,INSERT_VALUES,xlocal);
360: DMGlobalToLocalEnd(da,x,INSERT_VALUES,xlocal);
362: /*
363: Get pointers to vector data.
364: - The vector xlocal includes ghost point; the vectors x and f do
365: NOT include ghost points.
366: - Using DMDAVecGetArray() allows accessing the values using global ordering
367: */
368: DMDAVecGetArray(da,xlocal,&xx);
369: DMDAVecGetArray(da,f,&ff);
370: DMDAVecGetArray(da,user->F,&FF);
372: /*
373: Get local grid boundaries (for 1-dimensional DMDA):
374: xs, xm - starting grid index, width of local grid (no ghost points)
375: */
376: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
377: DMDAGetInfo(da,NULL,&M,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
379: /*
380: Set function values for boundary points; define local interior grid point range:
381: xsi - starting interior grid index
382: xei - ending interior grid index
383: */
384: if (xs == 0) { /* left boundary */
385: ff[0] = xx[0];
386: xs++;xm--;
387: }
388: if (xs+xm == M) { /* right boundary */
389: ff[xs+xm-1] = xx[xs+xm-1] - 1.0;
390: xm--;
391: }
393: /*
394: Compute function over locally owned part of the grid (interior points only)
395: */
396: d = 1.0/(user->h*user->h);
397: for (i=xs; i<xs+xm; i++) ff[i] = d*(xx[i-1] - 2.0*xx[i] + xx[i+1]) + xx[i]*xx[i] - FF[i];
399: /*
400: Restore vectors
401: */
402: DMDAVecRestoreArray(da,xlocal,&xx);
403: DMDAVecRestoreArray(da,f,&ff);
404: DMDAVecRestoreArray(da,user->F,&FF);
405: DMRestoreLocalVector(da,&xlocal);
406: return(0);
407: }
409: /* ------------------------------------------------------------------- */
410: /*
411: FormJacobian - Evaluates Jacobian matrix.
413: Input Parameters:
414: . snes - the SNES context
415: . x - input vector
416: . dummy - optional user-defined context (not used here)
418: Output Parameters:
419: . jac - Jacobian matrix
420: . B - optionally different preconditioning matrix
421: . flag - flag indicating matrix structure
422: */
423: PetscErrorCode FormJacobian(SNES snes,Vec x,Mat jac,Mat B,void *ctx)
424: {
425: ApplicationCtx *user = (ApplicationCtx*) ctx;
426: PetscScalar *xx,d,A[3];
428: PetscInt i,j[3],M,xs,xm;
429: DM da = user->da;
432: /*
433: Get pointer to vector data
434: */
435: DMDAVecGetArrayRead(da,x,&xx);
436: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
438: /*
439: Get range of locally owned matrix
440: */
441: DMDAGetInfo(da,NULL,&M,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
443: /*
444: Determine starting and ending local indices for interior grid points.
445: Set Jacobian entries for boundary points.
446: */
448: if (xs == 0) { /* left boundary */
449: i = 0; A[0] = 1.0;
451: MatSetValues(jac,1,&i,1,&i,A,INSERT_VALUES);
452: xs++;xm--;
453: }
454: if (xs+xm == M) { /* right boundary */
455: i = M-1;
456: A[0] = 1.0;
457: MatSetValues(jac,1,&i,1,&i,A,INSERT_VALUES);
458: xm--;
459: }
461: /*
462: Interior grid points
463: - Note that in this case we set all elements for a particular
464: row at once.
465: */
466: d = 1.0/(user->h*user->h);
467: for (i=xs; i<xs+xm; i++) {
468: j[0] = i - 1; j[1] = i; j[2] = i + 1;
469: A[0] = A[2] = d; A[1] = -2.0*d + 2.0*xx[i];
470: MatSetValues(jac,1,&i,3,j,A,INSERT_VALUES);
471: }
473: /*
474: Assemble matrix, using the 2-step process:
475: MatAssemblyBegin(), MatAssemblyEnd().
476: By placing code between these two statements, computations can be
477: done while messages are in transition.
479: Also, restore vector.
480: */
482: MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
483: DMDAVecRestoreArrayRead(da,x,&xx);
484: MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
486: return(0);
487: }
489: /* ------------------------------------------------------------------- */
490: /*
491: Monitor - Optional user-defined monitoring routine that views the
492: current iterate with an x-window plot. Set by SNESMonitorSet().
494: Input Parameters:
495: snes - the SNES context
496: its - iteration number
497: norm - 2-norm function value (may be estimated)
498: ctx - optional user-defined context for private data for the
499: monitor routine, as set by SNESMonitorSet()
501: Note:
502: See the manpage for PetscViewerDrawOpen() for useful runtime options,
503: such as -nox to deactivate all x-window output.
504: */
505: PetscErrorCode Monitor(SNES snes,PetscInt its,PetscReal fnorm,void *ctx)
506: {
508: MonitorCtx *monP = (MonitorCtx*) ctx;
509: Vec x;
512: PetscPrintf(PETSC_COMM_WORLD,"iter = %D,SNES Function norm %g\n",its,(double)fnorm);
513: SNESGetSolution(snes,&x);
514: VecView(x,monP->viewer);
515: return(0);
516: }
518: /* ------------------------------------------------------------------- */
519: /*
520: PreCheck - Optional user-defined routine that checks the validity of
521: candidate steps of a line search method. Set by SNESLineSearchSetPreCheck().
523: Input Parameters:
524: snes - the SNES context
525: xcurrent - current solution
526: y - search direction and length
528: Output Parameters:
529: y - proposed step (search direction and length) (possibly changed)
530: changed_y - tells if the step has changed or not
531: */
532: PetscErrorCode PreCheck(SNESLineSearch linesearch,Vec xcurrent,Vec y, PetscBool *changed_y, void * ctx)
533: {
535: *changed_y = PETSC_FALSE;
536: return(0);
537: }
539: /* ------------------------------------------------------------------- */
540: /*
541: PostCheck - Optional user-defined routine that checks the validity of
542: candidate steps of a line search method. Set by SNESLineSearchSetPostCheck().
544: Input Parameters:
545: snes - the SNES context
546: ctx - optional user-defined context for private data for the
547: monitor routine, as set by SNESLineSearchSetPostCheck()
548: xcurrent - current solution
549: y - search direction and length
550: x - the new candidate iterate
552: Output Parameters:
553: y - proposed step (search direction and length) (possibly changed)
554: x - current iterate (possibly modified)
556: */
557: PetscErrorCode PostCheck(SNESLineSearch linesearch,Vec xcurrent,Vec y,Vec x,PetscBool *changed_y,PetscBool *changed_x, void * ctx)
558: {
560: PetscInt i,iter,xs,xm;
561: StepCheckCtx *check;
562: ApplicationCtx *user;
563: PetscScalar *xa,*xa_last,tmp;
564: PetscReal rdiff;
565: DM da;
566: SNES snes;
569: *changed_x = PETSC_FALSE;
570: *changed_y = PETSC_FALSE;
572: SNESLineSearchGetSNES(linesearch, &snes);
573: check = (StepCheckCtx*)ctx;
574: user = check->user;
575: SNESGetIterationNumber(snes,&iter);
577: /* iteration 1 indicates we are working on the second iteration */
578: if (iter > 0) {
579: da = user->da;
580: PetscPrintf(PETSC_COMM_WORLD,"Checking candidate step at iteration %D with tolerance %g\n",iter,(double)check->tolerance);
582: /* Access local array data */
583: DMDAVecGetArray(da,check->last_step,&xa_last);
584: DMDAVecGetArray(da,x,&xa);
585: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
587: /*
588: If we fail the user-defined check for validity of the candidate iterate,
589: then modify the iterate as we like. (Note that the particular modification
590: below is intended simply to demonstrate how to manipulate this data, not
591: as a meaningful or appropriate choice.)
592: */
593: for (i=xs; i<xs+xm; i++) {
594: if (!PetscAbsScalar(xa[i])) rdiff = 2*check->tolerance;
595: else rdiff = PetscAbsScalar((xa[i] - xa_last[i])/xa[i]);
596: if (rdiff > check->tolerance) {
597: tmp = xa[i];
598: xa[i] = .5*(xa[i] + xa_last[i]);
599: *changed_x = PETSC_TRUE;
600: PetscPrintf(PETSC_COMM_WORLD," Altering entry %D: x=%g, x_last=%g, diff=%g, x_new=%g\n",i,(double)PetscAbsScalar(tmp),(double)PetscAbsScalar(xa_last[i]),(double)rdiff,(double)PetscAbsScalar(xa[i]));
601: }
602: }
603: DMDAVecRestoreArray(da,check->last_step,&xa_last);
604: DMDAVecRestoreArray(da,x,&xa);
605: }
606: VecCopy(x,check->last_step);
607: return(0);
608: }
610: /* ------------------------------------------------------------------- */
611: /*
612: PostSetSubKSP - Optional user-defined routine that reset SubKSP options when hierarchical bjacobi PC is used
613: e.g,
614: mpiexec -n 8 ./ex3 -nox -n 10000 -ksp_type fgmres -pc_type bjacobi -pc_bjacobi_blocks 4 -sub_ksp_type gmres -sub_ksp_max_it 3 -post_setsubksp -sub_ksp_rtol 1.e-16
615: Set by SNESLineSearchSetPostCheck().
617: Input Parameters:
618: linesearch - the LineSearch context
619: xcurrent - current solution
620: y - search direction and length
621: x - the new candidate iterate
623: Output Parameters:
624: y - proposed step (search direction and length) (possibly changed)
625: x - current iterate (possibly modified)
627: */
628: PetscErrorCode PostSetSubKSP(SNESLineSearch linesearch,Vec xcurrent,Vec y,Vec x,PetscBool *changed_y,PetscBool *changed_x, void * ctx)
629: {
631: SetSubKSPCtx *check;
632: PetscInt iter,its,sub_its,maxit;
633: KSP ksp,sub_ksp,*sub_ksps;
634: PC pc;
635: PetscReal ksp_ratio;
636: SNES snes;
639: SNESLineSearchGetSNES(linesearch, &snes);
640: check = (SetSubKSPCtx*)ctx;
641: SNESGetIterationNumber(snes,&iter);
642: SNESGetKSP(snes,&ksp);
643: KSPGetPC(ksp,&pc);
644: PCBJacobiGetSubKSP(pc,NULL,NULL,&sub_ksps);
645: sub_ksp = sub_ksps[0];
646: KSPGetIterationNumber(ksp,&its); /* outer KSP iteration number */
647: KSPGetIterationNumber(sub_ksp,&sub_its); /* inner KSP iteration number */
649: if (iter) {
650: PetscPrintf(PETSC_COMM_WORLD," ...PostCheck snes iteration %D, ksp_it %d %d, subksp_it %d\n",iter,check->its0,its,sub_its);
651: ksp_ratio = ((PetscReal)(its))/check->its0;
652: maxit = (PetscInt)(ksp_ratio*sub_its + 0.5);
653: if (maxit < 2) maxit = 2;
654: KSPSetTolerances(sub_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,maxit);
655: PetscPrintf(PETSC_COMM_WORLD," ...ksp_ratio %g, new maxit %d\n\n",ksp_ratio,maxit);
656: }
657: check->its0 = its; /* save current outer KSP iteration number */
658: return(0);
659: }
661: /* ------------------------------------------------------------------- */
662: /*
663: MatrixFreePreconditioner - This routine demonstrates the use of a
664: user-provided preconditioner. This code implements just the null
665: preconditioner, which of course is not recommended for general use.
667: Input Parameters:
668: + pc - preconditioner
669: - x - input vector
671: Output Parameter:
672: . y - preconditioned vector
673: */
674: PetscErrorCode MatrixFreePreconditioner(PC pc,Vec x,Vec y)
675: {
677: VecCopy(x,y);
678: return 0;
679: }
682: /*TEST
684: test:
685: args: -nox -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
687: test:
688: suffix: 2
689: nsize: 3
690: args: -nox -pc_type asm -mat_type mpiaij -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
692: test:
693: suffix: 3
694: nsize: 2
695: args: -nox -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
697: test:
698: suffix: 4
699: args: -nox -pre_check_iterates -post_check_iterates
701: test:
702: suffix: 5
703: requires: double !complex !single
704: nsize: 2
705: args: -nox -snes_test_jacobian -snes_test_jacobian_view
707: TEST*/