xref: /petsc/src/snes/tutorials/ex3.c (revision ac364067c38fcf400184aa78d587ee09f0c4bff5)
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";
9 
10 /*T
11    Concepts: SNES^basic parallel example
12    Concepts: SNES^setting a user-defined monitoring routine
13    Processors: n
14 T*/
15 
16 
17 
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 */
32 
33 #include <petscdm.h>
34 #include <petscdmda.h>
35 #include <petscsnes.h>
36 
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);
48 
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   PetscBool   sjerr;   /* if or not to test jacobian domain error */
59 } ApplicationCtx;
60 
61 /*
62    User-defined context for monitoring
63 */
64 typedef struct {
65   PetscViewer viewer;
66 } MonitorCtx;
67 
68 /*
69    User-defined context for checking candidate iterates that are
70    determined by line search methods
71 */
72 typedef struct {
73   Vec            last_step;  /* previous iterate */
74   PetscReal      tolerance;  /* tolerance for changes between successive iterates */
75   ApplicationCtx *user;
76 } StepCheckCtx;
77 
78 typedef struct {
79   PetscInt its0; /* num of prevous outer KSP iterations */
80 } SetSubKSPCtx;
81 
82 int main(int argc,char **argv)
83 {
84   SNES           snes;                 /* SNES context */
85   SNESLineSearch linesearch;           /* SNESLineSearch context */
86   Mat            J;                    /* Jacobian matrix */
87   ApplicationCtx ctx;                  /* user-defined context */
88   Vec            x,r,U,F;              /* vectors */
89   MonitorCtx     monP;                 /* monitoring context */
90   StepCheckCtx   checkP;               /* step-checking context */
91   SetSubKSPCtx   checkP1;
92   PetscBool      pre_check,post_check,post_setsubksp; /* flag indicating whether we're checking candidate iterates */
93   PetscScalar    xp,*FF,*UU,none = -1.0;
94   PetscErrorCode ierr;
95   PetscInt       its,N = 5,i,maxit,maxf,xs,xm;
96   PetscReal      abstol,rtol,stol,norm;
97   PetscBool      flg,viewinitial = PETSC_FALSE;
98 
99 
100   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
101   ierr  = MPI_Comm_rank(PETSC_COMM_WORLD,&ctx.rank);CHKERRMPI(ierr);
102   ierr  = MPI_Comm_size(PETSC_COMM_WORLD,&ctx.size);CHKERRMPI(ierr);
103   ierr  = PetscOptionsGetInt(NULL,NULL,"-n",&N,NULL);CHKERRQ(ierr);
104   ctx.h = 1.0/(N-1);
105   ctx.sjerr = PETSC_FALSE;
106   ierr  = PetscOptionsGetBool(NULL,NULL,"-test_jacobian_domain_error",&ctx.sjerr,NULL);CHKERRQ(ierr);
107   ierr  = PetscOptionsGetBool(NULL,NULL,"-view_initial",&viewinitial,NULL);CHKERRQ(ierr);
108 
109   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
110      Create nonlinear solver context
111      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
112 
113   ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr);
114 
115   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116      Create vector data structures; set function evaluation routine
117      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
118 
119   /*
120      Create distributed array (DMDA) to manage parallel grid and vectors
121   */
122   ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,N,1,1,NULL,&ctx.da);CHKERRQ(ierr);
123   ierr = DMSetFromOptions(ctx.da);CHKERRQ(ierr);
124   ierr = DMSetUp(ctx.da);CHKERRQ(ierr);
125 
126   /*
127      Extract global and local vectors from DMDA; then duplicate for remaining
128      vectors that are the same types
129   */
130   ierr = DMCreateGlobalVector(ctx.da,&x);CHKERRQ(ierr);
131   ierr = VecDuplicate(x,&r);CHKERRQ(ierr);
132   ierr = VecDuplicate(x,&F);CHKERRQ(ierr); ctx.F = F;
133   ierr = VecDuplicate(x,&U);CHKERRQ(ierr);
134 
135   /*
136      Set function evaluation routine and vector.  Whenever the nonlinear
137      solver needs to compute the nonlinear function, it will call this
138      routine.
139       - Note that the final routine argument is the user-defined
140         context that provides application-specific data for the
141         function evaluation routine.
142   */
143   ierr = SNESSetFunction(snes,r,FormFunction,&ctx);CHKERRQ(ierr);
144 
145   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
146      Create matrix data structure; set Jacobian evaluation routine
147      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
148 
149   ierr = MatCreate(PETSC_COMM_WORLD,&J);CHKERRQ(ierr);
150   ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,N,N);CHKERRQ(ierr);
151   ierr = MatSetFromOptions(J);CHKERRQ(ierr);
152   ierr = MatSeqAIJSetPreallocation(J,3,NULL);CHKERRQ(ierr);
153   ierr = MatMPIAIJSetPreallocation(J,3,NULL,3,NULL);CHKERRQ(ierr);
154 
155   /*
156      Set Jacobian matrix data structure and default Jacobian evaluation
157      routine.  Whenever the nonlinear solver needs to compute the
158      Jacobian matrix, it will call this routine.
159       - Note that the final routine argument is the user-defined
160         context that provides application-specific data for the
161         Jacobian evaluation routine.
162   */
163   ierr = SNESSetJacobian(snes,J,J,FormJacobian,&ctx);CHKERRQ(ierr);
164 
165   /*
166      Optionally allow user-provided preconditioner
167    */
168   ierr = PetscOptionsHasName(NULL,NULL,"-user_precond",&flg);CHKERRQ(ierr);
169   if (flg) {
170     KSP ksp;
171     PC  pc;
172     ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr);
173     ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
174     ierr = PCSetType(pc,PCSHELL);CHKERRQ(ierr);
175     ierr = PCShellSetApply(pc,MatrixFreePreconditioner);CHKERRQ(ierr);
176   }
177 
178   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
179      Customize nonlinear solver; set runtime options
180    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
181 
182   /*
183      Set an optional user-defined monitoring routine
184   */
185   ierr = PetscViewerDrawOpen(PETSC_COMM_WORLD,0,0,0,0,400,400,&monP.viewer);CHKERRQ(ierr);
186   ierr = SNESMonitorSet(snes,Monitor,&monP,0);CHKERRQ(ierr);
187 
188   /*
189      Set names for some vectors to facilitate monitoring (optional)
190   */
191   ierr = PetscObjectSetName((PetscObject)x,"Approximate Solution");CHKERRQ(ierr);
192   ierr = PetscObjectSetName((PetscObject)U,"Exact Solution");CHKERRQ(ierr);
193 
194   /*
195      Set SNES/KSP/KSP/PC runtime options, e.g.,
196          -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
197   */
198   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
199 
200   /*
201      Set an optional user-defined routine to check the validity of candidate
202      iterates that are determined by line search methods
203   */
204   ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
205   ierr = PetscOptionsHasName(NULL,NULL,"-post_check_iterates",&post_check);CHKERRQ(ierr);
206 
207   if (post_check) {
208     ierr = PetscPrintf(PETSC_COMM_WORLD,"Activating post step checking routine\n");CHKERRQ(ierr);
209     ierr = SNESLineSearchSetPostCheck(linesearch,PostCheck,&checkP);CHKERRQ(ierr);
210     ierr = VecDuplicate(x,&(checkP.last_step));CHKERRQ(ierr);
211 
212     checkP.tolerance = 1.0;
213     checkP.user      = &ctx;
214 
215     ierr = PetscOptionsGetReal(NULL,NULL,"-check_tol",&checkP.tolerance,NULL);CHKERRQ(ierr);
216   }
217 
218   ierr = PetscOptionsHasName(NULL,NULL,"-post_setsubksp",&post_setsubksp);CHKERRQ(ierr);
219   if (post_setsubksp) {
220     ierr = PetscPrintf(PETSC_COMM_WORLD,"Activating post setsubksp\n");CHKERRQ(ierr);
221     ierr = SNESLineSearchSetPostCheck(linesearch,PostSetSubKSP,&checkP1);CHKERRQ(ierr);
222   }
223 
224   ierr = PetscOptionsHasName(NULL,NULL,"-pre_check_iterates",&pre_check);CHKERRQ(ierr);
225   if (pre_check) {
226     ierr = PetscPrintf(PETSC_COMM_WORLD,"Activating pre step checking routine\n");CHKERRQ(ierr);
227     ierr = SNESLineSearchSetPreCheck(linesearch,PreCheck,&checkP);CHKERRQ(ierr);
228   }
229 
230   /*
231      Print parameters used for convergence testing (optional) ... just
232      to demonstrate this routine; this information is also printed with
233      the option -snes_view
234   */
235   ierr = SNESGetTolerances(snes,&abstol,&rtol,&stol,&maxit,&maxf);CHKERRQ(ierr);
236   ierr = PetscPrintf(PETSC_COMM_WORLD,"atol=%g, rtol=%g, stol=%g, maxit=%D, maxf=%D\n",(double)abstol,(double)rtol,(double)stol,maxit,maxf);CHKERRQ(ierr);
237 
238   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
239      Initialize application:
240      Store right-hand-side of PDE and exact solution
241    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
242 
243   /*
244      Get local grid boundaries (for 1-dimensional DMDA):
245        xs, xm - starting grid index, width of local grid (no ghost points)
246   */
247   ierr = DMDAGetCorners(ctx.da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr);
248 
249   /*
250      Get pointers to vector data
251   */
252   ierr = DMDAVecGetArray(ctx.da,F,&FF);CHKERRQ(ierr);
253   ierr = DMDAVecGetArray(ctx.da,U,&UU);CHKERRQ(ierr);
254 
255   /*
256      Compute local vector entries
257   */
258   xp = ctx.h*xs;
259   for (i=xs; i<xs+xm; i++) {
260     FF[i] = 6.0*xp + PetscPowScalar(xp+1.e-12,6.0); /* +1.e-12 is to prevent 0^6 */
261     UU[i] = xp*xp*xp;
262     xp   += ctx.h;
263   }
264 
265   /*
266      Restore vectors
267   */
268   ierr = DMDAVecRestoreArray(ctx.da,F,&FF);CHKERRQ(ierr);
269   ierr = DMDAVecRestoreArray(ctx.da,U,&UU);CHKERRQ(ierr);
270   if (viewinitial) {
271     ierr = VecView(U,0);CHKERRQ(ierr);
272     ierr = VecView(F,0);CHKERRQ(ierr);
273   }
274 
275   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
276      Evaluate initial guess; then solve nonlinear system
277    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
278 
279   /*
280      Note: The user should initialize the vector, x, with the initial guess
281      for the nonlinear solver prior to calling SNESSolve().  In particular,
282      to employ an initial guess of zero, the user should explicitly set
283      this vector to zero by calling VecSet().
284   */
285   ierr = FormInitialGuess(x);CHKERRQ(ierr);
286   ierr = SNESSolve(snes,NULL,x);CHKERRQ(ierr);
287   ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
288   ierr = PetscPrintf(PETSC_COMM_WORLD,"Number of SNES iterations = %D\n",its);CHKERRQ(ierr);
289 
290   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
291      Check solution and clean up
292    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
293 
294   /*
295      Check the error
296   */
297   ierr = VecAXPY(x,none,U);CHKERRQ(ierr);
298   ierr = VecNorm(x,NORM_2,&norm);CHKERRQ(ierr);
299   ierr = PetscPrintf(PETSC_COMM_WORLD,"Norm of error %g Iterations %D\n",(double)norm,its);CHKERRQ(ierr);
300   if (ctx.sjerr) {
301     SNESType       snestype;
302     ierr = SNESGetType(snes,&snestype);CHKERRQ(ierr);
303     ierr = PetscPrintf(PETSC_COMM_WORLD,"SNES Type %s\n",snestype);CHKERRQ(ierr);
304   }
305 
306   /*
307      Free work space.  All PETSc objects should be destroyed when they
308      are no longer needed.
309   */
310   ierr = PetscViewerDestroy(&monP.viewer);CHKERRQ(ierr);
311   if (post_check) {ierr = VecDestroy(&checkP.last_step);CHKERRQ(ierr);}
312   ierr = VecDestroy(&x);CHKERRQ(ierr);
313   ierr = VecDestroy(&r);CHKERRQ(ierr);
314   ierr = VecDestroy(&U);CHKERRQ(ierr);
315   ierr = VecDestroy(&F);CHKERRQ(ierr);
316   ierr = MatDestroy(&J);CHKERRQ(ierr);
317   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
318   ierr = DMDestroy(&ctx.da);CHKERRQ(ierr);
319   ierr = PetscFinalize();
320   return ierr;
321 }
322 
323 /* ------------------------------------------------------------------- */
324 /*
325    FormInitialGuess - Computes initial guess.
326 
327    Input/Output Parameter:
328 .  x - the solution vector
329 */
330 PetscErrorCode FormInitialGuess(Vec x)
331 {
332   PetscErrorCode ierr;
333   PetscScalar    pfive = .50;
334 
335   PetscFunctionBeginUser;
336   ierr = VecSet(x,pfive);CHKERRQ(ierr);
337   PetscFunctionReturn(0);
338 }
339 
340 /* ------------------------------------------------------------------- */
341 /*
342    FormFunction - Evaluates nonlinear function, F(x).
343 
344    Input Parameters:
345 .  snes - the SNES context
346 .  x - input vector
347 .  ctx - optional user-defined context, as set by SNESSetFunction()
348 
349    Output Parameter:
350 .  f - function vector
351 
352    Note:
353    The user-defined context can contain any application-specific
354    data needed for the function evaluation.
355 */
356 PetscErrorCode FormFunction(SNES snes,Vec x,Vec f,void *ctx)
357 {
358   ApplicationCtx *user = (ApplicationCtx*) ctx;
359   DM             da    = user->da;
360   PetscScalar    *xx,*ff,*FF,d;
361   PetscErrorCode ierr;
362   PetscInt       i,M,xs,xm;
363   Vec            xlocal;
364 
365   PetscFunctionBeginUser;
366   ierr = DMGetLocalVector(da,&xlocal);CHKERRQ(ierr);
367   /*
368      Scatter ghost points to local vector, using the 2-step process
369         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
370      By placing code between these two statements, computations can
371      be done while messages are in transition.
372   */
373   ierr = DMGlobalToLocalBegin(da,x,INSERT_VALUES,xlocal);CHKERRQ(ierr);
374   ierr = DMGlobalToLocalEnd(da,x,INSERT_VALUES,xlocal);CHKERRQ(ierr);
375 
376   /*
377      Get pointers to vector data.
378        - The vector xlocal includes ghost point; the vectors x and f do
379          NOT include ghost points.
380        - Using DMDAVecGetArray() allows accessing the values using global ordering
381   */
382   ierr = DMDAVecGetArray(da,xlocal,&xx);CHKERRQ(ierr);
383   ierr = DMDAVecGetArray(da,f,&ff);CHKERRQ(ierr);
384   ierr = DMDAVecGetArray(da,user->F,&FF);CHKERRQ(ierr);
385 
386   /*
387      Get local grid boundaries (for 1-dimensional DMDA):
388        xs, xm  - starting grid index, width of local grid (no ghost points)
389   */
390   ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr);
391   ierr = DMDAGetInfo(da,NULL,&M,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
392 
393   /*
394      Set function values for boundary points; define local interior grid point range:
395         xsi - starting interior grid index
396         xei - ending interior grid index
397   */
398   if (xs == 0) { /* left boundary */
399     ff[0] = xx[0];
400     xs++;xm--;
401   }
402   if (xs+xm == M) {  /* right boundary */
403     ff[xs+xm-1] = xx[xs+xm-1] - 1.0;
404     xm--;
405   }
406 
407   /*
408      Compute function over locally owned part of the grid (interior points only)
409   */
410   d = 1.0/(user->h*user->h);
411   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];
412 
413   /*
414      Restore vectors
415   */
416   ierr = DMDAVecRestoreArray(da,xlocal,&xx);CHKERRQ(ierr);
417   ierr = DMDAVecRestoreArray(da,f,&ff);CHKERRQ(ierr);
418   ierr = DMDAVecRestoreArray(da,user->F,&FF);CHKERRQ(ierr);
419   ierr = DMRestoreLocalVector(da,&xlocal);CHKERRQ(ierr);
420   PetscFunctionReturn(0);
421 }
422 
423 /* ------------------------------------------------------------------- */
424 /*
425    FormJacobian - Evaluates Jacobian matrix.
426 
427    Input Parameters:
428 .  snes - the SNES context
429 .  x - input vector
430 .  dummy - optional user-defined context (not used here)
431 
432    Output Parameters:
433 .  jac - Jacobian matrix
434 .  B - optionally different preconditioning matrix
435 .  flag - flag indicating matrix structure
436 */
437 PetscErrorCode FormJacobian(SNES snes,Vec x,Mat jac,Mat B,void *ctx)
438 {
439   ApplicationCtx *user = (ApplicationCtx*) ctx;
440   PetscScalar    *xx,d,A[3];
441   PetscErrorCode ierr;
442   PetscInt       i,j[3],M,xs,xm;
443   DM             da = user->da;
444 
445   PetscFunctionBeginUser;
446   if (user->sjerr) {
447     ierr = SNESSetJacobianDomainError(snes);CHKERRQ(ierr);
448     PetscFunctionReturn(0);
449   }
450   /*
451      Get pointer to vector data
452   */
453   ierr = DMDAVecGetArrayRead(da,x,&xx);CHKERRQ(ierr);
454   ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr);
455 
456   /*
457     Get range of locally owned matrix
458   */
459   ierr = DMDAGetInfo(da,NULL,&M,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
460 
461   /*
462      Determine starting and ending local indices for interior grid points.
463      Set Jacobian entries for boundary points.
464   */
465 
466   if (xs == 0) {  /* left boundary */
467     i = 0; A[0] = 1.0;
468 
469     ierr = MatSetValues(jac,1,&i,1,&i,A,INSERT_VALUES);CHKERRQ(ierr);
470     xs++;xm--;
471   }
472   if (xs+xm == M) { /* right boundary */
473     i    = M-1;
474     A[0] = 1.0;
475     ierr = MatSetValues(jac,1,&i,1,&i,A,INSERT_VALUES);CHKERRQ(ierr);
476     xm--;
477   }
478 
479   /*
480      Interior grid points
481       - Note that in this case we set all elements for a particular
482         row at once.
483   */
484   d = 1.0/(user->h*user->h);
485   for (i=xs; i<xs+xm; i++) {
486     j[0] = i - 1; j[1] = i; j[2] = i + 1;
487     A[0] = A[2] = d; A[1] = -2.0*d + 2.0*xx[i];
488     ierr = MatSetValues(jac,1,&i,3,j,A,INSERT_VALUES);CHKERRQ(ierr);
489   }
490 
491   /*
492      Assemble matrix, using the 2-step process:
493        MatAssemblyBegin(), MatAssemblyEnd().
494      By placing code between these two statements, computations can be
495      done while messages are in transition.
496 
497      Also, restore vector.
498   */
499 
500   ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
501   ierr = DMDAVecRestoreArrayRead(da,x,&xx);CHKERRQ(ierr);
502   ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
503 
504   PetscFunctionReturn(0);
505 }
506 
507 /* ------------------------------------------------------------------- */
508 /*
509    Monitor - Optional user-defined monitoring routine that views the
510    current iterate with an x-window plot. Set by SNESMonitorSet().
511 
512    Input Parameters:
513    snes - the SNES context
514    its - iteration number
515    norm - 2-norm function value (may be estimated)
516    ctx - optional user-defined context for private data for the
517          monitor routine, as set by SNESMonitorSet()
518 
519    Note:
520    See the manpage for PetscViewerDrawOpen() for useful runtime options,
521    such as -nox to deactivate all x-window output.
522  */
523 PetscErrorCode Monitor(SNES snes,PetscInt its,PetscReal fnorm,void *ctx)
524 {
525   PetscErrorCode ierr;
526   MonitorCtx     *monP = (MonitorCtx*) ctx;
527   Vec            x;
528 
529   PetscFunctionBeginUser;
530   ierr = PetscPrintf(PETSC_COMM_WORLD,"iter = %D,SNES Function norm %g\n",its,(double)fnorm);CHKERRQ(ierr);
531   ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr);
532   ierr = VecView(x,monP->viewer);CHKERRQ(ierr);
533   PetscFunctionReturn(0);
534 }
535 
536 /* ------------------------------------------------------------------- */
537 /*
538    PreCheck - Optional user-defined routine that checks the validity of
539    candidate steps of a line search method.  Set by SNESLineSearchSetPreCheck().
540 
541    Input Parameters:
542    snes - the SNES context
543    xcurrent - current solution
544    y - search direction and length
545 
546    Output Parameters:
547    y         - proposed step (search direction and length) (possibly changed)
548    changed_y - tells if the step has changed or not
549  */
550 PetscErrorCode PreCheck(SNESLineSearch linesearch,Vec xcurrent,Vec y, PetscBool *changed_y, void * ctx)
551 {
552   PetscFunctionBeginUser;
553   *changed_y = PETSC_FALSE;
554   PetscFunctionReturn(0);
555 }
556 
557 /* ------------------------------------------------------------------- */
558 /*
559    PostCheck - Optional user-defined routine that checks the validity of
560    candidate steps of a line search method.  Set by SNESLineSearchSetPostCheck().
561 
562    Input Parameters:
563    snes - the SNES context
564    ctx  - optional user-defined context for private data for the
565           monitor routine, as set by SNESLineSearchSetPostCheck()
566    xcurrent - current solution
567    y - search direction and length
568    x    - the new candidate iterate
569 
570    Output Parameters:
571    y    - proposed step (search direction and length) (possibly changed)
572    x    - current iterate (possibly modified)
573 
574  */
575 PetscErrorCode PostCheck(SNESLineSearch linesearch,Vec xcurrent,Vec y,Vec x,PetscBool  *changed_y,PetscBool  *changed_x, void * ctx)
576 {
577   PetscErrorCode ierr;
578   PetscInt       i,iter,xs,xm;
579   StepCheckCtx   *check;
580   ApplicationCtx *user;
581   PetscScalar    *xa,*xa_last,tmp;
582   PetscReal      rdiff;
583   DM             da;
584   SNES           snes;
585 
586   PetscFunctionBeginUser;
587   *changed_x = PETSC_FALSE;
588   *changed_y = PETSC_FALSE;
589 
590   ierr  = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr);
591   check = (StepCheckCtx*)ctx;
592   user  = check->user;
593   ierr  = SNESGetIterationNumber(snes,&iter);CHKERRQ(ierr);
594 
595   /* iteration 1 indicates we are working on the second iteration */
596   if (iter > 0) {
597     da   = user->da;
598     ierr = PetscPrintf(PETSC_COMM_WORLD,"Checking candidate step at iteration %D with tolerance %g\n",iter,(double)check->tolerance);CHKERRQ(ierr);
599 
600     /* Access local array data */
601     ierr = DMDAVecGetArray(da,check->last_step,&xa_last);CHKERRQ(ierr);
602     ierr = DMDAVecGetArray(da,x,&xa);CHKERRQ(ierr);
603     ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr);
604 
605     /*
606        If we fail the user-defined check for validity of the candidate iterate,
607        then modify the iterate as we like.  (Note that the particular modification
608        below is intended simply to demonstrate how to manipulate this data, not
609        as a meaningful or appropriate choice.)
610     */
611     for (i=xs; i<xs+xm; i++) {
612       if (!PetscAbsScalar(xa[i])) rdiff = 2*check->tolerance;
613       else rdiff = PetscAbsScalar((xa[i] - xa_last[i])/xa[i]);
614       if (rdiff > check->tolerance) {
615         tmp        = xa[i];
616         xa[i]      = .5*(xa[i] + xa_last[i]);
617         *changed_x = PETSC_TRUE;
618         ierr       = 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]));CHKERRQ(ierr);
619       }
620     }
621     ierr = DMDAVecRestoreArray(da,check->last_step,&xa_last);CHKERRQ(ierr);
622     ierr = DMDAVecRestoreArray(da,x,&xa);CHKERRQ(ierr);
623   }
624   ierr = VecCopy(x,check->last_step);CHKERRQ(ierr);
625   PetscFunctionReturn(0);
626 }
627 
628 /* ------------------------------------------------------------------- */
629 /*
630    PostSetSubKSP - Optional user-defined routine that reset SubKSP options when hierarchical bjacobi PC is used
631    e.g,
632      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
633    Set by SNESLineSearchSetPostCheck().
634 
635    Input Parameters:
636    linesearch - the LineSearch context
637    xcurrent - current solution
638    y - search direction and length
639    x    - the new candidate iterate
640 
641    Output Parameters:
642    y    - proposed step (search direction and length) (possibly changed)
643    x    - current iterate (possibly modified)
644 
645  */
646 PetscErrorCode PostSetSubKSP(SNESLineSearch linesearch,Vec xcurrent,Vec y,Vec x,PetscBool  *changed_y,PetscBool  *changed_x, void * ctx)
647 {
648   PetscErrorCode ierr;
649   SetSubKSPCtx   *check;
650   PetscInt       iter,its,sub_its,maxit;
651   KSP            ksp,sub_ksp,*sub_ksps;
652   PC             pc;
653   PetscReal      ksp_ratio;
654   SNES           snes;
655 
656   PetscFunctionBeginUser;
657   ierr    = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr);
658   check   = (SetSubKSPCtx*)ctx;
659   ierr    = SNESGetIterationNumber(snes,&iter);CHKERRQ(ierr);
660   ierr    = SNESGetKSP(snes,&ksp);CHKERRQ(ierr);
661   ierr    = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
662   ierr    = PCBJacobiGetSubKSP(pc,NULL,NULL,&sub_ksps);CHKERRQ(ierr);
663   sub_ksp = sub_ksps[0];
664   ierr    = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr);      /* outer KSP iteration number */
665   ierr    = KSPGetIterationNumber(sub_ksp,&sub_its);CHKERRQ(ierr); /* inner KSP iteration number */
666 
667   if (iter) {
668     ierr      = PetscPrintf(PETSC_COMM_WORLD,"    ...PostCheck snes iteration %D, ksp_it %D %D, subksp_it %D\n",iter,check->its0,its,sub_its);CHKERRQ(ierr);
669     ksp_ratio = ((PetscReal)(its))/check->its0;
670     maxit     = (PetscInt)(ksp_ratio*sub_its + 0.5);
671     if (maxit < 2) maxit = 2;
672     ierr = KSPSetTolerances(sub_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,maxit);CHKERRQ(ierr);
673     ierr = PetscPrintf(PETSC_COMM_WORLD,"    ...ksp_ratio %g, new maxit %D\n\n",(double)ksp_ratio,maxit);CHKERRQ(ierr);
674   }
675   check->its0 = its; /* save current outer KSP iteration number */
676   PetscFunctionReturn(0);
677 }
678 
679 /* ------------------------------------------------------------------- */
680 /*
681    MatrixFreePreconditioner - This routine demonstrates the use of a
682    user-provided preconditioner.  This code implements just the null
683    preconditioner, which of course is not recommended for general use.
684 
685    Input Parameters:
686 +  pc - preconditioner
687 -  x - input vector
688 
689    Output Parameter:
690 .  y - preconditioned vector
691 */
692 PetscErrorCode MatrixFreePreconditioner(PC pc,Vec x,Vec y)
693 {
694   PetscErrorCode ierr;
695   ierr = VecCopy(x,y);CHKERRQ(ierr);
696   return 0;
697 }
698 
699 
700 /*TEST
701 
702    test:
703       args: -nox -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
704 
705    test:
706       suffix: 2
707       nsize: 3
708       args: -nox -pc_type asm -mat_type mpiaij -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
709 
710    test:
711       suffix: 3
712       nsize: 2
713       args: -nox -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
714 
715    test:
716       suffix: 4
717       args: -nox -pre_check_iterates -post_check_iterates
718 
719    test:
720       suffix: 5
721       requires: double !complex !single
722       nsize: 2
723       args: -nox -snes_test_jacobian  -snes_test_jacobian_view
724 
725    test:
726       suffix: 6
727       requires: double !complex !single
728       nsize: 4
729       args: -test_jacobian_domain_error -snes_converged_reason -snes_check_jacobian_domain_error 1
730 
731    test:
732       suffix: 7
733       requires: double !complex !single
734       nsize: 4
735       args: -test_jacobian_domain_error -snes_converged_reason -snes_type newtontr -snes_check_jacobian_domain_error 1
736 
737    test:
738       suffix: 8
739       requires: double !complex !single
740       nsize: 4
741       args: -test_jacobian_domain_error -snes_converged_reason -snes_type vinewtonrsls -snes_check_jacobian_domain_error 1
742 
743    test:
744       suffix: 9
745       requires: double !complex !single
746       nsize: 4
747       args: -test_jacobian_domain_error -snes_converged_reason -snes_type vinewtonssls -snes_check_jacobian_domain_error 1
748 
749    test:
750       suffix: 10
751       requires: double !complex !single
752       nsize: 4
753       args: -test_jacobian_domain_error -snes_converged_reason -snes_type qn -snes_qn_scale_type jacobian -snes_check_jacobian_domain_error 1
754 
755    test:
756       suffix: 11
757       requires: double !complex !single
758       nsize: 4
759       args: -test_jacobian_domain_error -snes_converged_reason -snes_type ms -snes_ms_type m62 -snes_ms_damping 0.9 -snes_check_jacobian_domain_error 1
760 
761    test:
762       suffix: 12
763       args: -view_initial
764       filter: grep -v "type:"
765 
766 TEST*/
767