Actual source code: ex1.c
1: static char help[] = "Solves the nonlinear system, the Bratu (SFI - solid fuel ignition) problem in a 2D rectangular domain.\n\
2: This example also illustrates the use of matrix coloring. Runtime options include:\n\
3: -par <parameter>, where <parameter> indicates the problem's nonlinearity\n\
4: problem SFI: <parameter> = Bratu parameter (0 <= par <= 6.81)\n\
5: -mx <xg>, where <xg> = number of grid points in the x-direction\n\
6: -my <yg>, where <yg> = number of grid points in the y-direction\n\n";
8: /*
10: Solid Fuel Ignition (SFI) problem. This problem is modeled by
11: the partial differential equation
13: -Laplacian u - lambda*exp(u) = 0, 0 < x,y < 1,
15: with boundary conditions
17: u = 0 for x = 0, x = 1, y = 0, y = 1.
19: A finite difference approximation with the usual 5-point stencil
20: is used to discretize the boundary value problem to obtain a nonlinear
21: system of equations.
23: The parallel version of this code is snes/tutorials/ex5.c
25: */
27: /*
28: Include "petscsnes.h" so that we can use SNES solvers. Note that
29: this file automatically includes:
30: petscsys.h - base PETSc routines petscvec.h - vectors
31: petscmat.h - matrices
32: petscis.h - index sets petscksp.h - Krylov subspace methods
33: petscviewer.h - viewers petscpc.h - preconditioners
34: petscksp.h - linear solvers
35: */
37: #include <petscsnes.h>
39: /*
40: User-defined application context - contains data needed by the
41: application-provided call-back routines, FormJacobian() and
42: FormFunction().
43: */
44: typedef struct {
45: PetscReal param; /* test problem parameter */
46: PetscInt mx; /* Discretization in x-direction */
47: PetscInt my; /* Discretization in y-direction */
48: } AppCtx;
50: /*
51: User-defined routines
52: */
53: extern PetscErrorCode FormJacobian(SNES, Vec, Mat, Mat, void *);
54: extern PetscErrorCode FormFunction(SNES, Vec, Vec, void *);
55: extern PetscErrorCode FormInitialGuess(AppCtx *, Vec);
56: extern PetscErrorCode ConvergenceTest(KSP, PetscInt, PetscReal, KSPConvergedReason *, void *);
57: extern PetscErrorCode ConvergenceDestroy(void *);
58: extern PetscErrorCode postcheck(SNES, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
60: int main(int argc, char **argv)
61: {
62: SNES snes; /* nonlinear solver context */
63: Vec x, r; /* solution, residual vectors */
64: Mat J; /* Jacobian matrix */
65: AppCtx user; /* user-defined application context */
66: PetscInt i, its, N, hist_its[50];
67: PetscMPIInt size;
68: PetscReal bratu_lambda_max = 6.81, bratu_lambda_min = 0., history[50];
69: MatFDColoring fdcoloring;
70: PetscBool matrix_free = PETSC_FALSE, flg, fd_coloring = PETSC_FALSE, use_convergence_test = PETSC_FALSE, pc = PETSC_FALSE, prunejacobian = PETSC_FALSE, null_appctx = PETSC_TRUE;
71: KSP ksp;
72: PetscInt *testarray;
74: PetscFunctionBeginUser;
75: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
76: PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
77: PetscCheck(size == 1, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "This is a uniprocessor example only!");
79: /*
80: Initialize problem parameters
81: */
82: user.mx = 4;
83: user.my = 4;
84: user.param = 6.0;
85: PetscCall(PetscOptionsGetInt(NULL, NULL, "-mx", &user.mx, NULL));
86: PetscCall(PetscOptionsGetInt(NULL, NULL, "-my", &user.my, NULL));
87: PetscCall(PetscOptionsGetReal(NULL, NULL, "-par", &user.param, NULL));
88: PetscCall(PetscOptionsGetBool(NULL, NULL, "-pc", &pc, NULL));
89: PetscCheck(user.param < bratu_lambda_max && user.param > bratu_lambda_min, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lambda is out of range");
90: N = user.mx * user.my;
91: PetscCall(PetscOptionsGetBool(NULL, NULL, "-use_convergence_test", &use_convergence_test, NULL));
92: PetscCall(PetscOptionsGetBool(NULL, NULL, "-prune_jacobian", &prunejacobian, NULL));
93: PetscCall(PetscOptionsGetBool(NULL, NULL, "-null_appctx", &null_appctx, NULL));
95: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96: Create nonlinear solver context
97: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
99: PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
101: if (pc) {
102: PetscCall(SNESSetType(snes, SNESNEWTONTR));
103: PetscCall(SNESNewtonTRSetPostCheck(snes, postcheck, NULL));
104: }
106: /* Test application context handling from Python */
107: if (!null_appctx) { PetscCall(SNESSetApplicationContext(snes, (void *)&user)); }
109: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
110: Create vector data structures; set function evaluation routine
111: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
113: PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
114: PetscCall(VecSetSizes(x, PETSC_DECIDE, N));
115: PetscCall(VecSetFromOptions(x));
116: PetscCall(VecDuplicate(x, &r));
118: /*
119: Set function evaluation routine and vector. Whenever the nonlinear
120: solver needs to evaluate the nonlinear function, it will call this
121: routine.
122: - Note that the final routine argument is the user-defined
123: context that provides application-specific data for the
124: function evaluation routine.
125: */
126: PetscCall(SNESSetFunction(snes, r, FormFunction, (void *)&user));
128: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
129: Create matrix data structure; set Jacobian evaluation routine
130: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
132: /*
133: Create matrix. Here we only approximately preallocate storage space
134: for the Jacobian. See the users manual for a discussion of better
135: techniques for preallocating matrix memory.
136: */
137: PetscCall(PetscOptionsGetBool(NULL, NULL, "-snes_mf", &matrix_free, NULL));
138: if (!matrix_free) {
139: PetscBool matrix_free_operator = PETSC_FALSE;
140: PetscCall(PetscOptionsGetBool(NULL, NULL, "-snes_mf_operator", &matrix_free_operator, NULL));
141: if (matrix_free_operator) matrix_free = PETSC_FALSE;
142: }
143: if (!matrix_free) PetscCall(MatCreateSeqAIJ(PETSC_COMM_WORLD, N, N, 5, NULL, &J));
145: /*
146: This option will cause the Jacobian to be computed via finite differences
147: efficiently using a coloring of the columns of the matrix.
148: */
149: PetscCall(PetscOptionsGetBool(NULL, NULL, "-snes_fd_coloring", &fd_coloring, NULL));
150: PetscCheck(!matrix_free || !fd_coloring, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Use only one of -snes_mf, -snes_fd_coloring options! You can do -snes_mf_operator -snes_fd_coloring");
152: if (fd_coloring) {
153: ISColoring iscoloring;
154: MatColoring mc;
155: if (prunejacobian) {
156: /* Initialize x with random nonzero values so that the nonzeros in the Jacobian
157: can better reflect the sparsity structure of the Jacobian. */
158: PetscRandom rctx;
159: PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rctx));
160: PetscCall(PetscRandomSetInterval(rctx, 1.0, 2.0));
161: PetscCall(VecSetRandom(x, rctx));
162: PetscCall(PetscRandomDestroy(&rctx));
163: }
165: /*
166: This initializes the nonzero structure of the Jacobian. This is artificial
167: because clearly if we had a routine to compute the Jacobian we won't need
168: to use finite differences.
169: */
170: PetscCall(FormJacobian(snes, x, J, J, &user));
172: /*
173: Color the matrix, i.e. determine groups of columns that share no common
174: rows. These columns in the Jacobian can all be computed simultaneously.
175: */
176: PetscCall(MatColoringCreate(J, &mc));
177: PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
178: PetscCall(MatColoringSetFromOptions(mc));
179: PetscCall(MatColoringApply(mc, &iscoloring));
180: PetscCall(MatColoringDestroy(&mc));
181: /*
182: Create the data structure that SNESComputeJacobianDefaultColor() uses
183: to compute the actual Jacobians via finite differences.
184: */
185: PetscCall(MatFDColoringCreate(J, iscoloring, &fdcoloring));
186: PetscCall(MatFDColoringSetFunction(fdcoloring, (PetscErrorCode (*)(void))FormFunction, &user));
187: PetscCall(MatFDColoringSetFromOptions(fdcoloring));
188: PetscCall(MatFDColoringSetUp(J, iscoloring, fdcoloring));
189: /*
190: Tell SNES to use the routine SNESComputeJacobianDefaultColor()
191: to compute Jacobians.
192: */
193: PetscCall(SNESSetJacobian(snes, J, J, SNESComputeJacobianDefaultColor, fdcoloring));
194: PetscCall(ISColoringDestroy(&iscoloring));
195: if (prunejacobian) PetscCall(SNESPruneJacobianColor(snes, J, J));
196: }
197: /*
198: Set Jacobian matrix data structure and default Jacobian evaluation
199: routine. Whenever the nonlinear solver needs to compute the
200: Jacobian matrix, it will call this routine.
201: - Note that the final routine argument is the user-defined
202: context that provides application-specific data for the
203: Jacobian evaluation routine.
204: - The user can override with:
205: -snes_fd : default finite differencing approximation of Jacobian
206: -snes_mf : matrix-free Newton-Krylov method with no preconditioning
207: (unless user explicitly sets preconditioner)
208: -snes_mf_operator : form preconditioning matrix as set by the user,
209: but use matrix-free approx for Jacobian-vector
210: products within Newton-Krylov method
211: */
212: else if (!matrix_free) {
213: PetscCall(SNESSetJacobian(snes, J, J, FormJacobian, (void *)&user));
214: }
216: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
217: Customize nonlinear solver; set runtime options
218: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
220: /*
221: Set runtime options (e.g., -snes_monitor -snes_rtol <rtol> -ksp_type <type>)
222: */
223: PetscCall(SNESSetFromOptions(snes));
225: /*
226: Set array that saves the function norms. This array is intended
227: when the user wants to save the convergence history for later use
228: rather than just to view the function norms via -snes_monitor.
229: */
230: PetscCall(SNESSetConvergenceHistory(snes, history, hist_its, 50, PETSC_TRUE));
232: /*
233: Add a user provided convergence test; this is to test that SNESNEWTONTR properly calls the
234: user provided test before the specialized test. The convergence context is just an array to
235: test that it gets properly freed at the end
236: */
237: if (use_convergence_test) {
238: PetscCall(SNESGetKSP(snes, &ksp));
239: PetscCall(PetscMalloc1(5, &testarray));
240: PetscCall(KSPSetConvergenceTest(ksp, ConvergenceTest, testarray, ConvergenceDestroy));
241: }
243: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
244: Evaluate initial guess; then solve nonlinear system
245: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
246: /*
247: Note: The user should initialize the vector, x, with the initial guess
248: for the nonlinear solver prior to calling SNESSolve(). In particular,
249: to employ an initial guess of zero, the user should explicitly set
250: this vector to zero by calling VecSet().
251: */
252: PetscCall(FormInitialGuess(&user, x));
253: PetscCall(SNESSolve(snes, NULL, x));
254: PetscCall(SNESGetIterationNumber(snes, &its));
255: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Number of SNES iterations = %" PetscInt_FMT "\n", its));
257: /*
258: Print the convergence history. This is intended just to demonstrate
259: use of the data attained via SNESSetConvergenceHistory().
260: */
261: PetscCall(PetscOptionsHasName(NULL, NULL, "-print_history", &flg));
262: if (flg) {
263: for (i = 0; i < its + 1; i++) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "iteration %" PetscInt_FMT ": Linear iterations %" PetscInt_FMT " Function norm = %g\n", i, hist_its[i], (double)history[i]));
264: }
266: /* Test NewtonTR API */
267: PetscCall(SNESNewtonTRSetTolerances(snes, 1.0, 2.0, 3.0));
268: PetscCall(SNESNewtonTRSetUpdateParameters(snes, 4.0, 5.0, 6.0, 7.0, 8.0));
269: PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESNEWTONTR, &flg));
270: if (flg) {
271: PetscReal tmp[5];
273: PetscCall(SNESNewtonTRGetTolerances(snes, &tmp[0], &tmp[1], &tmp[2]));
274: PetscCheck(tmp[0] == 1.0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Wrong value");
275: PetscCheck(tmp[1] == 2.0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Wrong value");
276: PetscCheck(tmp[2] == 3.0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Wrong value");
277: PetscCall(SNESNewtonTRGetUpdateParameters(snes, &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4]));
278: PetscCheck(tmp[0] == 4.0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Wrong value");
279: PetscCheck(tmp[1] == 5.0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Wrong value");
280: PetscCheck(tmp[2] == 6.0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Wrong value");
281: PetscCheck(tmp[3] == 7.0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Wrong value");
282: PetscCheck(tmp[4] == 8.0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Wrong value");
283: }
285: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
286: Free work space. All PETSc objects should be destroyed when they
287: are no longer needed.
288: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
290: if (!matrix_free) PetscCall(MatDestroy(&J));
291: if (fd_coloring) PetscCall(MatFDColoringDestroy(&fdcoloring));
292: PetscCall(VecDestroy(&x));
293: PetscCall(VecDestroy(&r));
294: PetscCall(SNESDestroy(&snes));
295: PetscCall(PetscFinalize());
296: return 0;
297: }
299: /*
300: FormInitialGuess - Forms initial approximation.
302: Input Parameters:
303: user - user-defined application context
304: X - vector
306: Output Parameter:
307: X - vector
308: */
309: PetscErrorCode FormInitialGuess(AppCtx *user, Vec X)
310: {
311: PetscInt i, j, row, mx, my;
312: PetscReal lambda, temp1, temp, hx, hy;
313: PetscScalar *x;
315: PetscFunctionBeginUser;
316: mx = user->mx;
317: my = user->my;
318: lambda = user->param;
320: hx = 1.0 / (PetscReal)(mx - 1);
321: hy = 1.0 / (PetscReal)(my - 1);
323: /*
324: Get a pointer to vector data.
325: - For default PETSc vectors, VecGetArray() returns a pointer to
326: the data array. Otherwise, the routine is implementation dependent.
327: - You MUST call VecRestoreArray() when you no longer need access to
328: the array.
329: */
330: PetscCall(VecGetArray(X, &x));
331: temp1 = lambda / (lambda + 1.0);
332: for (j = 0; j < my; j++) {
333: temp = (PetscReal)(PetscMin(j, my - j - 1)) * hy;
334: for (i = 0; i < mx; i++) {
335: row = i + j * mx;
336: if (i == 0 || j == 0 || i == mx - 1 || j == my - 1) {
337: x[row] = 0.0;
338: continue;
339: }
340: x[row] = temp1 * PetscSqrtReal(PetscMin((PetscReal)(PetscMin(i, mx - i - 1)) * hx, temp));
341: }
342: }
344: /*
345: Restore vector
346: */
347: PetscCall(VecRestoreArray(X, &x));
348: PetscFunctionReturn(PETSC_SUCCESS);
349: }
351: /*
352: FormFunction - Evaluates nonlinear function, F(x).
354: Input Parameters:
355: . snes - the SNES context
356: . X - input vector
357: . ptr - optional user-defined context, as set by SNESSetFunction()
359: Output Parameter:
360: . F - function vector
361: */
362: PetscErrorCode FormFunction(SNES snes, Vec X, Vec F, void *ptr)
363: {
364: AppCtx *user = (AppCtx *)ptr;
365: PetscInt i, j, row, mx, my;
366: PetscReal two = 2.0, one = 1.0, lambda, hx, hy, hxdhy, hydhx;
367: PetscScalar ut, ub, ul, ur, u, uxx, uyy, sc, *f;
368: const PetscScalar *x;
370: PetscFunctionBeginUser;
371: mx = user->mx;
372: my = user->my;
373: lambda = user->param;
374: hx = one / (PetscReal)(mx - 1);
375: hy = one / (PetscReal)(my - 1);
376: sc = hx * hy;
377: hxdhy = hx / hy;
378: hydhx = hy / hx;
380: /*
381: Get pointers to vector data
382: */
383: PetscCall(VecGetArrayRead(X, &x));
384: PetscCall(VecGetArray(F, &f));
386: /*
387: Compute function
388: */
389: for (j = 0; j < my; j++) {
390: for (i = 0; i < mx; i++) {
391: row = i + j * mx;
392: if (i == 0 || j == 0 || i == mx - 1 || j == my - 1) {
393: f[row] = x[row];
394: continue;
395: }
396: u = x[row];
397: ub = x[row - mx];
398: ul = x[row - 1];
399: ut = x[row + mx];
400: ur = x[row + 1];
401: uxx = (-ur + two * u - ul) * hydhx;
402: uyy = (-ut + two * u - ub) * hxdhy;
403: f[row] = uxx + uyy - sc * lambda * PetscExpScalar(u);
404: }
405: }
407: /*
408: Restore vectors
409: */
410: PetscCall(VecRestoreArrayRead(X, &x));
411: PetscCall(VecRestoreArray(F, &f));
412: PetscFunctionReturn(PETSC_SUCCESS);
413: }
415: /*
416: FormJacobian - Evaluates Jacobian matrix.
418: Input Parameters:
419: . snes - the SNES context
420: . x - input vector
421: . ptr - optional user-defined context, as set by SNESSetJacobian()
423: Output Parameters:
424: . A - Jacobian matrix
425: . B - optionally different preconditioning matrix
427: */
428: PetscErrorCode FormJacobian(SNES snes, Vec X, Mat J, Mat jac, void *ptr)
429: {
430: AppCtx *user = (AppCtx *)ptr; /* user-defined application context */
431: PetscInt i, j, row, mx, my, col[5];
432: PetscScalar two = 2.0, one = 1.0, lambda, v[5], sc;
433: const PetscScalar *x;
434: PetscReal hx, hy, hxdhy, hydhx;
436: PetscFunctionBeginUser;
437: mx = user->mx;
438: my = user->my;
439: lambda = user->param;
440: hx = 1.0 / (PetscReal)(mx - 1);
441: hy = 1.0 / (PetscReal)(my - 1);
442: sc = hx * hy;
443: hxdhy = hx / hy;
444: hydhx = hy / hx;
446: /*
447: Get pointer to vector data
448: */
449: PetscCall(VecGetArrayRead(X, &x));
451: /*
452: Compute entries of the Jacobian
453: */
454: for (j = 0; j < my; j++) {
455: for (i = 0; i < mx; i++) {
456: row = i + j * mx;
457: if (i == 0 || j == 0 || i == mx - 1 || j == my - 1) {
458: PetscCall(MatSetValues(jac, 1, &row, 1, &row, &one, INSERT_VALUES));
459: continue;
460: }
461: v[0] = -hxdhy;
462: col[0] = row - mx;
463: v[1] = -hydhx;
464: col[1] = row - 1;
465: v[2] = two * (hydhx + hxdhy) - sc * lambda * PetscExpScalar(x[row]);
466: col[2] = row;
467: v[3] = -hydhx;
468: col[3] = row + 1;
469: v[4] = -hxdhy;
470: col[4] = row + mx;
471: PetscCall(MatSetValues(jac, 1, &row, 5, col, v, INSERT_VALUES));
472: }
473: }
475: /*
476: Restore vector
477: */
478: PetscCall(VecRestoreArrayRead(X, &x));
480: /*
481: Assemble matrix
482: */
483: PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY));
484: PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY));
486: if (jac != J) {
487: PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
488: PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
489: }
490: PetscFunctionReturn(PETSC_SUCCESS);
491: }
493: PetscErrorCode ConvergenceTest(KSP ksp, PetscInt it, PetscReal nrm, KSPConvergedReason *reason, void *ctx)
494: {
495: PetscFunctionBeginUser;
496: *reason = KSP_CONVERGED_ITERATING;
497: if (it > 1) {
498: *reason = KSP_CONVERGED_ITS;
499: PetscCall(PetscInfo(NULL, "User provided convergence test returning after 2 iterations\n"));
500: }
501: PetscFunctionReturn(PETSC_SUCCESS);
502: }
504: PetscErrorCode ConvergenceDestroy(void *ctx)
505: {
506: PetscFunctionBeginUser;
507: PetscCall(PetscInfo(NULL, "User provided convergence destroy called\n"));
508: PetscCall(PetscFree(ctx));
509: PetscFunctionReturn(PETSC_SUCCESS);
510: }
512: PetscErrorCode postcheck(SNES snes, Vec x, Vec y, Vec w, PetscBool *changed_y, PetscBool *changed_w, void *ctx)
513: {
514: PetscReal norm;
515: Vec tmp;
517: PetscFunctionBeginUser;
518: PetscCall(VecDuplicate(x, &tmp));
519: PetscCall(VecWAXPY(tmp, -1.0, x, w));
520: PetscCall(VecNorm(tmp, NORM_2, &norm));
521: PetscCall(VecDestroy(&tmp));
522: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Norm of search step %g\n", (double)norm));
523: PetscFunctionReturn(PETSC_SUCCESS);
524: }
526: /*TEST
528: build:
529: requires: !single
531: test:
532: args: -ksp_gmres_cgs_refinement_type refine_always
534: test:
535: suffix: 2
536: args: -snes_monitor_short -snes_type newtontr -ksp_gmres_cgs_refinement_type refine_always
538: test:
539: suffix: 2a
540: filter: grep -i KSPConvergedDefault > /dev/null && echo "Found KSPConvergedDefault"
541: args: -snes_monitor_short -snes_type newtontr -ksp_gmres_cgs_refinement_type refine_always -info
542: requires: defined(PETSC_USE_INFO)
544: test:
545: suffix: 2b
546: filter: grep -i "User provided convergence test" > /dev/null && echo "Found User provided convergence test"
547: args: -snes_monitor_short -snes_type newtontr -ksp_gmres_cgs_refinement_type refine_always -use_convergence_test -info
548: requires: defined(PETSC_USE_INFO)
550: test:
551: suffix: 2c
552: args: -snes_converged_reason -snes_type newtontr -snes_tr_qn {{same different}separate output} -pc_type mat -snes_view -snes_tr_qn_mat_type lmvmdfp -snes_tr_norm_type infinity
554: test:
555: suffix: 3
556: args: -snes_monitor_short -mat_coloring_type sl -snes_fd_coloring -mx 8 -my 11 -ksp_gmres_cgs_refinement_type refine_always
558: test:
559: suffix: 4
560: args: -pc -par 6.807 -snes_monitor -snes_converged_reason
562: test:
563: suffix: 5
564: args: -snes_monitor_short -mat_coloring_type sl -snes_fd_coloring -mx 8 -my 11 -ksp_gmres_cgs_refinement_type refine_always -prune_jacobian
565: output_file: output/ex1_3.out
567: test:
568: suffix: 6
569: args: -snes_monitor draw:image:testfile -viewer_view
571: test:
572: suffix: python
573: requires: petsc4py
574: args: -python -snes_type python -snes_python_type ex1.py:MySNES -snes_view -null_appctx {{0 1}separate output}
575: localrunfiles: ex1.py
577: TEST*/