xref: /petsc/src/snes/tutorials/ex3.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1c4762a1bSJed Brown static char help[] = "Newton methods to solve u'' + u^{2} = f in parallel.\n\
2c4762a1bSJed Brown This example employs a user-defined monitoring routine and optionally a user-defined\n\
3c4762a1bSJed Brown routine to check candidate iterates produced by line search routines.\n\
4c4762a1bSJed Brown The command line options include:\n\
5c4762a1bSJed Brown   -pre_check_iterates : activate checking of iterates\n\
6c4762a1bSJed Brown   -post_check_iterates : activate checking of iterates\n\
7c4762a1bSJed Brown   -check_tol <tol>: set tolerance for iterate checking\n\
8c4762a1bSJed Brown   -user_precond : activate a (trivial) user-defined preconditioner\n\n";
9c4762a1bSJed Brown 
10c4762a1bSJed Brown /*
11c4762a1bSJed Brown    Include "petscdm.h" so that we can use data management objects (DMs)
12c4762a1bSJed Brown    Include "petscdmda.h" so that we can use distributed arrays (DMDAs).
13c4762a1bSJed Brown    Include "petscsnes.h" so that we can use SNES solvers.  Note that this
14c4762a1bSJed Brown    file automatically includes:
15c4762a1bSJed Brown      petscsys.h    - base PETSc routines
16c4762a1bSJed Brown      petscvec.h    - vectors
17c4762a1bSJed Brown      petscmat.h    - matrices
18c4762a1bSJed Brown      petscis.h     - index sets
19c4762a1bSJed Brown      petscksp.h    - Krylov subspace methods
20c4762a1bSJed Brown      petscviewer.h - viewers
21c4762a1bSJed Brown      petscpc.h     - preconditioners
22c4762a1bSJed Brown      petscksp.h    - linear solvers
23c4762a1bSJed Brown */
24c4762a1bSJed Brown 
25c4762a1bSJed Brown #include <petscdm.h>
26c4762a1bSJed Brown #include <petscdmda.h>
27c4762a1bSJed Brown #include <petscsnes.h>
28c4762a1bSJed Brown 
29c4762a1bSJed Brown /*
30c4762a1bSJed Brown    User-defined routines.
31c4762a1bSJed Brown */
32c4762a1bSJed Brown PetscErrorCode FormJacobian(SNES, Vec, Mat, Mat, void *);
33c4762a1bSJed Brown PetscErrorCode FormFunction(SNES, Vec, Vec, void *);
34c4762a1bSJed Brown PetscErrorCode FormInitialGuess(Vec);
35c4762a1bSJed Brown PetscErrorCode Monitor(SNES, PetscInt, PetscReal, void *);
36c4762a1bSJed Brown PetscErrorCode PreCheck(SNESLineSearch, Vec, Vec, PetscBool *, void *);
37c4762a1bSJed Brown PetscErrorCode PostCheck(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
38c4762a1bSJed Brown PetscErrorCode PostSetSubKSP(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
39c4762a1bSJed Brown PetscErrorCode MatrixFreePreconditioner(PC, Vec, Vec);
40c4762a1bSJed Brown 
41c4762a1bSJed Brown /*
42c4762a1bSJed Brown    User-defined application context
43c4762a1bSJed Brown */
44*9371c9d4SSatish Balay typedef struct {
45c4762a1bSJed Brown   DM          da;    /* distributed array */
46c4762a1bSJed Brown   Vec         F;     /* right-hand-side of PDE */
47c4762a1bSJed Brown   PetscMPIInt rank;  /* rank of processor */
48c4762a1bSJed Brown   PetscMPIInt size;  /* size of communicator */
49c4762a1bSJed Brown   PetscReal   h;     /* mesh spacing */
50c4762a1bSJed Brown   PetscBool   sjerr; /* if or not to test jacobian domain error */
51c4762a1bSJed Brown } ApplicationCtx;
52c4762a1bSJed Brown 
53c4762a1bSJed Brown /*
54c4762a1bSJed Brown    User-defined context for monitoring
55c4762a1bSJed Brown */
56*9371c9d4SSatish Balay typedef struct {
57c4762a1bSJed Brown   PetscViewer viewer;
58c4762a1bSJed Brown } MonitorCtx;
59c4762a1bSJed Brown 
60c4762a1bSJed Brown /*
61c4762a1bSJed Brown    User-defined context for checking candidate iterates that are
62c4762a1bSJed Brown    determined by line search methods
63c4762a1bSJed Brown */
64*9371c9d4SSatish Balay typedef struct {
65c4762a1bSJed Brown   Vec             last_step; /* previous iterate */
66c4762a1bSJed Brown   PetscReal       tolerance; /* tolerance for changes between successive iterates */
67c4762a1bSJed Brown   ApplicationCtx *user;
68c4762a1bSJed Brown } StepCheckCtx;
69c4762a1bSJed Brown 
70*9371c9d4SSatish Balay typedef struct {
71c4762a1bSJed Brown   PetscInt its0; /* num of prevous outer KSP iterations */
72c4762a1bSJed Brown } SetSubKSPCtx;
73c4762a1bSJed Brown 
74*9371c9d4SSatish Balay int main(int argc, char **argv) {
75c4762a1bSJed Brown   SNES           snes;       /* SNES context */
76c4762a1bSJed Brown   SNESLineSearch linesearch; /* SNESLineSearch context */
77c4762a1bSJed Brown   Mat            J;          /* Jacobian matrix */
78c4762a1bSJed Brown   ApplicationCtx ctx;        /* user-defined context */
79c4762a1bSJed Brown   Vec            x, r, U, F; /* vectors */
80c4762a1bSJed Brown   MonitorCtx     monP;       /* monitoring context */
81c4762a1bSJed Brown   StepCheckCtx   checkP;     /* step-checking context */
82c4762a1bSJed Brown   SetSubKSPCtx   checkP1;
83c4762a1bSJed Brown   PetscBool      pre_check, post_check, post_setsubksp; /* flag indicating whether we're checking candidate iterates */
84c4762a1bSJed Brown   PetscScalar    xp, *FF, *UU, none = -1.0;
85c4762a1bSJed Brown   PetscInt       its, N = 5, i, maxit, maxf, xs, xm;
86c4762a1bSJed Brown   PetscReal      abstol, rtol, stol, norm;
87c0558f20SBarry Smith   PetscBool      flg, viewinitial = PETSC_FALSE;
88c4762a1bSJed Brown 
89327415f7SBarry Smith   PetscFunctionBeginUser;
909566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &ctx.rank));
929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &ctx.size));
939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-n", &N, NULL));
94c4762a1bSJed Brown   ctx.h     = 1.0 / (N - 1);
95c4762a1bSJed Brown   ctx.sjerr = PETSC_FALSE;
969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_jacobian_domain_error", &ctx.sjerr, NULL));
979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-view_initial", &viewinitial, NULL));
98c4762a1bSJed Brown 
99c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100c4762a1bSJed Brown      Create nonlinear solver context
101c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
102c4762a1bSJed Brown 
1039566063dSJacob Faibussowitsch   PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
104c4762a1bSJed Brown 
105c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
106c4762a1bSJed Brown      Create vector data structures; set function evaluation routine
107c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
108c4762a1bSJed Brown 
109c4762a1bSJed Brown   /*
110c4762a1bSJed Brown      Create distributed array (DMDA) to manage parallel grid and vectors
111c4762a1bSJed Brown   */
1129566063dSJacob Faibussowitsch   PetscCall(DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, N, 1, 1, NULL, &ctx.da));
1139566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(ctx.da));
1149566063dSJacob Faibussowitsch   PetscCall(DMSetUp(ctx.da));
115c4762a1bSJed Brown 
116c4762a1bSJed Brown   /*
117c4762a1bSJed Brown      Extract global and local vectors from DMDA; then duplicate for remaining
118c4762a1bSJed Brown      vectors that are the same types
119c4762a1bSJed Brown   */
1209566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(ctx.da, &x));
1219566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &r));
12211486bccSBarry Smith   PetscCall(VecDuplicate(x, &F));
12311486bccSBarry Smith   ctx.F = F;
1249566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &U));
125c4762a1bSJed Brown 
126c4762a1bSJed Brown   /*
127c4762a1bSJed Brown      Set function evaluation routine and vector.  Whenever the nonlinear
128c4762a1bSJed Brown      solver needs to compute the nonlinear function, it will call this
129c4762a1bSJed Brown      routine.
130c4762a1bSJed Brown       - Note that the final routine argument is the user-defined
131c4762a1bSJed Brown         context that provides application-specific data for the
132c4762a1bSJed Brown         function evaluation routine.
133c4762a1bSJed Brown   */
1349566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, FormFunction, &ctx));
135c4762a1bSJed Brown 
136c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
137c4762a1bSJed Brown      Create matrix data structure; set Jacobian evaluation routine
138c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
139c4762a1bSJed Brown 
1409566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, &J));
1419566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(J, PETSC_DECIDE, PETSC_DECIDE, N, N));
1429566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(J));
1439566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(J, 3, NULL));
1449566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(J, 3, NULL, 3, NULL));
145c4762a1bSJed Brown 
146c4762a1bSJed Brown   /*
147c4762a1bSJed Brown      Set Jacobian matrix data structure and default Jacobian evaluation
148c4762a1bSJed Brown      routine.  Whenever the nonlinear solver needs to compute the
149c4762a1bSJed Brown      Jacobian matrix, it will call this routine.
150c4762a1bSJed Brown       - Note that the final routine argument is the user-defined
151c4762a1bSJed Brown         context that provides application-specific data for the
152c4762a1bSJed Brown         Jacobian evaluation routine.
153c4762a1bSJed Brown   */
1549566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, J, J, FormJacobian, &ctx));
155c4762a1bSJed Brown 
156c4762a1bSJed Brown   /*
157c4762a1bSJed Brown      Optionally allow user-provided preconditioner
158c4762a1bSJed Brown    */
1599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-user_precond", &flg));
160c4762a1bSJed Brown   if (flg) {
161c4762a1bSJed Brown     KSP ksp;
162c4762a1bSJed Brown     PC  pc;
1639566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
1649566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
1659566063dSJacob Faibussowitsch     PetscCall(PCSetType(pc, PCSHELL));
1669566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(pc, MatrixFreePreconditioner));
167c4762a1bSJed Brown   }
168c4762a1bSJed Brown 
169c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
170c4762a1bSJed Brown      Customize nonlinear solver; set runtime options
171c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
172c4762a1bSJed Brown 
173c4762a1bSJed Brown   /*
174c4762a1bSJed Brown      Set an optional user-defined monitoring routine
175c4762a1bSJed Brown   */
1769566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawOpen(PETSC_COMM_WORLD, 0, 0, 0, 0, 400, 400, &monP.viewer));
1779566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSet(snes, Monitor, &monP, 0));
178c4762a1bSJed Brown 
179c4762a1bSJed Brown   /*
180c4762a1bSJed Brown      Set names for some vectors to facilitate monitoring (optional)
181c4762a1bSJed Brown   */
1829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, "Approximate Solution"));
1839566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)U, "Exact Solution"));
184c4762a1bSJed Brown 
185c4762a1bSJed Brown   /*
186c4762a1bSJed Brown      Set SNES/KSP/KSP/PC runtime options, e.g.,
187c4762a1bSJed Brown          -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
188c4762a1bSJed Brown   */
1899566063dSJacob Faibussowitsch   PetscCall(SNESSetFromOptions(snes));
190c4762a1bSJed Brown 
191c4762a1bSJed Brown   /*
192c4762a1bSJed Brown      Set an optional user-defined routine to check the validity of candidate
193c4762a1bSJed Brown      iterates that are determined by line search methods
194c4762a1bSJed Brown   */
1959566063dSJacob Faibussowitsch   PetscCall(SNESGetLineSearch(snes, &linesearch));
1969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-post_check_iterates", &post_check));
197c4762a1bSJed Brown 
198c4762a1bSJed Brown   if (post_check) {
1999566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Activating post step checking routine\n"));
2009566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetPostCheck(linesearch, PostCheck, &checkP));
2019566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &(checkP.last_step)));
202c4762a1bSJed Brown 
203c4762a1bSJed Brown     checkP.tolerance = 1.0;
204c4762a1bSJed Brown     checkP.user      = &ctx;
205c4762a1bSJed Brown 
2069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(NULL, NULL, "-check_tol", &checkP.tolerance, NULL));
207c4762a1bSJed Brown   }
208c4762a1bSJed Brown 
2099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-post_setsubksp", &post_setsubksp));
210c4762a1bSJed Brown   if (post_setsubksp) {
2119566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Activating post setsubksp\n"));
2129566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetPostCheck(linesearch, PostSetSubKSP, &checkP1));
213c4762a1bSJed Brown   }
214c4762a1bSJed Brown 
2159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(NULL, NULL, "-pre_check_iterates", &pre_check));
216c4762a1bSJed Brown   if (pre_check) {
2179566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Activating pre step checking routine\n"));
2189566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetPreCheck(linesearch, PreCheck, &checkP));
219c4762a1bSJed Brown   }
220c4762a1bSJed Brown 
221c4762a1bSJed Brown   /*
222c4762a1bSJed Brown      Print parameters used for convergence testing (optional) ... just
223c4762a1bSJed Brown      to demonstrate this routine; this information is also printed with
224c4762a1bSJed Brown      the option -snes_view
225c4762a1bSJed Brown   */
2269566063dSJacob Faibussowitsch   PetscCall(SNESGetTolerances(snes, &abstol, &rtol, &stol, &maxit, &maxf));
22763a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "atol=%g, rtol=%g, stol=%g, maxit=%" PetscInt_FMT ", maxf=%" PetscInt_FMT "\n", (double)abstol, (double)rtol, (double)stol, maxit, maxf));
228c4762a1bSJed Brown 
229c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
230c4762a1bSJed Brown      Initialize application:
231c4762a1bSJed Brown      Store right-hand-side of PDE and exact solution
232c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
233c4762a1bSJed Brown 
234c4762a1bSJed Brown   /*
235c4762a1bSJed Brown      Get local grid boundaries (for 1-dimensional DMDA):
236c4762a1bSJed Brown        xs, xm - starting grid index, width of local grid (no ghost points)
237c4762a1bSJed Brown   */
2389566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ctx.da, &xs, NULL, NULL, &xm, NULL, NULL));
239c4762a1bSJed Brown 
240c4762a1bSJed Brown   /*
241c4762a1bSJed Brown      Get pointers to vector data
242c4762a1bSJed Brown   */
2439566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(ctx.da, F, &FF));
2449566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(ctx.da, U, &UU));
245c4762a1bSJed Brown 
246c4762a1bSJed Brown   /*
247c4762a1bSJed Brown      Compute local vector entries
248c4762a1bSJed Brown   */
249c4762a1bSJed Brown   xp = ctx.h * xs;
250c4762a1bSJed Brown   for (i = xs; i < xs + xm; i++) {
251c4762a1bSJed Brown     FF[i] = 6.0 * xp + PetscPowScalar(xp + 1.e-12, 6.0); /* +1.e-12 is to prevent 0^6 */
252c4762a1bSJed Brown     UU[i] = xp * xp * xp;
253c4762a1bSJed Brown     xp += ctx.h;
254c4762a1bSJed Brown   }
255c4762a1bSJed Brown 
256c4762a1bSJed Brown   /*
257c4762a1bSJed Brown      Restore vectors
258c4762a1bSJed Brown   */
2599566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(ctx.da, F, &FF));
2609566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(ctx.da, U, &UU));
261c0558f20SBarry Smith   if (viewinitial) {
2629566063dSJacob Faibussowitsch     PetscCall(VecView(U, 0));
2639566063dSJacob Faibussowitsch     PetscCall(VecView(F, 0));
264c0558f20SBarry Smith   }
265c4762a1bSJed Brown 
266c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
267c4762a1bSJed Brown      Evaluate initial guess; then solve nonlinear system
268c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
269c4762a1bSJed Brown 
270c4762a1bSJed Brown   /*
271c4762a1bSJed Brown      Note: The user should initialize the vector, x, with the initial guess
272c4762a1bSJed Brown      for the nonlinear solver prior to calling SNESSolve().  In particular,
273c4762a1bSJed Brown      to employ an initial guess of zero, the user should explicitly set
274c4762a1bSJed Brown      this vector to zero by calling VecSet().
275c4762a1bSJed Brown   */
2769566063dSJacob Faibussowitsch   PetscCall(FormInitialGuess(x));
2779566063dSJacob Faibussowitsch   PetscCall(SNESSolve(snes, NULL, x));
2789566063dSJacob Faibussowitsch   PetscCall(SNESGetIterationNumber(snes, &its));
27963a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Number of SNES iterations = %" PetscInt_FMT "\n", its));
280c4762a1bSJed Brown 
281c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
282c4762a1bSJed Brown      Check solution and clean up
283c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
284c4762a1bSJed Brown 
285c4762a1bSJed Brown   /*
286c4762a1bSJed Brown      Check the error
287c4762a1bSJed Brown   */
2889566063dSJacob Faibussowitsch   PetscCall(VecAXPY(x, none, U));
2899566063dSJacob Faibussowitsch   PetscCall(VecNorm(x, NORM_2, &norm));
29063a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Norm of error %g Iterations %" PetscInt_FMT "\n", (double)norm, its));
291c4762a1bSJed Brown   if (ctx.sjerr) {
292c4762a1bSJed Brown     SNESType snestype;
2939566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &snestype));
2949566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "SNES Type %s\n", snestype));
295c4762a1bSJed Brown   }
296c4762a1bSJed Brown 
297c4762a1bSJed Brown   /*
298c4762a1bSJed Brown      Free work space.  All PETSc objects should be destroyed when they
299c4762a1bSJed Brown      are no longer needed.
300c4762a1bSJed Brown   */
3019566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&monP.viewer));
3029566063dSJacob Faibussowitsch   if (post_check) PetscCall(VecDestroy(&checkP.last_step));
3039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
3049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&r));
3059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&U));
3069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&F));
3079566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
3089566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes));
3099566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&ctx.da));
3109566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
311b122ec5aSJacob Faibussowitsch   return 0;
312c4762a1bSJed Brown }
313c4762a1bSJed Brown 
314c4762a1bSJed Brown /* ------------------------------------------------------------------- */
315c4762a1bSJed Brown /*
316c4762a1bSJed Brown    FormInitialGuess - Computes initial guess.
317c4762a1bSJed Brown 
318c4762a1bSJed Brown    Input/Output Parameter:
319c4762a1bSJed Brown .  x - the solution vector
320c4762a1bSJed Brown */
321*9371c9d4SSatish Balay PetscErrorCode FormInitialGuess(Vec x) {
322c4762a1bSJed Brown   PetscScalar pfive = .50;
323c4762a1bSJed Brown 
324c4762a1bSJed Brown   PetscFunctionBeginUser;
3259566063dSJacob Faibussowitsch   PetscCall(VecSet(x, pfive));
326c4762a1bSJed Brown   PetscFunctionReturn(0);
327c4762a1bSJed Brown }
328c4762a1bSJed Brown 
329c4762a1bSJed Brown /* ------------------------------------------------------------------- */
330c4762a1bSJed Brown /*
331c4762a1bSJed Brown    FormFunction - Evaluates nonlinear function, F(x).
332c4762a1bSJed Brown 
333c4762a1bSJed Brown    Input Parameters:
334c4762a1bSJed Brown .  snes - the SNES context
335c4762a1bSJed Brown .  x - input vector
336c4762a1bSJed Brown .  ctx - optional user-defined context, as set by SNESSetFunction()
337c4762a1bSJed Brown 
338c4762a1bSJed Brown    Output Parameter:
339c4762a1bSJed Brown .  f - function vector
340c4762a1bSJed Brown 
341c4762a1bSJed Brown    Note:
342c4762a1bSJed Brown    The user-defined context can contain any application-specific
343c4762a1bSJed Brown    data needed for the function evaluation.
344c4762a1bSJed Brown */
345*9371c9d4SSatish Balay PetscErrorCode FormFunction(SNES snes, Vec x, Vec f, void *ctx) {
346c4762a1bSJed Brown   ApplicationCtx    *user = (ApplicationCtx *)ctx;
347c4762a1bSJed Brown   DM                 da   = user->da;
34806cf5b03SBarry Smith   PetscScalar       *ff, d;
34906cf5b03SBarry Smith   const PetscScalar *xx, *FF;
350c4762a1bSJed Brown   PetscInt           i, M, xs, xm;
351c4762a1bSJed Brown   Vec                xlocal;
352c4762a1bSJed Brown 
353c4762a1bSJed Brown   PetscFunctionBeginUser;
3549566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(da, &xlocal));
355c4762a1bSJed Brown   /*
356c4762a1bSJed Brown      Scatter ghost points to local vector, using the 2-step process
357c4762a1bSJed Brown         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
358c4762a1bSJed Brown      By placing code between these two statements, computations can
359c4762a1bSJed Brown      be done while messages are in transition.
360c4762a1bSJed Brown   */
3619566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(da, x, INSERT_VALUES, xlocal));
3629566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(da, x, INSERT_VALUES, xlocal));
363c4762a1bSJed Brown 
364c4762a1bSJed Brown   /*
365c4762a1bSJed Brown      Get pointers to vector data.
366c4762a1bSJed Brown        - The vector xlocal includes ghost point; the vectors x and f do
367c4762a1bSJed Brown          NOT include ghost points.
368c4762a1bSJed Brown        - Using DMDAVecGetArray() allows accessing the values using global ordering
369c4762a1bSJed Brown   */
37095b2e421SBarry Smith   PetscCall(DMDAVecGetArrayRead(da, xlocal, (void *)&xx));
3719566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(da, f, &ff));
37295b2e421SBarry Smith   PetscCall(DMDAVecGetArrayRead(da, user->F, (void *)&FF));
373c4762a1bSJed Brown 
374c4762a1bSJed Brown   /*
375c4762a1bSJed Brown      Get local grid boundaries (for 1-dimensional DMDA):
376c4762a1bSJed Brown        xs, xm  - starting grid index, width of local grid (no ghost points)
377c4762a1bSJed Brown   */
3789566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &xm, NULL, NULL));
3799566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, NULL, &M, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL));
380c4762a1bSJed Brown 
381c4762a1bSJed Brown   /*
382c4762a1bSJed Brown      Set function values for boundary points; define local interior grid point range:
383c4762a1bSJed Brown         xsi - starting interior grid index
384c4762a1bSJed Brown         xei - ending interior grid index
385c4762a1bSJed Brown   */
386c4762a1bSJed Brown   if (xs == 0) { /* left boundary */
387c4762a1bSJed Brown     ff[0] = xx[0];
38811486bccSBarry Smith     xs++;
38911486bccSBarry Smith     xm--;
390c4762a1bSJed Brown   }
391c4762a1bSJed Brown   if (xs + xm == M) { /* right boundary */
392c4762a1bSJed Brown     ff[xs + xm - 1] = xx[xs + xm - 1] - 1.0;
393c4762a1bSJed Brown     xm--;
394c4762a1bSJed Brown   }
395c4762a1bSJed Brown 
396c4762a1bSJed Brown   /*
397c4762a1bSJed Brown      Compute function over locally owned part of the grid (interior points only)
398c4762a1bSJed Brown   */
399c4762a1bSJed Brown   d = 1.0 / (user->h * user->h);
400c4762a1bSJed Brown   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];
401c4762a1bSJed Brown 
402c4762a1bSJed Brown   /*
403c4762a1bSJed Brown      Restore vectors
404c4762a1bSJed Brown   */
40595b2e421SBarry Smith   PetscCall(DMDAVecRestoreArrayRead(da, xlocal, (void *)&xx));
4069566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(da, f, &ff));
40795b2e421SBarry Smith   PetscCall(DMDAVecRestoreArrayRead(da, user->F, (void *)&FF));
4089566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(da, &xlocal));
409c4762a1bSJed Brown   PetscFunctionReturn(0);
410c4762a1bSJed Brown }
411c4762a1bSJed Brown 
412c4762a1bSJed Brown /* ------------------------------------------------------------------- */
413c4762a1bSJed Brown /*
414c4762a1bSJed Brown    FormJacobian - Evaluates Jacobian matrix.
415c4762a1bSJed Brown 
416c4762a1bSJed Brown    Input Parameters:
417c4762a1bSJed Brown .  snes - the SNES context
418c4762a1bSJed Brown .  x - input vector
419c4762a1bSJed Brown .  dummy - optional user-defined context (not used here)
420c4762a1bSJed Brown 
421c4762a1bSJed Brown    Output Parameters:
422c4762a1bSJed Brown .  jac - Jacobian matrix
423c4762a1bSJed Brown .  B - optionally different preconditioning matrix
424c4762a1bSJed Brown .  flag - flag indicating matrix structure
425c4762a1bSJed Brown */
426*9371c9d4SSatish Balay PetscErrorCode FormJacobian(SNES snes, Vec x, Mat jac, Mat B, void *ctx) {
427c4762a1bSJed Brown   ApplicationCtx *user = (ApplicationCtx *)ctx;
428c4762a1bSJed Brown   PetscScalar    *xx, d, A[3];
429c4762a1bSJed Brown   PetscInt        i, j[3], M, xs, xm;
430c4762a1bSJed Brown   DM              da = user->da;
431c4762a1bSJed Brown 
432c4762a1bSJed Brown   PetscFunctionBeginUser;
433c4762a1bSJed Brown   if (user->sjerr) {
4349566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobianDomainError(snes));
435c4762a1bSJed Brown     PetscFunctionReturn(0);
436c4762a1bSJed Brown   }
437c4762a1bSJed Brown   /*
438c4762a1bSJed Brown      Get pointer to vector data
439c4762a1bSJed Brown   */
4409566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArrayRead(da, x, &xx));
4419566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &xm, NULL, NULL));
442c4762a1bSJed Brown 
443c4762a1bSJed Brown   /*
444c4762a1bSJed Brown     Get range of locally owned matrix
445c4762a1bSJed Brown   */
4469566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, NULL, &M, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL));
447c4762a1bSJed Brown 
448c4762a1bSJed Brown   /*
449c4762a1bSJed Brown      Determine starting and ending local indices for interior grid points.
450c4762a1bSJed Brown      Set Jacobian entries for boundary points.
451c4762a1bSJed Brown   */
452c4762a1bSJed Brown 
453c4762a1bSJed Brown   if (xs == 0) { /* left boundary */
45411486bccSBarry Smith     i    = 0;
45511486bccSBarry Smith     A[0] = 1.0;
456c4762a1bSJed Brown 
4579566063dSJacob Faibussowitsch     PetscCall(MatSetValues(jac, 1, &i, 1, &i, A, INSERT_VALUES));
45811486bccSBarry Smith     xs++;
45911486bccSBarry Smith     xm--;
460c4762a1bSJed Brown   }
461c4762a1bSJed Brown   if (xs + xm == M) { /* right boundary */
462c4762a1bSJed Brown     i    = M - 1;
463c4762a1bSJed Brown     A[0] = 1.0;
4649566063dSJacob Faibussowitsch     PetscCall(MatSetValues(jac, 1, &i, 1, &i, A, INSERT_VALUES));
465c4762a1bSJed Brown     xm--;
466c4762a1bSJed Brown   }
467c4762a1bSJed Brown 
468c4762a1bSJed Brown   /*
469c4762a1bSJed Brown      Interior grid points
470c4762a1bSJed Brown       - Note that in this case we set all elements for a particular
471c4762a1bSJed Brown         row at once.
472c4762a1bSJed Brown   */
473c4762a1bSJed Brown   d = 1.0 / (user->h * user->h);
474c4762a1bSJed Brown   for (i = xs; i < xs + xm; i++) {
47511486bccSBarry Smith     j[0] = i - 1;
47611486bccSBarry Smith     j[1] = i;
47711486bccSBarry Smith     j[2] = i + 1;
47811486bccSBarry Smith     A[0] = A[2] = d;
47911486bccSBarry Smith     A[1]        = -2.0 * d + 2.0 * xx[i];
4809566063dSJacob Faibussowitsch     PetscCall(MatSetValues(jac, 1, &i, 3, j, A, INSERT_VALUES));
481c4762a1bSJed Brown   }
482c4762a1bSJed Brown 
483c4762a1bSJed Brown   /*
484c4762a1bSJed Brown      Assemble matrix, using the 2-step process:
485c4762a1bSJed Brown        MatAssemblyBegin(), MatAssemblyEnd().
486c4762a1bSJed Brown      By placing code between these two statements, computations can be
487c4762a1bSJed Brown      done while messages are in transition.
488c4762a1bSJed Brown 
489c4762a1bSJed Brown      Also, restore vector.
490c4762a1bSJed Brown   */
491c4762a1bSJed Brown 
4929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY));
4939566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArrayRead(da, x, &xx));
4949566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY));
495c4762a1bSJed Brown 
496c4762a1bSJed Brown   PetscFunctionReturn(0);
497c4762a1bSJed Brown }
498c4762a1bSJed Brown 
499c4762a1bSJed Brown /* ------------------------------------------------------------------- */
500c4762a1bSJed Brown /*
501c4762a1bSJed Brown    Monitor - Optional user-defined monitoring routine that views the
502c4762a1bSJed Brown    current iterate with an x-window plot. Set by SNESMonitorSet().
503c4762a1bSJed Brown 
504c4762a1bSJed Brown    Input Parameters:
505c4762a1bSJed Brown    snes - the SNES context
506c4762a1bSJed Brown    its - iteration number
507c4762a1bSJed Brown    norm - 2-norm function value (may be estimated)
508c4762a1bSJed Brown    ctx - optional user-defined context for private data for the
509c4762a1bSJed Brown          monitor routine, as set by SNESMonitorSet()
510c4762a1bSJed Brown 
511c4762a1bSJed Brown    Note:
512c4762a1bSJed Brown    See the manpage for PetscViewerDrawOpen() for useful runtime options,
513c4762a1bSJed Brown    such as -nox to deactivate all x-window output.
514c4762a1bSJed Brown  */
515*9371c9d4SSatish Balay PetscErrorCode Monitor(SNES snes, PetscInt its, PetscReal fnorm, void *ctx) {
516c4762a1bSJed Brown   MonitorCtx *monP = (MonitorCtx *)ctx;
517c4762a1bSJed Brown   Vec         x;
518c4762a1bSJed Brown 
519c4762a1bSJed Brown   PetscFunctionBeginUser;
52063a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "iter = %" PetscInt_FMT ",SNES Function norm %g\n", its, (double)fnorm));
5219566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &x));
5229566063dSJacob Faibussowitsch   PetscCall(VecView(x, monP->viewer));
523c4762a1bSJed Brown   PetscFunctionReturn(0);
524c4762a1bSJed Brown }
525c4762a1bSJed Brown 
526c4762a1bSJed Brown /* ------------------------------------------------------------------- */
527c4762a1bSJed Brown /*
528c4762a1bSJed Brown    PreCheck - Optional user-defined routine that checks the validity of
529c4762a1bSJed Brown    candidate steps of a line search method.  Set by SNESLineSearchSetPreCheck().
530c4762a1bSJed Brown 
531c4762a1bSJed Brown    Input Parameters:
532c4762a1bSJed Brown    snes - the SNES context
533c4762a1bSJed Brown    xcurrent - current solution
534c4762a1bSJed Brown    y - search direction and length
535c4762a1bSJed Brown 
536c4762a1bSJed Brown    Output Parameters:
537c4762a1bSJed Brown    y         - proposed step (search direction and length) (possibly changed)
538c4762a1bSJed Brown    changed_y - tells if the step has changed or not
539c4762a1bSJed Brown  */
540*9371c9d4SSatish Balay PetscErrorCode PreCheck(SNESLineSearch linesearch, Vec xcurrent, Vec y, PetscBool *changed_y, void *ctx) {
541c4762a1bSJed Brown   PetscFunctionBeginUser;
542c4762a1bSJed Brown   *changed_y = PETSC_FALSE;
543c4762a1bSJed Brown   PetscFunctionReturn(0);
544c4762a1bSJed Brown }
545c4762a1bSJed Brown 
546c4762a1bSJed Brown /* ------------------------------------------------------------------- */
547c4762a1bSJed Brown /*
548c4762a1bSJed Brown    PostCheck - Optional user-defined routine that checks the validity of
549c4762a1bSJed Brown    candidate steps of a line search method.  Set by SNESLineSearchSetPostCheck().
550c4762a1bSJed Brown 
551c4762a1bSJed Brown    Input Parameters:
552c4762a1bSJed Brown    snes - the SNES context
553c4762a1bSJed Brown    ctx  - optional user-defined context for private data for the
554c4762a1bSJed Brown           monitor routine, as set by SNESLineSearchSetPostCheck()
555c4762a1bSJed Brown    xcurrent - current solution
556c4762a1bSJed Brown    y - search direction and length
557c4762a1bSJed Brown    x    - the new candidate iterate
558c4762a1bSJed Brown 
559c4762a1bSJed Brown    Output Parameters:
560c4762a1bSJed Brown    y    - proposed step (search direction and length) (possibly changed)
561c4762a1bSJed Brown    x    - current iterate (possibly modified)
562c4762a1bSJed Brown 
563c4762a1bSJed Brown  */
564*9371c9d4SSatish Balay PetscErrorCode PostCheck(SNESLineSearch linesearch, Vec xcurrent, Vec y, Vec x, PetscBool *changed_y, PetscBool *changed_x, void *ctx) {
565c4762a1bSJed Brown   PetscInt        i, iter, xs, xm;
566c4762a1bSJed Brown   StepCheckCtx   *check;
567c4762a1bSJed Brown   ApplicationCtx *user;
568c4762a1bSJed Brown   PetscScalar    *xa, *xa_last, tmp;
569c4762a1bSJed Brown   PetscReal       rdiff;
570c4762a1bSJed Brown   DM              da;
571c4762a1bSJed Brown   SNES            snes;
572c4762a1bSJed Brown 
573c4762a1bSJed Brown   PetscFunctionBeginUser;
574c4762a1bSJed Brown   *changed_x = PETSC_FALSE;
575c4762a1bSJed Brown   *changed_y = PETSC_FALSE;
576c4762a1bSJed Brown 
5779566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
578c4762a1bSJed Brown   check = (StepCheckCtx *)ctx;
579c4762a1bSJed Brown   user  = check->user;
5809566063dSJacob Faibussowitsch   PetscCall(SNESGetIterationNumber(snes, &iter));
581c4762a1bSJed Brown 
582c4762a1bSJed Brown   /* iteration 1 indicates we are working on the second iteration */
583c4762a1bSJed Brown   if (iter > 0) {
584c4762a1bSJed Brown     da = user->da;
58563a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Checking candidate step at iteration %" PetscInt_FMT " with tolerance %g\n", iter, (double)check->tolerance));
586c4762a1bSJed Brown 
587c4762a1bSJed Brown     /* Access local array data */
5889566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(da, check->last_step, &xa_last));
5899566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(da, x, &xa));
5909566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da, &xs, NULL, NULL, &xm, NULL, NULL));
591c4762a1bSJed Brown 
592c4762a1bSJed Brown     /*
593c4762a1bSJed Brown        If we fail the user-defined check for validity of the candidate iterate,
594c4762a1bSJed Brown        then modify the iterate as we like.  (Note that the particular modification
595c4762a1bSJed Brown        below is intended simply to demonstrate how to manipulate this data, not
596c4762a1bSJed Brown        as a meaningful or appropriate choice.)
597c4762a1bSJed Brown     */
598c4762a1bSJed Brown     for (i = xs; i < xs + xm; i++) {
599c4762a1bSJed Brown       if (!PetscAbsScalar(xa[i])) rdiff = 2 * check->tolerance;
600c4762a1bSJed Brown       else rdiff = PetscAbsScalar((xa[i] - xa_last[i]) / xa[i]);
601c4762a1bSJed Brown       if (rdiff > check->tolerance) {
602c4762a1bSJed Brown         tmp        = xa[i];
603c4762a1bSJed Brown         xa[i]      = .5 * (xa[i] + xa_last[i]);
604c4762a1bSJed Brown         *changed_x = PETSC_TRUE;
60563a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  Altering entry %" PetscInt_FMT ": 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])));
606c4762a1bSJed Brown       }
607c4762a1bSJed Brown     }
6089566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(da, check->last_step, &xa_last));
6099566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(da, x, &xa));
610c4762a1bSJed Brown   }
6119566063dSJacob Faibussowitsch   PetscCall(VecCopy(x, check->last_step));
612c4762a1bSJed Brown   PetscFunctionReturn(0);
613c4762a1bSJed Brown }
614c4762a1bSJed Brown 
615c4762a1bSJed Brown /* ------------------------------------------------------------------- */
616c4762a1bSJed Brown /*
617c4762a1bSJed Brown    PostSetSubKSP - Optional user-defined routine that reset SubKSP options when hierarchical bjacobi PC is used
618c4762a1bSJed Brown    e.g,
619c4762a1bSJed Brown      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
620c4762a1bSJed Brown    Set by SNESLineSearchSetPostCheck().
621c4762a1bSJed Brown 
622c4762a1bSJed Brown    Input Parameters:
623c4762a1bSJed Brown    linesearch - the LineSearch context
624c4762a1bSJed Brown    xcurrent - current solution
625c4762a1bSJed Brown    y - search direction and length
626c4762a1bSJed Brown    x    - the new candidate iterate
627c4762a1bSJed Brown 
628c4762a1bSJed Brown    Output Parameters:
629c4762a1bSJed Brown    y    - proposed step (search direction and length) (possibly changed)
630c4762a1bSJed Brown    x    - current iterate (possibly modified)
631c4762a1bSJed Brown 
632c4762a1bSJed Brown  */
633*9371c9d4SSatish Balay PetscErrorCode PostSetSubKSP(SNESLineSearch linesearch, Vec xcurrent, Vec y, Vec x, PetscBool *changed_y, PetscBool *changed_x, void *ctx) {
634c4762a1bSJed Brown   SetSubKSPCtx *check;
635c4762a1bSJed Brown   PetscInt      iter, its, sub_its, maxit;
636c4762a1bSJed Brown   KSP           ksp, sub_ksp, *sub_ksps;
637c4762a1bSJed Brown   PC            pc;
638c4762a1bSJed Brown   PetscReal     ksp_ratio;
639c4762a1bSJed Brown   SNES          snes;
640c4762a1bSJed Brown 
641c4762a1bSJed Brown   PetscFunctionBeginUser;
6429566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchGetSNES(linesearch, &snes));
643c4762a1bSJed Brown   check = (SetSubKSPCtx *)ctx;
6449566063dSJacob Faibussowitsch   PetscCall(SNESGetIterationNumber(snes, &iter));
6459566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
6469566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(ksp, &pc));
6479566063dSJacob Faibussowitsch   PetscCall(PCBJacobiGetSubKSP(pc, NULL, NULL, &sub_ksps));
648c4762a1bSJed Brown   sub_ksp = sub_ksps[0];
6499566063dSJacob Faibussowitsch   PetscCall(KSPGetIterationNumber(ksp, &its));         /* outer KSP iteration number */
6509566063dSJacob Faibussowitsch   PetscCall(KSPGetIterationNumber(sub_ksp, &sub_its)); /* inner KSP iteration number */
651c4762a1bSJed Brown 
652c4762a1bSJed Brown   if (iter) {
65363a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "    ...PostCheck snes iteration %" PetscInt_FMT ", ksp_it %" PetscInt_FMT " %" PetscInt_FMT ", subksp_it %" PetscInt_FMT "\n", iter, check->its0, its, sub_its));
654c4762a1bSJed Brown     ksp_ratio = ((PetscReal)(its)) / check->its0;
655c4762a1bSJed Brown     maxit     = (PetscInt)(ksp_ratio * sub_its + 0.5);
656c4762a1bSJed Brown     if (maxit < 2) maxit = 2;
6579566063dSJacob Faibussowitsch     PetscCall(KSPSetTolerances(sub_ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, maxit));
65863a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "    ...ksp_ratio %g, new maxit %" PetscInt_FMT "\n\n", (double)ksp_ratio, maxit));
659c4762a1bSJed Brown   }
660c4762a1bSJed Brown   check->its0 = its; /* save current outer KSP iteration number */
661c4762a1bSJed Brown   PetscFunctionReturn(0);
662c4762a1bSJed Brown }
663c4762a1bSJed Brown 
664c4762a1bSJed Brown /* ------------------------------------------------------------------- */
665c4762a1bSJed Brown /*
666c4762a1bSJed Brown    MatrixFreePreconditioner - This routine demonstrates the use of a
667c4762a1bSJed Brown    user-provided preconditioner.  This code implements just the null
668c4762a1bSJed Brown    preconditioner, which of course is not recommended for general use.
669c4762a1bSJed Brown 
670c4762a1bSJed Brown    Input Parameters:
671c4762a1bSJed Brown +  pc - preconditioner
672c4762a1bSJed Brown -  x - input vector
673c4762a1bSJed Brown 
674c4762a1bSJed Brown    Output Parameter:
675c4762a1bSJed Brown .  y - preconditioned vector
676c4762a1bSJed Brown */
677*9371c9d4SSatish Balay PetscErrorCode MatrixFreePreconditioner(PC pc, Vec x, Vec y) {
6789566063dSJacob Faibussowitsch   PetscCall(VecCopy(x, y));
679c4762a1bSJed Brown   return 0;
680c4762a1bSJed Brown }
681c4762a1bSJed Brown 
682c4762a1bSJed Brown /*TEST
683c4762a1bSJed Brown 
684c4762a1bSJed Brown    test:
685c4762a1bSJed Brown       args: -nox -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
686c4762a1bSJed Brown 
687c4762a1bSJed Brown    test:
688c4762a1bSJed Brown       suffix: 2
689c4762a1bSJed Brown       nsize: 3
690c4762a1bSJed Brown       args: -nox -pc_type asm -mat_type mpiaij -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
691c4762a1bSJed Brown 
692c4762a1bSJed Brown    test:
693c4762a1bSJed Brown       suffix: 3
694c4762a1bSJed Brown       nsize: 2
695c4762a1bSJed Brown       args: -nox -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always
696c4762a1bSJed Brown 
697c4762a1bSJed Brown    test:
698c4762a1bSJed Brown       suffix: 4
699c4762a1bSJed Brown       args: -nox -pre_check_iterates -post_check_iterates
700c4762a1bSJed Brown 
701c4762a1bSJed Brown    test:
702c4762a1bSJed Brown       suffix: 5
703c4762a1bSJed Brown       requires: double !complex !single
704c4762a1bSJed Brown       nsize: 2
705c4762a1bSJed Brown       args: -nox -snes_test_jacobian  -snes_test_jacobian_view
706c4762a1bSJed Brown 
707c4762a1bSJed Brown    test:
708c4762a1bSJed Brown       suffix: 6
709c4762a1bSJed Brown       requires: double !complex !single
710c4762a1bSJed Brown       nsize: 4
711c4762a1bSJed Brown       args: -test_jacobian_domain_error -snes_converged_reason -snes_check_jacobian_domain_error 1
712c4762a1bSJed Brown 
713c4762a1bSJed Brown    test:
714c4762a1bSJed Brown       suffix: 7
715c4762a1bSJed Brown       requires: double !complex !single
716c4762a1bSJed Brown       nsize: 4
717c4762a1bSJed Brown       args: -test_jacobian_domain_error -snes_converged_reason -snes_type newtontr -snes_check_jacobian_domain_error 1
718c4762a1bSJed Brown 
719c4762a1bSJed Brown    test:
720c4762a1bSJed Brown       suffix: 8
721c4762a1bSJed Brown       requires: double !complex !single
722c4762a1bSJed Brown       nsize: 4
723c4762a1bSJed Brown       args: -test_jacobian_domain_error -snes_converged_reason -snes_type vinewtonrsls -snes_check_jacobian_domain_error 1
724c4762a1bSJed Brown 
725c4762a1bSJed Brown    test:
726c4762a1bSJed Brown       suffix: 9
727c4762a1bSJed Brown       requires: double !complex !single
728c4762a1bSJed Brown       nsize: 4
729c4762a1bSJed Brown       args: -test_jacobian_domain_error -snes_converged_reason -snes_type vinewtonssls -snes_check_jacobian_domain_error 1
730c4762a1bSJed Brown 
731c4762a1bSJed Brown    test:
732c4762a1bSJed Brown       suffix: 10
733c4762a1bSJed Brown       requires: double !complex !single
734c4762a1bSJed Brown       nsize: 4
735c4762a1bSJed Brown       args: -test_jacobian_domain_error -snes_converged_reason -snes_type qn -snes_qn_scale_type jacobian -snes_check_jacobian_domain_error 1
736c4762a1bSJed Brown 
737c4762a1bSJed Brown    test:
738c4762a1bSJed Brown       suffix: 11
739c4762a1bSJed Brown       requires: double !complex !single
740c4762a1bSJed Brown       nsize: 4
74157715debSLisandro Dalcin       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
742c4762a1bSJed Brown 
743c0558f20SBarry Smith    test:
744c0558f20SBarry Smith       suffix: 12
745c0558f20SBarry Smith       args: -view_initial
746c0558f20SBarry Smith       filter: grep -v "type:"
747c0558f20SBarry Smith 
74841ba4c6cSHeeho Park    test:
74941ba4c6cSHeeho Park       suffix: 13
75041ba4c6cSHeeho Park       requires: double !complex !single
75141ba4c6cSHeeho Park       nsize: 4
75241ba4c6cSHeeho Park       args: -test_jacobian_domain_error -snes_converged_reason -snes_type newtontrdc -snes_check_jacobian_domain_error 1
75341ba4c6cSHeeho Park 
754c4762a1bSJed Brown TEST*/
755