Actual source code: snes.c
1: #define PETSCSNES_DLL
3: #include private/snesimpl.h
5: PetscTruth SNESRegisterAllCalled = PETSC_FALSE;
6: PetscFList SNESList = PETSC_NULL;
8: /* Logging support */
9: PetscCookie SNES_COOKIE;
10: PetscLogEvent SNES_Solve, SNES_LineSearch, SNES_FunctionEval, SNES_JacobianEval;
14: /*@
15: SNESSetFunctionDomainError - tells SNES that the input vector to your FormFunction is not
16: in the functions domain. For example, negative pressure.
18: Collective on SNES
20: Input Parameters:
21: . SNES - the SNES context
23: Level: advanced
25: .keywords: SNES, view
27: .seealso: SNESCreate(), SNESSetFunction()
28: @*/
29: PetscErrorCode SNESSetFunctionDomainError(SNES snes)
30: {
33: snes->domainerror = PETSC_TRUE;
34: return(0);
35: }
39: /*@C
40: SNESView - Prints the SNES data structure.
42: Collective on SNES
44: Input Parameters:
45: + SNES - the SNES context
46: - viewer - visualization context
48: Options Database Key:
49: . -snes_view - Calls SNESView() at end of SNESSolve()
51: Notes:
52: The available visualization contexts include
53: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
54: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
55: output where only the first processor opens
56: the file. All other processors send their
57: data to the first processor to print.
59: The user can open an alternative visualization context with
60: PetscViewerASCIIOpen() - output to a specified file.
62: Level: beginner
64: .keywords: SNES, view
66: .seealso: PetscViewerASCIIOpen()
67: @*/
68: PetscErrorCode SNESView(SNES snes,PetscViewer viewer)
69: {
70: SNESKSPEW *kctx;
71: PetscErrorCode ierr;
72: KSP ksp;
73: const SNESType type;
74: PetscTruth iascii,isstring;
78: if (!viewer) {
79: PetscViewerASCIIGetStdout(((PetscObject)snes)->comm,&viewer);
80: }
84: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
85: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
86: if (iascii) {
87: if (((PetscObject)snes)->prefix) {
88: PetscViewerASCIIPrintf(viewer,"SNES Object:(%s)\n",((PetscObject)snes)->prefix);
89: } else {
90: PetscViewerASCIIPrintf(viewer,"SNES Object:\n");
91: }
92: SNESGetType(snes,&type);
93: if (type) {
94: PetscViewerASCIIPrintf(viewer," type: %s\n",type);
95: } else {
96: PetscViewerASCIIPrintf(viewer," type: not set yet\n");
97: }
98: if (snes->ops->view) {
99: PetscViewerASCIIPushTab(viewer);
100: (*snes->ops->view)(snes,viewer);
101: PetscViewerASCIIPopTab(viewer);
102: }
103: PetscViewerASCIIPrintf(viewer," maximum iterations=%D, maximum function evaluations=%D\n",snes->max_its,snes->max_funcs);
104: PetscViewerASCIIPrintf(viewer," tolerances: relative=%G, absolute=%G, solution=%G\n",
105: snes->rtol,snes->abstol,snes->xtol);
106: PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",snes->linear_its);
107: PetscViewerASCIIPrintf(viewer," total number of function evaluations=%D\n",snes->nfuncs);
108: if (snes->ksp_ewconv) {
109: kctx = (SNESKSPEW *)snes->kspconvctx;
110: if (kctx) {
111: PetscViewerASCIIPrintf(viewer," Eisenstat-Walker computation of KSP relative tolerance (version %D)\n",kctx->version);
112: PetscViewerASCIIPrintf(viewer," rtol_0=%G, rtol_max=%G, threshold=%G\n",kctx->rtol_0,kctx->rtol_max,kctx->threshold);
113: PetscViewerASCIIPrintf(viewer," gamma=%G, alpha=%G, alpha2=%G\n",kctx->gamma,kctx->alpha,kctx->alpha2);
114: }
115: }
116: if (snes->lagpreconditioner == -1) {
117: PetscViewerASCIIPrintf(viewer," Preconditioned is never rebuilt\n");
118: } else if (snes->lagpreconditioner > 1) {
119: PetscViewerASCIIPrintf(viewer," Preconditioned is rebuilt every %D new Jacobians\n",snes->lagpreconditioner);
120: }
121: if (snes->lagjacobian == -1) {
122: PetscViewerASCIIPrintf(viewer," Jacobian is never rebuilt\n");
123: } else if (snes->lagjacobian > 1) {
124: PetscViewerASCIIPrintf(viewer," Jacobian is rebuilt every %D Newton iterations\n",snes->lagjacobian);
125: }
126: } else if (isstring) {
127: SNESGetType(snes,&type);
128: PetscViewerStringSPrintf(viewer," %-3.3s",type);
129: }
130: SNESGetKSP(snes,&ksp);
131: PetscViewerASCIIPushTab(viewer);
132: KSPView(ksp,viewer);
133: PetscViewerASCIIPopTab(viewer);
134: return(0);
135: }
137: /*
138: We retain a list of functions that also take SNES command
139: line options. These are called at the end SNESSetFromOptions()
140: */
141: #define MAXSETFROMOPTIONS 5
142: static PetscInt numberofsetfromoptions;
143: static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
147: /*@C
148: SNESAddOptionsChecker - Adds an additional function to check for SNES options.
150: Not Collective
152: Input Parameter:
153: . snescheck - function that checks for options
155: Level: developer
157: .seealso: SNESSetFromOptions()
158: @*/
159: PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES))
160: {
162: if (numberofsetfromoptions >= MAXSETFROMOPTIONS) {
163: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %D allowed", MAXSETFROMOPTIONS);
164: }
165: othersetfromoptions[numberofsetfromoptions++] = snescheck;
166: return(0);
167: }
169: EXTERN PetscErrorCode SNESDefaultMatrixFreeCreate2(SNES,Vec,Mat*);
173: static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscTruth hasOperator, PetscInt version)
174: {
175: Mat J;
176: KSP ksp;
177: PC pc;
178: PetscTruth match;
184: if(!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
185: Mat A = snes->jacobian, B = snes->jacobian_pre;
186: MatGetVecs(A ? A : B, PETSC_NULL,&snes->vec_func);
187: }
189: if (version == 1) {
190: MatCreateSNESMF(snes,&J);
191: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
192: MatMFFDSetFromOptions(J);
193: } else if (version == 2) {
194: if (!snes->vec_func) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"SNESSetFunction() must be called first");
195: #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SCALAR_SINGLE) && !defined(PETSC_USE_SCALAR_MAT_SINGLE) && !defined(PETSC_USE_SCALAR_LONG_DOUBLE) && !defined(PETSC_USE_SCALAR_INT)
196: SNESDefaultMatrixFreeCreate2(snes,snes->vec_func,&J);
197: #else
198: SETERRQ(PETSC_ERR_SUP, "matrix-free operator rutines (version 2)");
199: #endif
200: } else {
201: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator rutines, only version 1 and 2");
202: }
203:
204: PetscInfo1(snes,"Setting default matrix-free operator routines (version %D)\n", version);
205: if (hasOperator) {
206: /* This version replaces the user provided Jacobian matrix with a
207: matrix-free version but still employs the user-provided preconditioner matrix. */
208: SNESSetJacobian(snes,J,0,0,0);
209: } else {
210: /* This version replaces both the user-provided Jacobian and the user-
211: provided preconditioner matrix with the default matrix free version. */
212: SNESSetJacobian(snes,J,J,MatMFFDComputeJacobian,snes->funP);
213: /* Force no preconditioner */
214: SNESGetKSP(snes,&ksp);
215: KSPGetPC(ksp,&pc);
216: PetscTypeCompare((PetscObject)pc,PCSHELL,&match);
217: if (!match) {
218: PetscInfo(snes,"Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n");
219: PCSetType(pc,PCNONE);
220: }
221: }
222: MatDestroy(J);
224: return(0);
225: }
229: /*@
230: SNESSetFromOptions - Sets various SNES and KSP parameters from user options.
232: Collective on SNES
234: Input Parameter:
235: . snes - the SNES context
237: Options Database Keys:
238: + -snes_type <type> - ls, tr, umls, umtr, test
239: . -snes_stol - convergence tolerance in terms of the norm
240: of the change in the solution between steps
241: . -snes_atol <abstol> - absolute tolerance of residual norm
242: . -snes_rtol <rtol> - relative decrease in tolerance norm from initial
243: . -snes_max_it <max_it> - maximum number of iterations
244: . -snes_max_funcs <max_funcs> - maximum number of function evaluations
245: . -snes_max_fail <max_fail> - maximum number of failures
246: . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
247: . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild)
248: . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild)
249: . -snes_trtol <trtol> - trust region tolerance
250: . -snes_no_convergence_test - skip convergence test in nonlinear
251: solver; hence iterations will continue until max_it
252: or some other criterion is reached. Saves expense
253: of convergence test
254: . -snes_monitor <optional filename> - prints residual norm at each iteration. if no
255: filename given prints to stdout
256: . -snes_monitor_solution - plots solution at each iteration
257: . -snes_monitor_residual - plots residual (not its norm) at each iteration
258: . -snes_monitor_solution_update - plots update to solution at each iteration
259: . -snes_monitor_draw - plots residual norm at each iteration
260: . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
261: . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration
262: - -snes_converged_reason - print the reason for convergence/divergence after each solve
264: Options Database for Eisenstat-Walker method:
265: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
266: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
267: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
268: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
269: . -snes_ksp_ew_gamma <gamma> - Sets gamma
270: . -snes_ksp_ew_alpha <alpha> - Sets alpha
271: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
272: - -snes_ksp_ew_threshold <threshold> - Sets threshold
274: Notes:
275: To see all options, run your program with the -help option or consult
276: the users manual.
278: Level: beginner
280: .keywords: SNES, nonlinear, set, options, database
282: .seealso: SNESSetOptionsPrefix()
283: @*/
284: PetscErrorCode SNESSetFromOptions(SNES snes)
285: {
286: PetscTruth flg,mf,mf_operator;
287: PetscInt i,indx,lag,mf_version;
288: MatStructure matflag;
289: const char *deft = SNESLS;
290: const char *convtests[] = {"default","skip"};
291: SNESKSPEW *kctx = NULL;
292: char type[256], monfilename[PETSC_MAX_PATH_LEN];
293: PetscViewerASCIIMonitor monviewer;
294: PetscErrorCode ierr;
299: if (!SNESRegisterAllCalled) {SNESRegisterAll(PETSC_NULL);}
300: PetscOptionsBegin(((PetscObject)snes)->comm,((PetscObject)snes)->prefix,"Nonlinear solver (SNES) options","SNES");
301: if (((PetscObject)snes)->type_name) { deft = ((PetscObject)snes)->type_name; }
302: PetscOptionsList("-snes_type","Nonlinear solver method","SNESSetType",SNESList,deft,type,256,&flg);
303: if (flg) {
304: SNESSetType(snes,type);
305: } else if (!((PetscObject)snes)->type_name) {
306: SNESSetType(snes,deft);
307: }
308: /* not used here, but called so will go into help messaage */
309: PetscOptionsName("-snes_view","Print detailed information on solver used","SNESView",0);
311: PetscOptionsReal("-snes_stol","Stop if step length less than","SNESSetTolerances",snes->xtol,&snes->xtol,0);
312: PetscOptionsReal("-snes_atol","Stop if function norm less than","SNESSetTolerances",snes->abstol,&snes->abstol,0);
314: PetscOptionsReal("-snes_rtol","Stop if decrease in function norm less than","SNESSetTolerances",snes->rtol,&snes->rtol,0);
315: PetscOptionsInt("-snes_max_it","Maximum iterations","SNESSetTolerances",snes->max_its,&snes->max_its,PETSC_NULL);
316: PetscOptionsInt("-snes_max_funcs","Maximum function evaluations","SNESSetTolerances",snes->max_funcs,&snes->max_funcs,PETSC_NULL);
317: PetscOptionsInt("-snes_max_fail","Maximum failures","SNESSetTolerances",snes->maxFailures,&snes->maxFailures,PETSC_NULL);
318: PetscOptionsInt("-snes_max_linear_solve_fail","Maximum failures in linear solves allowed","SNESSetMaxLinearSolveFailures",snes->maxLinearSolveFailures,&snes->maxLinearSolveFailures,PETSC_NULL);
320: PetscOptionsInt("-snes_lag_preconditioner","How often to rebuild preconditioner","SNESSetLagPreconditioner",snes->lagpreconditioner,&lag,&flg);
321: if (flg) {
322: SNESSetLagPreconditioner(snes,lag);
323: }
324: PetscOptionsInt("-snes_lag_jacobian","How often to rebuild Jacobian","SNESSetLagJacobian",snes->lagjacobian,&lag,&flg);
325: if (flg) {
326: SNESSetLagJacobian(snes,lag);
327: }
329: PetscOptionsEList("-snes_convergence_test","Convergence test","SNESSetConvergenceTest",convtests,2,"default",&indx,&flg);
330: if (flg) {
331: switch (indx) {
332: case 0: SNESSetConvergenceTest(snes,SNESDefaultConverged,PETSC_NULL,PETSC_NULL); break;
333: case 1: SNESSetConvergenceTest(snes,SNESSkipConverged,PETSC_NULL,PETSC_NULL); break;
334: }
335: }
337: PetscOptionsTruth("-snes_converged_reason","Print reason for converged or diverged","SNESSolve",snes->printreason,&snes->printreason,PETSC_NULL);
339: kctx = (SNESKSPEW *)snes->kspconvctx;
341: PetscOptionsTruth("-snes_ksp_ew","Use Eisentat-Walker linear system convergence test","SNESKSPSetUseEW",snes->ksp_ewconv,&snes->ksp_ewconv,PETSC_NULL);
343: PetscOptionsInt("-snes_ksp_ew_version","Version 1, 2 or 3","SNESKSPSetParametersEW",kctx->version,&kctx->version,0);
344: PetscOptionsReal("-snes_ksp_ew_rtol0","0 <= rtol0 < 1","SNESKSPSetParametersEW",kctx->rtol_0,&kctx->rtol_0,0);
345: PetscOptionsReal("-snes_ksp_ew_rtolmax","0 <= rtolmax < 1","SNESKSPSetParametersEW",kctx->rtol_max,&kctx->rtol_max,0);
346: PetscOptionsReal("-snes_ksp_ew_gamma","0 <= gamma <= 1","SNESKSPSetParametersEW",kctx->gamma,&kctx->gamma,0);
347: PetscOptionsReal("-snes_ksp_ew_alpha","1 < alpha <= 2","SNESKSPSetParametersEW",kctx->alpha,&kctx->alpha,0);
348: PetscOptionsReal("-snes_ksp_ew_alpha2","alpha2","SNESKSPSetParametersEW",kctx->alpha2,&kctx->alpha2,0);
349: PetscOptionsReal("-snes_ksp_ew_threshold","0 < threshold < 1","SNESKSPSetParametersEW",kctx->threshold,&kctx->threshold,0);
351: flg = PETSC_FALSE;
352: PetscOptionsTruth("-snes_monitor_cancel","Remove all monitors","SNESMonitorCancel",flg,&flg,PETSC_NULL);
353: if (flg) {SNESMonitorCancel(snes);}
355: PetscOptionsString("-snes_monitor","Monitor norm of function","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
356: if (flg) {
357: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,monfilename,((PetscObject)snes)->tablevel,&monviewer);
358: SNESMonitorSet(snes,SNESMonitorDefault,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
359: }
361: PetscOptionsString("-snes_monitor_range","Monitor range of elements of function","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
362: if (flg) {
363: SNESMonitorSet(snes,SNESMonitorRange,0,0);
364: }
366: PetscOptionsString("-snes_ratiomonitor","Monitor ratios of norms of function","SNESMonitorSetRatio","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
367: if (flg) {
368: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,monfilename,((PetscObject)snes)->tablevel,&monviewer);
369: SNESMonitorSetRatio(snes,monviewer);
370: }
372: PetscOptionsString("-snes_monitor_short","Monitor norm of function (fewer digits)","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
373: if (flg) {
374: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,monfilename,((PetscObject)snes)->tablevel,&monviewer);
375: SNESMonitorSet(snes,SNESMonitorDefaultShort,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
376: }
378: flg = PETSC_FALSE;
379: PetscOptionsTruth("-snes_monitor_solution","Plot solution at each iteration","SNESMonitorSolution",flg,&flg,PETSC_NULL);
380: if (flg) {SNESMonitorSet(snes,SNESMonitorSolution,0,0);}
381: flg = PETSC_FALSE;
382: PetscOptionsTruth("-snes_monitor_solution_update","Plot correction at each iteration","SNESMonitorSolutionUpdate",flg,&flg,PETSC_NULL);
383: if (flg) {SNESMonitorSet(snes,SNESMonitorSolutionUpdate,0,0);}
384: flg = PETSC_FALSE;
385: PetscOptionsTruth("-snes_monitor_residual","Plot residual at each iteration","SNESMonitorResidual",flg,&flg,PETSC_NULL);
386: if (flg) {SNESMonitorSet(snes,SNESMonitorResidual,0,0);}
387: flg = PETSC_FALSE;
388: PetscOptionsTruth("-snes_monitor_draw","Plot function norm at each iteration","SNESMonitorLG",flg,&flg,PETSC_NULL);
389: if (flg) {SNESMonitorSet(snes,SNESMonitorLG,PETSC_NULL,PETSC_NULL);}
390: flg = PETSC_FALSE;
391: PetscOptionsTruth("-snes_monitor_range_draw","Plot function range at each iteration","SNESMonitorLG",flg,&flg,PETSC_NULL);
392: if (flg) {SNESMonitorSet(snes,SNESMonitorLGRange,PETSC_NULL,PETSC_NULL);}
394: flg = PETSC_FALSE;
395: PetscOptionsTruth("-snes_fd","Use finite differences (slow) to compute Jacobian","SNESDefaultComputeJacobian",flg,&flg,PETSC_NULL);
396: if (flg) {
397: SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESDefaultComputeJacobian,snes->funP);
398: PetscInfo(snes,"Setting default finite difference Jacobian matrix\n");
399: }
401: mf = mf_operator = PETSC_FALSE;
402: flg = PETSC_FALSE;
403: PetscOptionsTruth("-snes_mf_operator","Use a Matrix-Free Jacobian with user-provided preconditioner matrix","MatCreateSNESMF",PETSC_FALSE,&mf_operator,&flg);
404: if (flg && mf_operator) mf = PETSC_TRUE;
405: flg = PETSC_FALSE;
406: PetscOptionsTruth("-snes_mf","Use a Matrix-Free Jacobian with no preconditioner matrix","MatCreateSNESMF",PETSC_FALSE,&mf,&flg);
407: if (!flg && mf_operator) mf = PETSC_TRUE;
408: mf_version = 1;
409: PetscOptionsInt("-snes_mf_version","Matrix-Free routines version 1 or 2","None",mf_version,&mf_version,0);
411: for(i = 0; i < numberofsetfromoptions; i++) {
412: (*othersetfromoptions[i])(snes);
413: }
415: if (snes->ops->setfromoptions) {
416: (*snes->ops->setfromoptions)(snes);
417: }
418: PetscOptionsEnd();
420: if (mf) { SNESSetUpMatrixFree_Private(snes, mf_operator, mf_version); }
421:
422: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
423: KSPGetOperators(snes->ksp,PETSC_NULL,PETSC_NULL,&matflag);
424: KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,matflag);
425: KSPSetFromOptions(snes->ksp);
427: return(0);
428: }
433: /*@
434: SNESSetApplicationContext - Sets the optional user-defined context for
435: the nonlinear solvers.
437: Collective on SNES
439: Input Parameters:
440: + snes - the SNES context
441: - usrP - optional user context
443: Level: intermediate
445: .keywords: SNES, nonlinear, set, application, context
447: .seealso: SNESGetApplicationContext()
448: @*/
449: PetscErrorCode SNESSetApplicationContext(SNES snes,void *usrP)
450: {
453: snes->user = usrP;
454: return(0);
455: }
459: /*@C
460: SNESGetApplicationContext - Gets the user-defined context for the
461: nonlinear solvers.
463: Not Collective
465: Input Parameter:
466: . snes - SNES context
468: Output Parameter:
469: . usrP - user context
471: Level: intermediate
473: .keywords: SNES, nonlinear, get, application, context
475: .seealso: SNESSetApplicationContext()
476: @*/
477: PetscErrorCode SNESGetApplicationContext(SNES snes,void **usrP)
478: {
481: *usrP = snes->user;
482: return(0);
483: }
487: /*@
488: SNESGetIterationNumber - Gets the number of nonlinear iterations completed
489: at this time.
491: Not Collective
493: Input Parameter:
494: . snes - SNES context
496: Output Parameter:
497: . iter - iteration number
499: Notes:
500: For example, during the computation of iteration 2 this would return 1.
502: This is useful for using lagged Jacobians (where one does not recompute the
503: Jacobian at each SNES iteration). For example, the code
504: .vb
505: SNESGetIterationNumber(snes,&it);
506: if (!(it % 2)) {
507: [compute Jacobian here]
508: }
509: .ve
510: can be used in your ComputeJacobian() function to cause the Jacobian to be
511: recomputed every second SNES iteration.
513: Level: intermediate
515: .keywords: SNES, nonlinear, get, iteration, number,
517: .seealso: SNESGetFunctionNorm(), SNESGetLinearSolveIterations()
518: @*/
519: PetscErrorCode SNESGetIterationNumber(SNES snes,PetscInt* iter)
520: {
524: *iter = snes->iter;
525: return(0);
526: }
530: /*@
531: SNESGetFunctionNorm - Gets the norm of the current function that was set
532: with SNESSSetFunction().
534: Collective on SNES
536: Input Parameter:
537: . snes - SNES context
539: Output Parameter:
540: . fnorm - 2-norm of function
542: Level: intermediate
544: .keywords: SNES, nonlinear, get, function, norm
546: .seealso: SNESGetFunction(), SNESGetIterationNumber(), SNESGetLinearSolveIterations()
547: @*/
548: PetscErrorCode SNESGetFunctionNorm(SNES snes,PetscReal *fnorm)
549: {
553: *fnorm = snes->norm;
554: return(0);
555: }
559: /*@
560: SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
561: attempted by the nonlinear solver.
563: Not Collective
565: Input Parameter:
566: . snes - SNES context
568: Output Parameter:
569: . nfails - number of unsuccessful steps attempted
571: Notes:
572: This counter is reset to zero for each successive call to SNESSolve().
574: Level: intermediate
576: .keywords: SNES, nonlinear, get, number, unsuccessful, steps
578: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
579: SNESSetMaxNonlinearStepFailures(), SNESGetMaxNonlinearStepFailures()
580: @*/
581: PetscErrorCode SNESGetNonlinearStepFailures(SNES snes,PetscInt* nfails)
582: {
586: *nfails = snes->numFailures;
587: return(0);
588: }
592: /*@
593: SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
594: attempted by the nonlinear solver before it gives up.
596: Not Collective
598: Input Parameters:
599: + snes - SNES context
600: - maxFails - maximum of unsuccessful steps
602: Level: intermediate
604: .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps
606: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
607: SNESGetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
608: @*/
609: PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
610: {
613: snes->maxFailures = maxFails;
614: return(0);
615: }
619: /*@
620: SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
621: attempted by the nonlinear solver before it gives up.
623: Not Collective
625: Input Parameter:
626: . snes - SNES context
628: Output Parameter:
629: . maxFails - maximum of unsuccessful steps
631: Level: intermediate
633: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
635: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
636: SNESSetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
637:
638: @*/
639: PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
640: {
644: *maxFails = snes->maxFailures;
645: return(0);
646: }
650: /*@
651: SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
652: done by SNES.
654: Not Collective
656: Input Parameter:
657: . snes - SNES context
659: Output Parameter:
660: . nfuncs - number of evaluations
662: Level: intermediate
664: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
666: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures()
667: @*/
668: PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
669: {
673: *nfuncs = snes->nfuncs;
674: return(0);
675: }
679: /*@
680: SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
681: linear solvers.
683: Not Collective
685: Input Parameter:
686: . snes - SNES context
688: Output Parameter:
689: . nfails - number of failed solves
691: Notes:
692: This counter is reset to zero for each successive call to SNESSolve().
694: Level: intermediate
696: .keywords: SNES, nonlinear, get, number, unsuccessful, steps
698: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures()
699: @*/
700: PetscErrorCode SNESGetLinearSolveFailures(SNES snes,PetscInt* nfails)
701: {
705: *nfails = snes->numLinearSolveFailures;
706: return(0);
707: }
711: /*@
712: SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
713: allowed before SNES returns with a diverged reason of SNES_DIVERGED_LINEAR_SOLVE
715: Collective on SNES
717: Input Parameters:
718: + snes - SNES context
719: - maxFails - maximum allowed linear solve failures
721: Level: intermediate
723: Notes: By default this is 0; that is SNES returns on the first failed linear solve
725: .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps
727: .seealso: SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations()
728: @*/
729: PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
730: {
733: snes->maxLinearSolveFailures = maxFails;
734: return(0);
735: }
739: /*@
740: SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
741: are allowed before SNES terminates
743: Not Collective
745: Input Parameter:
746: . snes - SNES context
748: Output Parameter:
749: . maxFails - maximum of unsuccessful solves allowed
751: Level: intermediate
753: Notes: By default this is 1; that is SNES returns on the first failed linear solve
755: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
757: .seealso: SNESGetLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(),
758: @*/
759: PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
760: {
764: *maxFails = snes->maxLinearSolveFailures;
765: return(0);
766: }
770: /*@
771: SNESGetLinearSolveIterations - Gets the total number of linear iterations
772: used by the nonlinear solver.
774: Not Collective
776: Input Parameter:
777: . snes - SNES context
779: Output Parameter:
780: . lits - number of linear iterations
782: Notes:
783: This counter is reset to zero for each successive call to SNESSolve().
785: Level: intermediate
787: .keywords: SNES, nonlinear, get, number, linear, iterations
789: .seealso: SNESGetIterationNumber(), SNESGetFunctionNorm(), SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures()
790: @*/
791: PetscErrorCode SNESGetLinearSolveIterations(SNES snes,PetscInt* lits)
792: {
796: *lits = snes->linear_its;
797: return(0);
798: }
802: /*@
803: SNESGetKSP - Returns the KSP context for a SNES solver.
805: Not Collective, but if SNES object is parallel, then KSP object is parallel
807: Input Parameter:
808: . snes - the SNES context
810: Output Parameter:
811: . ksp - the KSP context
813: Notes:
814: The user can then directly manipulate the KSP context to set various
815: options, etc. Likewise, the user can then extract and manipulate the
816: PC contexts as well.
818: Level: beginner
820: .keywords: SNES, nonlinear, get, KSP, context
822: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
823: @*/
824: PetscErrorCode SNESGetKSP(SNES snes,KSP *ksp)
825: {
832: if (!snes->ksp) {
833: KSPCreate(((PetscObject)snes)->comm,&snes->ksp);
834: PetscObjectIncrementTabLevel((PetscObject)snes->ksp,(PetscObject)snes,1);
835: PetscLogObjectParent(snes,snes->ksp);
836: }
837: *ksp = snes->ksp;
838: return(0);
839: }
843: /*@
844: SNESSetKSP - Sets a KSP context for the SNES object to use
846: Not Collective, but the SNES and KSP objects must live on the same MPI_Comm
848: Input Parameters:
849: + snes - the SNES context
850: - ksp - the KSP context
852: Notes:
853: The SNES object already has its KSP object, you can obtain with SNESGetKSP()
854: so this routine is rarely needed.
856: The KSP object that is already in the SNES object has its reference count
857: decreased by one.
859: Level: developer
861: .keywords: SNES, nonlinear, get, KSP, context
863: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
864: @*/
865: PetscErrorCode SNESSetKSP(SNES snes,KSP ksp)
866: {
873: PetscObjectReference((PetscObject)ksp);
874: if (snes->ksp) {PetscObjectDereference((PetscObject)snes->ksp);}
875: snes->ksp = ksp;
876: return(0);
877: }
879: #if 0
882: static PetscErrorCode SNESPublish_Petsc(PetscObject obj)
883: {
885: return(0);
886: }
887: #endif
889: /* -----------------------------------------------------------*/
892: /*@
893: SNESCreate - Creates a nonlinear solver context.
895: Collective on MPI_Comm
897: Input Parameters:
898: . comm - MPI communicator
900: Output Parameter:
901: . outsnes - the new SNES context
903: Options Database Keys:
904: + -snes_mf - Activates default matrix-free Jacobian-vector products,
905: and no preconditioning matrix
906: . -snes_mf_operator - Activates default matrix-free Jacobian-vector
907: products, and a user-provided preconditioning matrix
908: as set by SNESSetJacobian()
909: - -snes_fd - Uses (slow!) finite differences to compute Jacobian
911: Level: beginner
913: .keywords: SNES, nonlinear, create, context
915: .seealso: SNESSolve(), SNESDestroy(), SNES, SNESSetLagPreconditioner()
917: @*/
918: PetscErrorCode SNESCreate(MPI_Comm comm,SNES *outsnes)
919: {
920: PetscErrorCode ierr;
921: SNES snes;
922: SNESKSPEW *kctx;
926: *outsnes = PETSC_NULL;
927: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
928: SNESInitializePackage(PETSC_NULL);
929: #endif
931: PetscHeaderCreate(snes,_p_SNES,struct _SNESOps,SNES_COOKIE,0,"SNES",comm,SNESDestroy,SNESView);
933: snes->ops->converged = SNESDefaultConverged;
934: snes->max_its = 50;
935: snes->max_funcs = 10000;
936: snes->norm = 0.0;
937: snes->rtol = 1.e-8;
938: snes->ttol = 0.0;
939: snes->abstol = 1.e-50;
940: snes->xtol = 1.e-8;
941: snes->deltatol = 1.e-12;
942: snes->nfuncs = 0;
943: snes->numFailures = 0;
944: snes->maxFailures = 1;
945: snes->linear_its = 0;
946: snes->lagjacobian = 1;
947: snes->lagpreconditioner = 1;
948: snes->numbermonitors = 0;
949: snes->data = 0;
950: snes->setupcalled = PETSC_FALSE;
951: snes->ksp_ewconv = PETSC_FALSE;
952: snes->vwork = 0;
953: snes->nwork = 0;
954: snes->conv_hist_len = 0;
955: snes->conv_hist_max = 0;
956: snes->conv_hist = PETSC_NULL;
957: snes->conv_hist_its = PETSC_NULL;
958: snes->conv_hist_reset = PETSC_TRUE;
959: snes->reason = SNES_CONVERGED_ITERATING;
961: snes->numLinearSolveFailures = 0;
962: snes->maxLinearSolveFailures = 1;
964: /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
965: PetscNewLog(snes,SNESKSPEW,&kctx);
966: snes->kspconvctx = (void*)kctx;
967: kctx->version = 2;
968: kctx->rtol_0 = .3; /* Eisenstat and Walker suggest rtol_0=.5, but
969: this was too large for some test cases */
970: kctx->rtol_last = 0.0;
971: kctx->rtol_max = .9;
972: kctx->gamma = 1.0;
973: kctx->alpha = .5*(1.0 + sqrt(5.0));
974: kctx->alpha2 = kctx->alpha;
975: kctx->threshold = .1;
976: kctx->lresid_last = 0.0;
977: kctx->norm_last = 0.0;
979: *outsnes = snes;
980: PetscPublishAll(snes);
981: return(0);
982: }
986: /*@C
987: SNESSetFunction - Sets the function evaluation routine and function
988: vector for use by the SNES routines in solving systems of nonlinear
989: equations.
991: Collective on SNES
993: Input Parameters:
994: + snes - the SNES context
995: . r - vector to store function value
996: . func - function evaluation routine
997: - ctx - [optional] user-defined context for private data for the
998: function evaluation routine (may be PETSC_NULL)
1000: Calling sequence of func:
1001: $ func (SNES snes,Vec x,Vec f,void *ctx);
1003: . f - function vector
1004: - ctx - optional user-defined function context
1006: Notes:
1007: The Newton-like methods typically solve linear systems of the form
1008: $ f'(x) x = -f(x),
1009: where f'(x) denotes the Jacobian matrix and f(x) is the function.
1011: Level: beginner
1013: .keywords: SNES, nonlinear, set, function
1015: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian()
1016: @*/
1017: PetscErrorCode SNESSetFunction(SNES snes,Vec r,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx)
1018: {
1024: PetscObjectReference((PetscObject)r);
1025: if (snes->vec_func) { VecDestroy(snes->vec_func); }
1026: snes->ops->computefunction = func;
1027: snes->vec_func = r;
1028: snes->funP = ctx;
1029: return(0);
1030: }
1032: /* --------------------------------------------------------------- */
1035: /*@C
1036: SNESGetRhs - Gets the vector for solving F(x) = rhs. If rhs is not set
1037: it assumes a zero right hand side.
1039: Collective on SNES
1041: Input Parameter:
1042: . snes - the SNES context
1044: Output Parameter:
1045: . rhs - the right hand side vector or PETSC_NULL if the right hand side vector is null
1047: Level: intermediate
1049: .keywords: SNES, nonlinear, get, function, right hand side
1051: .seealso: SNESGetSolution(), SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
1052: @*/
1053: PetscErrorCode SNESGetRhs(SNES snes,Vec *rhs)
1054: {
1058: *rhs = snes->vec_rhs;
1059: return(0);
1060: }
1064: /*@
1065: SNESComputeFunction - Calls the function that has been set with
1066: SNESSetFunction().
1068: Collective on SNES
1070: Input Parameters:
1071: + snes - the SNES context
1072: - x - input vector
1074: Output Parameter:
1075: . y - function vector, as set by SNESSetFunction()
1077: Notes:
1078: SNESComputeFunction() is typically used within nonlinear solvers
1079: implementations, so most users would not generally call this routine
1080: themselves.
1082: Level: developer
1084: .keywords: SNES, nonlinear, compute, function
1086: .seealso: SNESSetFunction(), SNESGetFunction()
1087: @*/
1088: PetscErrorCode SNESComputeFunction(SNES snes,Vec x,Vec y)
1089: {
1099: PetscLogEventBegin(SNES_FunctionEval,snes,x,y,0);
1100: if (snes->ops->computefunction) {
1101: PetscStackPush("SNES user function");
1102: CHKMEMQ;
1103: (*snes->ops->computefunction)(snes,x,y,snes->funP);
1104: CHKMEMQ;
1105: PetscStackPop;
1106: if (PetscExceptionValue(ierr)) {
1107: PetscErrorCode pPetscLogEventEnd(SNES_FunctionEval,snes,x,y,0);CHKERRQ(pierr);
1108: }
1109:
1110: } else if (snes->vec_rhs) {
1111: MatMult(snes->jacobian, x, y);
1112: } else {
1113: SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() before SNESComputeFunction(), likely called from SNESSolve().");
1114: }
1115: if (snes->vec_rhs) {
1116: VecAXPY(y,-1.0,snes->vec_rhs);
1117: }
1118: snes->nfuncs++;
1119: PetscLogEventEnd(SNES_FunctionEval,snes,x,y,0);
1120: return(0);
1121: }
1125: /*@
1126: SNESComputeJacobian - Computes the Jacobian matrix that has been
1127: set with SNESSetJacobian().
1129: Collective on SNES and Mat
1131: Input Parameters:
1132: + snes - the SNES context
1133: - x - input vector
1135: Output Parameters:
1136: + A - Jacobian matrix
1137: . B - optional preconditioning matrix
1138: - flag - flag indicating matrix structure (one of, SAME_NONZERO_PATTERN,DIFFERENT_NONZERO_PATTERN,SAME_PRECONDITIONER)
1140: Options Database Keys:
1141: + -snes_lag_preconditioner <lag>
1142: - -snes_lag_jacobian <lag>
1144: Notes:
1145: Most users should not need to explicitly call this routine, as it
1146: is used internally within the nonlinear solvers.
1148: See KSPSetOperators() for important information about setting the
1149: flag parameter.
1151: Level: developer
1153: .keywords: SNES, compute, Jacobian, matrix
1155: .seealso: SNESSetJacobian(), KSPSetOperators(), MatStructure, SNESSetLagPreconditioner(), SNESSetLagJacobian()
1156: @*/
1157: PetscErrorCode SNESComputeJacobian(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *flg)
1158: {
1160: PetscTruth flag;
1167: if (!snes->ops->computejacobian) return(0);
1169: /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
1171: if (snes->lagjacobian == -2) {
1172: snes->lagjacobian = -1;
1173: PetscInfo(snes,"Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n");
1174: } else if (snes->lagjacobian == -1) {
1175: *flg = SAME_PRECONDITIONER;
1176: PetscInfo(snes,"Reusing Jacobian/preconditioner because lag is -1\n");
1177: PetscTypeCompare((PetscObject)*A,MATMFFD,&flag);
1178: if (flag) {
1179: MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
1180: MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
1181: }
1182: return(0);
1183: } else if (snes->lagjacobian > 1 && snes->iter % snes->lagjacobian) {
1184: *flg = SAME_PRECONDITIONER;
1185: PetscInfo2(snes,"Reusing Jacobian/preconditioner because lag is %D and SNES iteration is %D\n",snes->lagjacobian,snes->iter);
1186: PetscTypeCompare((PetscObject)*A,MATMFFD,&flag);
1187: if (flag) {
1188: MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
1189: MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
1190: }
1191: return(0);
1192: }
1194: *flg = DIFFERENT_NONZERO_PATTERN;
1195: PetscLogEventBegin(SNES_JacobianEval,snes,X,*A,*B);
1196: PetscStackPush("SNES user Jacobian function");
1197: CHKMEMQ;
1198: (*snes->ops->computejacobian)(snes,X,A,B,flg,snes->jacP);
1199: CHKMEMQ;
1200: PetscStackPop;
1201: PetscLogEventEnd(SNES_JacobianEval,snes,X,*A,*B);
1203: if (snes->lagpreconditioner == -2) {
1204: PetscInfo(snes,"Rebuilding preconditioner exactly once since lag is -2\n");
1205: snes->lagpreconditioner = -1;
1206: } else if (snes->lagpreconditioner == -1) {
1207: *flg = SAME_PRECONDITIONER;
1208: PetscInfo(snes,"Reusing preconditioner because lag is -1\n");
1209: } else if (snes->lagpreconditioner > 1 && snes->iter % snes->lagpreconditioner) {
1210: *flg = SAME_PRECONDITIONER;
1211: PetscInfo2(snes,"Reusing preconditioner because lag is %D and SNES iteration is %D\n",snes->lagpreconditioner,snes->iter);
1212: }
1214: /* make sure user returned a correct Jacobian and preconditioner */
1217: return(0);
1218: }
1222: /*@C
1223: SNESSetJacobian - Sets the function to compute Jacobian as well as the
1224: location to store the matrix.
1226: Collective on SNES and Mat
1228: Input Parameters:
1229: + snes - the SNES context
1230: . A - Jacobian matrix
1231: . B - preconditioner matrix (usually same as the Jacobian)
1232: . func - Jacobian evaluation routine
1233: - ctx - [optional] user-defined context for private data for the
1234: Jacobian evaluation routine (may be PETSC_NULL)
1236: Calling sequence of func:
1237: $ func (SNES snes,Vec x,Mat *A,Mat *B,int *flag,void *ctx);
1239: + x - input vector
1240: . A - Jacobian matrix
1241: . B - preconditioner matrix, usually the same as A
1242: . flag - flag indicating information about the preconditioner matrix
1243: structure (same as flag in KSPSetOperators()), one of SAME_NONZERO_PATTERN,DIFFERENT_NONZERO_PATTERN,SAME_PRECONDITIONER
1244: - ctx - [optional] user-defined Jacobian context
1246: Notes:
1247: See KSPSetOperators() for important information about setting the flag
1248: output parameter in the routine func(). Be sure to read this information!
1250: The routine func() takes Mat * as the matrix arguments rather than Mat.
1251: This allows the Jacobian evaluation routine to replace A and/or B with a
1252: completely new new matrix structure (not just different matrix elements)
1253: when appropriate, for instance, if the nonzero structure is changing
1254: throughout the global iterations.
1256: If the A matrix and B matrix are different you must call MatAssemblyBegin/End() on
1257: each matrix.
1259: Level: beginner
1261: .keywords: SNES, nonlinear, set, Jacobian, matrix
1263: .seealso: KSPSetOperators(), SNESSetFunction(), MatMFFDComputeJacobian(), SNESDefaultComputeJacobianColor(), MatStructure
1264: @*/
1265: PetscErrorCode SNESSetJacobian(SNES snes,Mat A,Mat B,PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
1266: {
1275: if (func) snes->ops->computejacobian = func;
1276: if (ctx) snes->jacP = ctx;
1277: if (A) {
1278: PetscObjectReference((PetscObject)A);
1279: if (snes->jacobian) {MatDestroy(snes->jacobian);}
1280: snes->jacobian = A;
1281: }
1282: if (B) {
1283: PetscObjectReference((PetscObject)B);
1284: if (snes->jacobian_pre) {MatDestroy(snes->jacobian_pre);}
1285: snes->jacobian_pre = B;
1286: }
1287: return(0);
1288: }
1292: /*@C
1293: SNESGetJacobian - Returns the Jacobian matrix and optionally the user
1294: provided context for evaluating the Jacobian.
1296: Not Collective, but Mat object will be parallel if SNES object is
1298: Input Parameter:
1299: . snes - the nonlinear solver context
1301: Output Parameters:
1302: + A - location to stash Jacobian matrix (or PETSC_NULL)
1303: . B - location to stash preconditioner matrix (or PETSC_NULL)
1304: . func - location to put Jacobian function (or PETSC_NULL)
1305: - ctx - location to stash Jacobian ctx (or PETSC_NULL)
1307: Level: advanced
1309: .seealso: SNESSetJacobian(), SNESComputeJacobian()
1310: @*/
1311: PetscErrorCode SNESGetJacobian(SNES snes,Mat *A,Mat *B,PetscErrorCode (**func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
1312: {
1315: if (A) *A = snes->jacobian;
1316: if (B) *B = snes->jacobian_pre;
1317: if (func) *func = snes->ops->computejacobian;
1318: if (ctx) *ctx = snes->jacP;
1319: return(0);
1320: }
1322: /* ----- Routines to initialize and destroy a nonlinear solver ---- */
1326: /*@
1327: SNESSetUp - Sets up the internal data structures for the later use
1328: of a nonlinear solver.
1330: Collective on SNES
1332: Input Parameters:
1333: . snes - the SNES context
1335: Notes:
1336: For basic use of the SNES solvers the user need not explicitly call
1337: SNESSetUp(), since these actions will automatically occur during
1338: the call to SNESSolve(). However, if one wishes to control this
1339: phase separately, SNESSetUp() should be called after SNESCreate()
1340: and optional routines of the form SNESSetXXX(), but before SNESSolve().
1342: Level: advanced
1344: .keywords: SNES, nonlinear, setup
1346: .seealso: SNESCreate(), SNESSolve(), SNESDestroy()
1347: @*/
1348: PetscErrorCode SNESSetUp(SNES snes)
1349: {
1354: if (snes->setupcalled) return(0);
1356: if (!((PetscObject)snes)->type_name) {
1357: SNESSetType(snes,SNESLS);
1358: }
1360: if (!snes->vec_func && !snes->vec_rhs) {
1361: SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
1362: }
1363: if (!snes->ops->computefunction && !snes->vec_rhs) {
1364: SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
1365: }
1366: if (snes->vec_func == snes->vec_sol) {
1367: SETERRQ(PETSC_ERR_ARG_IDN,"Solution vector cannot be function vector");
1368: }
1369:
1370: if (!snes->ksp) {SNESGetKSP(snes, &snes->ksp);}
1371:
1372: if (snes->ops->setup) {
1373: (*snes->ops->setup)(snes);
1374: }
1375: snes->setupcalled = PETSC_TRUE;
1376: return(0);
1377: }
1381: /*@
1382: SNESDestroy - Destroys the nonlinear solver context that was created
1383: with SNESCreate().
1385: Collective on SNES
1387: Input Parameter:
1388: . snes - the SNES context
1390: Level: beginner
1392: .keywords: SNES, nonlinear, destroy
1394: .seealso: SNESCreate(), SNESSolve()
1395: @*/
1396: PetscErrorCode SNESDestroy(SNES snes)
1397: {
1402: if (--((PetscObject)snes)->refct > 0) return(0);
1404: /* if memory was published with AMS then destroy it */
1405: PetscObjectDepublish(snes);
1406: if (snes->ops->destroy) {(*(snes)->ops->destroy)(snes);}
1407:
1408: if (snes->vec_rhs) {VecDestroy(snes->vec_rhs);}
1409: if (snes->vec_sol) {VecDestroy(snes->vec_sol);}
1410: if (snes->vec_func) {VecDestroy(snes->vec_func);}
1411: if (snes->jacobian) {MatDestroy(snes->jacobian);}
1412: if (snes->jacobian_pre) {MatDestroy(snes->jacobian_pre);}
1413: if (snes->ksp) {KSPDestroy(snes->ksp);}
1414: PetscFree(snes->kspconvctx);
1415: if (snes->vwork) {VecDestroyVecs(snes->vwork,snes->nvwork);}
1416: SNESMonitorCancel(snes);
1417: if (snes->ops->convergeddestroy) {(*snes->ops->convergeddestroy)(snes->cnvP);}
1418: PetscHeaderDestroy(snes);
1419: return(0);
1420: }
1422: /* ----------- Routines to set solver parameters ---------- */
1426: /*@
1427: SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
1429: Collective on SNES
1431: Input Parameters:
1432: + snes - the SNES context
1433: - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
1434: the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
1436: Options Database Keys:
1437: . -snes_lag_preconditioner <lag>
1439: Notes:
1440: The default is 1
1441: The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
1442: If -1 is used before the very first nonlinear solve the preconditioner is still built because there is no previous preconditioner to use
1444: Level: intermediate
1446: .keywords: SNES, nonlinear, set, convergence, tolerances
1448: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian()
1450: @*/
1451: PetscErrorCode SNESSetLagPreconditioner(SNES snes,PetscInt lag)
1452: {
1455: if (lag < -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater");
1456: if (!lag) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0");
1457: snes->lagpreconditioner = lag;
1458: return(0);
1459: }
1463: /*@
1464: SNESGetLagPreconditioner - Indicates how often the preconditioner is rebuilt
1466: Collective on SNES
1468: Input Parameter:
1469: . snes - the SNES context
1470:
1471: Output Parameter:
1472: . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
1473: the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
1475: Options Database Keys:
1476: . -snes_lag_preconditioner <lag>
1478: Notes:
1479: The default is 1
1480: The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
1482: Level: intermediate
1484: .keywords: SNES, nonlinear, set, convergence, tolerances
1486: .seealso: SNESSetTrustRegionTolerance(), SNESSetLagPreconditioner()
1488: @*/
1489: PetscErrorCode SNESGetLagPreconditioner(SNES snes,PetscInt *lag)
1490: {
1493: *lag = snes->lagpreconditioner;
1494: return(0);
1495: }
1499: /*@
1500: SNESSetLagJacobian - Determines when the Jacobian is rebuilt in the nonlinear solve. See SNESSetLagPreconditioner() for determining how
1501: often the preconditioner is rebuilt.
1503: Collective on SNES
1505: Input Parameters:
1506: + snes - the SNES context
1507: - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
1508: the Jacobian is built etc. -2 means rebuild at next chance but then never again
1510: Options Database Keys:
1511: . -snes_lag_jacobian <lag>
1513: Notes:
1514: The default is 1
1515: The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
1516: If -1 is used before the very first nonlinear solve the CODE WILL FAIL! because no Jacobian is used, use -2 to indicate you want it recomputed
1517: at the next Newton step but never again (unless it is reset to another value)
1519: Level: intermediate
1521: .keywords: SNES, nonlinear, set, convergence, tolerances
1523: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagPreconditioner(), SNESGetLagJacobian()
1525: @*/
1526: PetscErrorCode SNESSetLagJacobian(SNES snes,PetscInt lag)
1527: {
1530: if (lag < -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater");
1531: if (!lag) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0");
1532: snes->lagjacobian = lag;
1533: return(0);
1534: }
1538: /*@
1539: SNESGetLagJacobian - Indicates how often the Jacobian is rebuilt. See SNESGetLagPreconditioner() to determine when the preconditioner is rebuilt
1541: Collective on SNES
1543: Input Parameter:
1544: . snes - the SNES context
1545:
1546: Output Parameter:
1547: . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
1548: the Jacobian is built etc.
1550: Options Database Keys:
1551: . -snes_lag_jacobian <lag>
1553: Notes:
1554: The default is 1
1555: The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
1557: Level: intermediate
1559: .keywords: SNES, nonlinear, set, convergence, tolerances
1561: .seealso: SNESSetTrustRegionTolerance(), SNESSetLagJacobian(), SNESSetLagPreconditioner(), SNESGetLagPreconditioner()
1563: @*/
1564: PetscErrorCode SNESGetLagJacobian(SNES snes,PetscInt *lag)
1565: {
1568: *lag = snes->lagjacobian;
1569: return(0);
1570: }
1574: /*@
1575: SNESSetTolerances - Sets various parameters used in convergence tests.
1577: Collective on SNES
1579: Input Parameters:
1580: + snes - the SNES context
1581: . abstol - absolute convergence tolerance
1582: . rtol - relative convergence tolerance
1583: . stol - convergence tolerance in terms of the norm
1584: of the change in the solution between steps
1585: . maxit - maximum number of iterations
1586: - maxf - maximum number of function evaluations
1588: Options Database Keys:
1589: + -snes_atol <abstol> - Sets abstol
1590: . -snes_rtol <rtol> - Sets rtol
1591: . -snes_stol <stol> - Sets stol
1592: . -snes_max_it <maxit> - Sets maxit
1593: - -snes_max_funcs <maxf> - Sets maxf
1595: Notes:
1596: The default maximum number of iterations is 50.
1597: The default maximum number of function evaluations is 1000.
1599: Level: intermediate
1601: .keywords: SNES, nonlinear, set, convergence, tolerances
1603: .seealso: SNESSetTrustRegionTolerance()
1604: @*/
1605: PetscErrorCode SNESSetTolerances(SNES snes,PetscReal abstol,PetscReal rtol,PetscReal stol,PetscInt maxit,PetscInt maxf)
1606: {
1609: if (abstol != PETSC_DEFAULT) snes->abstol = abstol;
1610: if (rtol != PETSC_DEFAULT) snes->rtol = rtol;
1611: if (stol != PETSC_DEFAULT) snes->xtol = stol;
1612: if (maxit != PETSC_DEFAULT) snes->max_its = maxit;
1613: if (maxf != PETSC_DEFAULT) snes->max_funcs = maxf;
1614: return(0);
1615: }
1619: /*@
1620: SNESGetTolerances - Gets various parameters used in convergence tests.
1622: Not Collective
1624: Input Parameters:
1625: + snes - the SNES context
1626: . atol - absolute convergence tolerance
1627: . rtol - relative convergence tolerance
1628: . stol - convergence tolerance in terms of the norm
1629: of the change in the solution between steps
1630: . maxit - maximum number of iterations
1631: - maxf - maximum number of function evaluations
1633: Notes:
1634: The user can specify PETSC_NULL for any parameter that is not needed.
1636: Level: intermediate
1638: .keywords: SNES, nonlinear, get, convergence, tolerances
1640: .seealso: SNESSetTolerances()
1641: @*/
1642: PetscErrorCode SNESGetTolerances(SNES snes,PetscReal *atol,PetscReal *rtol,PetscReal *stol,PetscInt *maxit,PetscInt *maxf)
1643: {
1646: if (atol) *atol = snes->abstol;
1647: if (rtol) *rtol = snes->rtol;
1648: if (stol) *stol = snes->xtol;
1649: if (maxit) *maxit = snes->max_its;
1650: if (maxf) *maxf = snes->max_funcs;
1651: return(0);
1652: }
1656: /*@
1657: SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
1659: Collective on SNES
1661: Input Parameters:
1662: + snes - the SNES context
1663: - tol - tolerance
1664:
1665: Options Database Key:
1666: . -snes_trtol <tol> - Sets tol
1668: Level: intermediate
1670: .keywords: SNES, nonlinear, set, trust region, tolerance
1672: .seealso: SNESSetTolerances()
1673: @*/
1674: PetscErrorCode SNESSetTrustRegionTolerance(SNES snes,PetscReal tol)
1675: {
1678: snes->deltatol = tol;
1679: return(0);
1680: }
1682: /*
1683: Duplicate the lg monitors for SNES from KSP; for some reason with
1684: dynamic libraries things don't work under Sun4 if we just use
1685: macros instead of functions
1686: */
1689: PetscErrorCode SNESMonitorLG(SNES snes,PetscInt it,PetscReal norm,void *ctx)
1690: {
1695: KSPMonitorLG((KSP)snes,it,norm,ctx);
1696: return(0);
1697: }
1701: PetscErrorCode SNESMonitorLGCreate(const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *draw)
1702: {
1706: KSPMonitorLGCreate(host,label,x,y,m,n,draw);
1707: return(0);
1708: }
1712: PetscErrorCode SNESMonitorLGDestroy(PetscDrawLG draw)
1713: {
1717: KSPMonitorLGDestroy(draw);
1718: return(0);
1719: }
1724: PetscErrorCode SNESMonitorLGRange(SNES snes,PetscInt n,PetscReal rnorm,void *monctx)
1725: {
1726: PetscDrawLG lg;
1727: PetscErrorCode ierr;
1728: PetscReal x,y,per;
1729: PetscViewer v = (PetscViewer)monctx;
1730: static PetscReal prev; /* should be in the context */
1731: PetscDraw draw;
1733: if (!monctx) {
1734: MPI_Comm comm;
1736: PetscObjectGetComm((PetscObject)snes,&comm);
1737: v = PETSC_VIEWER_DRAW_(comm);
1738: }
1739: PetscViewerDrawGetDrawLG(v,0,&lg);
1740: if (!n) {PetscDrawLGReset(lg);}
1741: PetscDrawLGGetDraw(lg,&draw);
1742: PetscDrawSetTitle(draw,"Residual norm");
1743: x = (PetscReal) n;
1744: if (rnorm > 0.0) y = log10(rnorm); else y = -15.0;
1745: PetscDrawLGAddPoint(lg,&x,&y);
1746: if (n < 20 || !(n % 5)) {
1747: PetscDrawLGDraw(lg);
1748: }
1750: PetscViewerDrawGetDrawLG(v,1,&lg);
1751: if (!n) {PetscDrawLGReset(lg);}
1752: PetscDrawLGGetDraw(lg,&draw);
1753: PetscDrawSetTitle(draw,"% elemts > .2*max elemt");
1754: SNESMonitorRange_Private(snes,n,&per);
1755: x = (PetscReal) n;
1756: y = 100.0*per;
1757: PetscDrawLGAddPoint(lg,&x,&y);
1758: if (n < 20 || !(n % 5)) {
1759: PetscDrawLGDraw(lg);
1760: }
1762: PetscViewerDrawGetDrawLG(v,2,&lg);
1763: if (!n) {prev = rnorm;PetscDrawLGReset(lg);}
1764: PetscDrawLGGetDraw(lg,&draw);
1765: PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm");
1766: x = (PetscReal) n;
1767: y = (prev - rnorm)/prev;
1768: PetscDrawLGAddPoint(lg,&x,&y);
1769: if (n < 20 || !(n % 5)) {
1770: PetscDrawLGDraw(lg);
1771: }
1773: PetscViewerDrawGetDrawLG(v,3,&lg);
1774: if (!n) {PetscDrawLGReset(lg);}
1775: PetscDrawLGGetDraw(lg,&draw);
1776: PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm*(% > .2 max)");
1777: x = (PetscReal) n;
1778: y = (prev - rnorm)/(prev*per);
1779: if (n > 2) { /*skip initial crazy value */
1780: PetscDrawLGAddPoint(lg,&x,&y);
1781: }
1782: if (n < 20 || !(n % 5)) {
1783: PetscDrawLGDraw(lg);
1784: }
1785: prev = rnorm;
1786: return(0);
1787: }
1791: PetscErrorCode SNESMonitorLGRangeCreate(const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *draw)
1792: {
1796: KSPMonitorLGCreate(host,label,x,y,m,n,draw);
1797: return(0);
1798: }
1802: PetscErrorCode SNESMonitorLGRangeDestroy(PetscDrawLG draw)
1803: {
1807: KSPMonitorLGDestroy(draw);
1808: return(0);
1809: }
1811: /* ------------ Routines to set performance monitoring options ----------- */
1815: /*@C
1816: SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
1817: iteration of the nonlinear solver to display the iteration's
1818: progress.
1820: Collective on SNES
1822: Input Parameters:
1823: + snes - the SNES context
1824: . func - monitoring routine
1825: . mctx - [optional] user-defined context for private data for the
1826: monitor routine (use PETSC_NULL if no context is desired)
1827: - monitordestroy - [optional] routine that frees monitor context
1828: (may be PETSC_NULL)
1830: Calling sequence of func:
1831: $ int func(SNES snes,PetscInt its, PetscReal norm,void *mctx)
1833: + snes - the SNES context
1834: . its - iteration number
1835: . norm - 2-norm function value (may be estimated)
1836: - mctx - [optional] monitoring context
1838: Options Database Keys:
1839: + -snes_monitor - sets SNESMonitorDefault()
1840: . -snes_monitor_draw - sets line graph monitor,
1841: uses SNESMonitorLGCreate()
1842: _ -snes_monitor_cancel - cancels all monitors that have
1843: been hardwired into a code by
1844: calls to SNESMonitorSet(), but
1845: does not cancel those set via
1846: the options database.
1848: Notes:
1849: Several different monitoring routines may be set by calling
1850: SNESMonitorSet() multiple times; all will be called in the
1851: order in which they were set.
1853: Fortran notes: Only a single monitor function can be set for each SNES object
1855: Level: intermediate
1857: .keywords: SNES, nonlinear, set, monitor
1859: .seealso: SNESMonitorDefault(), SNESMonitorCancel()
1860: @*/
1861: PetscErrorCode SNESMonitorSet(SNES snes,PetscErrorCode (*monitor)(SNES,PetscInt,PetscReal,void*),void *mctx,PetscErrorCode (*monitordestroy)(void*))
1862: {
1863: PetscInt i;
1867: if (snes->numbermonitors >= MAXSNESMONITORS) {
1868: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
1869: }
1870: for (i=0; i<snes->numbermonitors;i++) {
1871: if (monitor == snes->monitor[i] && monitordestroy == snes->monitordestroy[i] && mctx == snes->monitorcontext[i]) return(0);
1873: /* check if both default monitors that share common ASCII viewer */
1874: if (monitor == snes->monitor[i] && monitor == SNESMonitorDefault) {
1875: if (mctx && snes->monitorcontext[i]) {
1876: PetscErrorCode ierr;
1877: PetscViewerASCIIMonitor viewer1 = (PetscViewerASCIIMonitor) mctx;
1878: PetscViewerASCIIMonitor viewer2 = (PetscViewerASCIIMonitor) snes->monitorcontext[i];
1879: if (viewer1->viewer == viewer2->viewer) {
1880: (*monitordestroy)(mctx);
1881: return(0);
1882: }
1883: }
1884: }
1885: }
1886: snes->monitor[snes->numbermonitors] = monitor;
1887: snes->monitordestroy[snes->numbermonitors] = monitordestroy;
1888: snes->monitorcontext[snes->numbermonitors++] = (void*)mctx;
1889: return(0);
1890: }
1894: /*@C
1895: SNESMonitorCancel - Clears all the monitor functions for a SNES object.
1897: Collective on SNES
1899: Input Parameters:
1900: . snes - the SNES context
1902: Options Database Key:
1903: . -snes_monitor_cancel - cancels all monitors that have been hardwired
1904: into a code by calls to SNESMonitorSet(), but does not cancel those
1905: set via the options database
1907: Notes:
1908: There is no way to clear one specific monitor from a SNES object.
1910: Level: intermediate
1912: .keywords: SNES, nonlinear, set, monitor
1914: .seealso: SNESMonitorDefault(), SNESMonitorSet()
1915: @*/
1916: PetscErrorCode SNESMonitorCancel(SNES snes)
1917: {
1919: PetscInt i;
1923: for (i=0; i<snes->numbermonitors; i++) {
1924: if (snes->monitordestroy[i]) {
1925: (*snes->monitordestroy[i])(snes->monitorcontext[i]);
1926: }
1927: }
1928: snes->numbermonitors = 0;
1929: return(0);
1930: }
1934: /*@C
1935: SNESSetConvergenceTest - Sets the function that is to be used
1936: to test for convergence of the nonlinear iterative solution.
1938: Collective on SNES
1940: Input Parameters:
1941: + snes - the SNES context
1942: . func - routine to test for convergence
1943: . cctx - [optional] context for private data for the convergence routine (may be PETSC_NULL)
1944: - destroy - [optional] destructor for the context (may be PETSC_NULL; PETSC_NULL_FUNCTION in Fortran)
1946: Calling sequence of func:
1947: $ PetscErrorCode func (SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx)
1949: + snes - the SNES context
1950: . it - current iteration (0 is the first and is before any Newton step)
1951: . cctx - [optional] convergence context
1952: . reason - reason for convergence/divergence
1953: . xnorm - 2-norm of current iterate
1954: . gnorm - 2-norm of current step
1955: - f - 2-norm of function
1957: Level: advanced
1959: .keywords: SNES, nonlinear, set, convergence, test
1961: .seealso: SNESDefaultConverged(), SNESSkipConverged()
1962: @*/
1963: PetscErrorCode SNESSetConvergenceTest(SNES snes,PetscErrorCode (*func)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void *cctx,PetscErrorCode (*destroy)(void*))
1964: {
1969: if (!func) func = SNESSkipConverged;
1970: if (snes->ops->convergeddestroy) {
1971: (*snes->ops->convergeddestroy)(snes->cnvP);
1972: }
1973: snes->ops->converged = func;
1974: snes->ops->convergeddestroy = destroy;
1975: snes->cnvP = cctx;
1976: return(0);
1977: }
1981: /*@
1982: SNESGetConvergedReason - Gets the reason the SNES iteration was stopped.
1984: Not Collective
1986: Input Parameter:
1987: . snes - the SNES context
1989: Output Parameter:
1990: . reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the
1991: manual pages for the individual convergence tests for complete lists
1993: Level: intermediate
1995: Notes: Can only be called after the call the SNESSolve() is complete.
1997: .keywords: SNES, nonlinear, set, convergence, test
1999: .seealso: SNESSetConvergenceTest(), SNESConvergedReason
2000: @*/
2001: PetscErrorCode SNESGetConvergedReason(SNES snes,SNESConvergedReason *reason)
2002: {
2006: *reason = snes->reason;
2007: return(0);
2008: }
2012: /*@
2013: SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
2015: Collective on SNES
2017: Input Parameters:
2018: + snes - iterative context obtained from SNESCreate()
2019: . a - array to hold history, this array will contain the function norms computed at each step
2020: . its - integer array holds the number of linear iterations for each solve.
2021: . na - size of a and its
2022: - reset - PETSC_TRUE indicates each new nonlinear solve resets the history counter to zero,
2023: else it continues storing new values for new nonlinear solves after the old ones
2025: This routine is useful, e.g., when running a code for purposes
2026: of accurate performance monitoring, when no I/O should be done
2027: during the section of code that is being timed.
2029: Level: intermediate
2031: .keywords: SNES, set, convergence, history
2033: .seealso: SNESGetConvergenceHistory()
2035: @*/
2036: PetscErrorCode SNESSetConvergenceHistory(SNES snes,PetscReal a[],PetscInt its[],PetscInt na,PetscTruth reset)
2037: {
2042: snes->conv_hist = a;
2043: snes->conv_hist_its = its;
2044: snes->conv_hist_max = na;
2045: snes->conv_hist_len = 0;
2046: snes->conv_hist_reset = reset;
2047: return(0);
2048: }
2052: /*@C
2053: SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
2055: Collective on SNES
2057: Input Parameter:
2058: . snes - iterative context obtained from SNESCreate()
2060: Output Parameters:
2061: . a - array to hold history
2062: . its - integer array holds the number of linear iterations (or
2063: negative if not converged) for each solve.
2064: - na - size of a and its
2066: Notes:
2067: The calling sequence for this routine in Fortran is
2068: $ call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
2070: This routine is useful, e.g., when running a code for purposes
2071: of accurate performance monitoring, when no I/O should be done
2072: during the section of code that is being timed.
2074: Level: intermediate
2076: .keywords: SNES, get, convergence, history
2078: .seealso: SNESSetConvergencHistory()
2080: @*/
2081: PetscErrorCode SNESGetConvergenceHistory(SNES snes,PetscReal *a[],PetscInt *its[],PetscInt *na)
2082: {
2085: if (a) *a = snes->conv_hist;
2086: if (its) *its = snes->conv_hist_its;
2087: if (na) *na = snes->conv_hist_len;
2088: return(0);
2089: }
2093: /*@C
2094: SNESSetUpdate - Sets the general-purpose update function called
2095: at the beginning o every iteration of the nonlinear solve. Specifically
2096: it is called just before the Jacobian is "evaluated".
2098: Collective on SNES
2100: Input Parameters:
2101: . snes - The nonlinear solver context
2102: . func - The function
2104: Calling sequence of func:
2105: . func (SNES snes, PetscInt step);
2107: . step - The current step of the iteration
2109: Level: advanced
2111: Note: This is NOT what one uses to update the ghost points before a function evaluation, that should be done at the beginning of your FormFunction()
2112: This is not used by most users.
2114: .keywords: SNES, update
2116: .seealso SNESDefaultUpdate(), SNESSetJacobian(), SNESSolve()
2117: @*/
2118: PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
2119: {
2122: snes->ops->update = func;
2123: return(0);
2124: }
2128: /*@
2129: SNESDefaultUpdate - The default update function which does nothing.
2131: Not collective
2133: Input Parameters:
2134: . snes - The nonlinear solver context
2135: . step - The current step of the iteration
2137: Level: intermediate
2139: .keywords: SNES, update
2140: .seealso SNESSetUpdate(), SNESDefaultRhsBC(), SNESDefaultShortolutionBC()
2141: @*/
2142: PetscErrorCode SNESDefaultUpdate(SNES snes, PetscInt step)
2143: {
2145: return(0);
2146: }
2150: /*
2151: SNESScaleStep_Private - Scales a step so that its length is less than the
2152: positive parameter delta.
2154: Input Parameters:
2155: + snes - the SNES context
2156: . y - approximate solution of linear system
2157: . fnorm - 2-norm of current function
2158: - delta - trust region size
2160: Output Parameters:
2161: + gpnorm - predicted function norm at the new point, assuming local
2162: linearization. The value is zero if the step lies within the trust
2163: region, and exceeds zero otherwise.
2164: - ynorm - 2-norm of the step
2166: Note:
2167: For non-trust region methods such as SNESLS, the parameter delta
2168: is set to be the maximum allowable step size.
2170: .keywords: SNES, nonlinear, scale, step
2171: */
2172: PetscErrorCode SNESScaleStep_Private(SNES snes,Vec y,PetscReal *fnorm,PetscReal *delta,PetscReal *gpnorm,PetscReal *ynorm)
2173: {
2174: PetscReal nrm;
2175: PetscScalar cnorm;
2183: VecNorm(y,NORM_2,&nrm);
2184: if (nrm > *delta) {
2185: nrm = *delta/nrm;
2186: *gpnorm = (1.0 - nrm)*(*fnorm);
2187: cnorm = nrm;
2188: VecScale(y,cnorm);
2189: *ynorm = *delta;
2190: } else {
2191: *gpnorm = 0.0;
2192: *ynorm = nrm;
2193: }
2194: return(0);
2195: }
2199: /*@C
2200: SNESSolve - Solves a nonlinear system F(x) = b.
2201: Call SNESSolve() after calling SNESCreate() and optional routines of the form SNESSetXXX().
2203: Collective on SNES
2205: Input Parameters:
2206: + snes - the SNES context
2207: . b - the constant part of the equation, or PETSC_NULL to use zero.
2208: - x - the solution vector.
2210: Notes:
2211: The user should initialize the vector,x, with the initial guess
2212: for the nonlinear solve prior to calling SNESSolve. In particular,
2213: to employ an initial guess of zero, the user should explicitly set
2214: this vector to zero by calling VecSet().
2216: Level: beginner
2218: .keywords: SNES, nonlinear, solve
2220: .seealso: SNESCreate(), SNESDestroy(), SNESSetFunction(), SNESSetJacobian()
2221: @*/
2222: PetscErrorCode SNESSolve(SNES snes,Vec b,Vec x)
2223: {
2225: PetscTruth flg;
2226: char filename[PETSC_MAX_PATH_LEN];
2227: PetscViewer viewer;
2236: /* set solution vector */
2237: PetscObjectReference((PetscObject)x);
2238: if (snes->vec_sol) { VecDestroy(snes->vec_sol); }
2239: snes->vec_sol = x;
2240: /* set afine vector if provided */
2241: if (b) { PetscObjectReference((PetscObject)b); }
2242: if (snes->vec_rhs) { VecDestroy(snes->vec_rhs); }
2243: snes->vec_rhs = b;
2244:
2245: if (!snes->vec_func && snes->vec_rhs) {
2246: VecDuplicate(b, &snes->vec_func);
2247: }
2249: SNESSetUp(snes);
2251: if (snes->conv_hist_reset) snes->conv_hist_len = 0;
2252: snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;
2254: PetscLogEventBegin(SNES_Solve,snes,0,0,0);
2255: (*snes->ops->solve)(snes);
2256: PetscLogEventEnd(SNES_Solve,snes,0,0,0);
2257: if (snes->domainerror){
2258: snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
2259: snes->domainerror = PETSC_FALSE;
2260: }
2262: if (!snes->reason) {
2263: SETERRQ(PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");
2264: }
2265:
2266: PetscOptionsGetString(((PetscObject)snes)->prefix,"-snes_view",filename,PETSC_MAX_PATH_LEN,&flg);
2267: if (flg && !PetscPreLoadingOn) {
2268: PetscViewerASCIIOpen(((PetscObject)snes)->comm,filename,&viewer);
2269: SNESView(snes,viewer);
2270: PetscViewerDestroy(viewer);
2271: }
2273: flg = PETSC_FALSE;
2274: PetscOptionsGetTruth(((PetscObject)snes)->prefix,"-snes_test_local_min",&flg,PETSC_NULL);
2275: if (flg && !PetscPreLoadingOn) { SNESTestLocalMin(snes); }
2276: if (snes->printreason) {
2277: if (snes->reason > 0) {
2278: PetscPrintf(((PetscObject)snes)->comm,"Nonlinear solve converged due to %s\n",SNESConvergedReasons[snes->reason]);
2279: } else {
2280: PetscPrintf(((PetscObject)snes)->comm,"Nonlinear solve did not converge due to %s\n",SNESConvergedReasons[snes->reason]);
2281: }
2282: }
2284: return(0);
2285: }
2287: /* --------- Internal routines for SNES Package --------- */
2291: /*@C
2292: SNESSetType - Sets the method for the nonlinear solver.
2294: Collective on SNES
2296: Input Parameters:
2297: + snes - the SNES context
2298: - type - a known method
2300: Options Database Key:
2301: . -snes_type <type> - Sets the method; use -help for a list
2302: of available methods (for instance, ls or tr)
2304: Notes:
2305: See "petsc/include/petscsnes.h" for available methods (for instance)
2306: + SNESLS - Newton's method with line search
2307: (systems of nonlinear equations)
2308: . SNESTR - Newton's method with trust region
2309: (systems of nonlinear equations)
2311: Normally, it is best to use the SNESSetFromOptions() command and then
2312: set the SNES solver type from the options database rather than by using
2313: this routine. Using the options database provides the user with
2314: maximum flexibility in evaluating the many nonlinear solvers.
2315: The SNESSetType() routine is provided for those situations where it
2316: is necessary to set the nonlinear solver independently of the command
2317: line or options database. This might be the case, for example, when
2318: the choice of solver changes during the execution of the program,
2319: and the user's application is taking responsibility for choosing the
2320: appropriate method.
2322: Level: intermediate
2324: .keywords: SNES, set, type
2326: .seealso: SNESType, SNESCreate()
2328: @*/
2329: PetscErrorCode SNESSetType(SNES snes,const SNESType type)
2330: {
2331: PetscErrorCode ierr,(*r)(SNES);
2332: PetscTruth match;
2338: PetscTypeCompare((PetscObject)snes,type,&match);
2339: if (match) return(0);
2341: PetscFListFind(SNESList,((PetscObject)snes)->comm,type,(void (**)(void)) &r);
2342: if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested SNES type %s",type);
2343: /* Destroy the previous private SNES context */
2344: if (snes->ops->destroy) { (*(snes)->ops->destroy)(snes); }
2345: /* Reinitialize function pointers in SNESOps structure */
2346: snes->ops->setup = 0;
2347: snes->ops->solve = 0;
2348: snes->ops->view = 0;
2349: snes->ops->setfromoptions = 0;
2350: snes->ops->destroy = 0;
2351: /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
2352: snes->setupcalled = PETSC_FALSE;
2353: (*r)(snes);
2354: PetscObjectChangeTypeName((PetscObject)snes,type);
2355: return(0);
2356: }
2359: /* --------------------------------------------------------------------- */
2362: /*@
2363: SNESRegisterDestroy - Frees the list of nonlinear solvers that were
2364: registered by SNESRegisterDynamic().
2366: Not Collective
2368: Level: advanced
2370: .keywords: SNES, nonlinear, register, destroy
2372: .seealso: SNESRegisterAll(), SNESRegisterAll()
2373: @*/
2374: PetscErrorCode SNESRegisterDestroy(void)
2375: {
2379: PetscFListDestroy(&SNESList);
2380: SNESRegisterAllCalled = PETSC_FALSE;
2381: return(0);
2382: }
2386: /*@C
2387: SNESGetType - Gets the SNES method type and name (as a string).
2389: Not Collective
2391: Input Parameter:
2392: . snes - nonlinear solver context
2394: Output Parameter:
2395: . type - SNES method (a character string)
2397: Level: intermediate
2399: .keywords: SNES, nonlinear, get, type, name
2400: @*/
2401: PetscErrorCode SNESGetType(SNES snes,const SNESType *type)
2402: {
2406: *type = ((PetscObject)snes)->type_name;
2407: return(0);
2408: }
2412: /*@
2413: SNESGetSolution - Returns the vector where the approximate solution is
2414: stored.
2416: Not Collective, but Vec is parallel if SNES is parallel
2418: Input Parameter:
2419: . snes - the SNES context
2421: Output Parameter:
2422: . x - the solution
2424: Level: intermediate
2426: .keywords: SNES, nonlinear, get, solution
2428: .seealso: SNESGetSolutionUpdate(), SNESGetFunction()
2429: @*/
2430: PetscErrorCode SNESGetSolution(SNES snes,Vec *x)
2431: {
2435: *x = snes->vec_sol;
2436: return(0);
2437: }
2441: /*@
2442: SNESGetSolutionUpdate - Returns the vector where the solution update is
2443: stored.
2445: Not Collective, but Vec is parallel if SNES is parallel
2447: Input Parameter:
2448: . snes - the SNES context
2450: Output Parameter:
2451: . x - the solution update
2453: Level: advanced
2455: .keywords: SNES, nonlinear, get, solution, update
2457: .seealso: SNESGetSolution(), SNESGetFunction()
2458: @*/
2459: PetscErrorCode SNESGetSolutionUpdate(SNES snes,Vec *x)
2460: {
2464: *x = snes->vec_sol_update;
2465: return(0);
2466: }
2470: /*@C
2471: SNESGetFunction - Returns the vector where the function is stored.
2473: Not Collective, but Vec is parallel if SNES is parallel
2475: Input Parameter:
2476: . snes - the SNES context
2478: Output Parameter:
2479: + r - the function (or PETSC_NULL)
2480: . func - the function (or PETSC_NULL)
2481: - ctx - the function context (or PETSC_NULL)
2483: Level: advanced
2485: .keywords: SNES, nonlinear, get, function
2487: .seealso: SNESSetFunction(), SNESGetSolution()
2488: @*/
2489: PetscErrorCode SNESGetFunction(SNES snes,Vec *r,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx)
2490: {
2493: if (r) *r = snes->vec_func;
2494: if (func) *func = snes->ops->computefunction;
2495: if (ctx) *ctx = snes->funP;
2496: return(0);
2497: }
2501: /*@C
2502: SNESSetOptionsPrefix - Sets the prefix used for searching for all
2503: SNES options in the database.
2505: Collective on SNES
2507: Input Parameter:
2508: + snes - the SNES context
2509: - prefix - the prefix to prepend to all option names
2511: Notes:
2512: A hyphen (-) must NOT be given at the beginning of the prefix name.
2513: The first character of all runtime options is AUTOMATICALLY the hyphen.
2515: Level: advanced
2517: .keywords: SNES, set, options, prefix, database
2519: .seealso: SNESSetFromOptions()
2520: @*/
2521: PetscErrorCode SNESSetOptionsPrefix(SNES snes,const char prefix[])
2522: {
2527: PetscObjectSetOptionsPrefix((PetscObject)snes,prefix);
2528: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
2529: KSPSetOptionsPrefix(snes->ksp,prefix);
2530: return(0);
2531: }
2535: /*@C
2536: SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
2537: SNES options in the database.
2539: Collective on SNES
2541: Input Parameters:
2542: + snes - the SNES context
2543: - prefix - the prefix to prepend to all option names
2545: Notes:
2546: A hyphen (-) must NOT be given at the beginning of the prefix name.
2547: The first character of all runtime options is AUTOMATICALLY the hyphen.
2549: Level: advanced
2551: .keywords: SNES, append, options, prefix, database
2553: .seealso: SNESGetOptionsPrefix()
2554: @*/
2555: PetscErrorCode SNESAppendOptionsPrefix(SNES snes,const char prefix[])
2556: {
2558:
2561: PetscObjectAppendOptionsPrefix((PetscObject)snes,prefix);
2562: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
2563: KSPAppendOptionsPrefix(snes->ksp,prefix);
2564: return(0);
2565: }
2569: /*@C
2570: SNESGetOptionsPrefix - Sets the prefix used for searching for all
2571: SNES options in the database.
2573: Not Collective
2575: Input Parameter:
2576: . snes - the SNES context
2578: Output Parameter:
2579: . prefix - pointer to the prefix string used
2581: Notes: On the fortran side, the user should pass in a string 'prefix' of
2582: sufficient length to hold the prefix.
2584: Level: advanced
2586: .keywords: SNES, get, options, prefix, database
2588: .seealso: SNESAppendOptionsPrefix()
2589: @*/
2590: PetscErrorCode SNESGetOptionsPrefix(SNES snes,const char *prefix[])
2591: {
2596: PetscObjectGetOptionsPrefix((PetscObject)snes,prefix);
2597: return(0);
2598: }
2603: /*@C
2604: SNESRegister - See SNESRegisterDynamic()
2606: Level: advanced
2607: @*/
2608: PetscErrorCode SNESRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(SNES))
2609: {
2610: char fullname[PETSC_MAX_PATH_LEN];
2614: PetscFListConcat(path,name,fullname);
2615: PetscFListAdd(&SNESList,sname,fullname,(void (*)(void))function);
2616: return(0);
2617: }
2621: PetscErrorCode SNESTestLocalMin(SNES snes)
2622: {
2624: PetscInt N,i,j;
2625: Vec u,uh,fh;
2626: PetscScalar value;
2627: PetscReal norm;
2630: SNESGetSolution(snes,&u);
2631: VecDuplicate(u,&uh);
2632: VecDuplicate(u,&fh);
2634: /* currently only works for sequential */
2635: PetscPrintf(PETSC_COMM_WORLD,"Testing FormFunction() for local min\n");
2636: VecGetSize(u,&N);
2637: for (i=0; i<N; i++) {
2638: VecCopy(u,uh);
2639: PetscPrintf(PETSC_COMM_WORLD,"i = %D\n",i);
2640: for (j=-10; j<11; j++) {
2641: value = PetscSign(j)*exp(PetscAbs(j)-10.0);
2642: VecSetValue(uh,i,value,ADD_VALUES);
2643: SNESComputeFunction(snes,uh,fh);
2644: VecNorm(fh,NORM_2,&norm);
2645: PetscPrintf(PETSC_COMM_WORLD," j norm %D %18.16e\n",j,norm);
2646: value = -value;
2647: VecSetValue(uh,i,value,ADD_VALUES);
2648: }
2649: }
2650: VecDestroy(uh);
2651: VecDestroy(fh);
2652: return(0);
2653: }
2657: /*@
2658: SNESKSPSetUseEW - Sets SNES use Eisenstat-Walker method for
2659: computing relative tolerance for linear solvers within an inexact
2660: Newton method.
2662: Collective on SNES
2664: Input Parameters:
2665: + snes - SNES context
2666: - flag - PETSC_TRUE or PETSC_FALSE
2668: Options Database:
2669: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
2670: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
2671: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
2672: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
2673: . -snes_ksp_ew_gamma <gamma> - Sets gamma
2674: . -snes_ksp_ew_alpha <alpha> - Sets alpha
2675: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
2676: - -snes_ksp_ew_threshold <threshold> - Sets threshold
2678: Notes:
2679: Currently, the default is to use a constant relative tolerance for
2680: the inner linear solvers. Alternatively, one can use the
2681: Eisenstat-Walker method, where the relative convergence tolerance
2682: is reset at each Newton iteration according progress of the nonlinear
2683: solver.
2685: Level: advanced
2687: Reference:
2688: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
2689: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
2691: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
2693: .seealso: SNESKSPGetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
2694: @*/
2695: PetscErrorCode SNESKSPSetUseEW(SNES snes,PetscTruth flag)
2696: {
2699: snes->ksp_ewconv = flag;
2700: return(0);
2701: }
2705: /*@
2706: SNESKSPGetUseEW - Gets if SNES is using Eisenstat-Walker method
2707: for computing relative tolerance for linear solvers within an
2708: inexact Newton method.
2710: Not Collective
2712: Input Parameter:
2713: . snes - SNES context
2715: Output Parameter:
2716: . flag - PETSC_TRUE or PETSC_FALSE
2718: Notes:
2719: Currently, the default is to use a constant relative tolerance for
2720: the inner linear solvers. Alternatively, one can use the
2721: Eisenstat-Walker method, where the relative convergence tolerance
2722: is reset at each Newton iteration according progress of the nonlinear
2723: solver.
2725: Level: advanced
2727: Reference:
2728: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
2729: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
2731: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
2733: .seealso: SNESKSPSetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
2734: @*/
2735: PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscTruth *flag)
2736: {
2740: *flag = snes->ksp_ewconv;
2741: return(0);
2742: }
2746: /*@
2747: SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
2748: convergence criteria for the linear solvers within an inexact
2749: Newton method.
2751: Collective on SNES
2752:
2753: Input Parameters:
2754: + snes - SNES context
2755: . version - version 1, 2 (default is 2) or 3
2756: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
2757: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
2758: . gamma - multiplicative factor for version 2 rtol computation
2759: (0 <= gamma2 <= 1)
2760: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
2761: . alpha2 - power for safeguard
2762: - threshold - threshold for imposing safeguard (0 < threshold < 1)
2764: Note:
2765: Version 3 was contributed by Luis Chacon, June 2006.
2767: Use PETSC_DEFAULT to retain the default for any of the parameters.
2769: Level: advanced
2771: Reference:
2772: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
2773: inexact Newton method", Utah State University Math. Stat. Dept. Res.
2774: Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
2776: .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
2778: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPGetParametersEW()
2779: @*/
2780: PetscErrorCode SNESKSPSetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,
2781: PetscReal gamma,PetscReal alpha,PetscReal alpha2,PetscReal threshold)
2782: {
2783: SNESKSPEW *kctx;
2786: kctx = (SNESKSPEW*)snes->kspconvctx;
2787: if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
2789: if (version != PETSC_DEFAULT) kctx->version = version;
2790: if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
2791: if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max;
2792: if (gamma != PETSC_DEFAULT) kctx->gamma = gamma;
2793: if (alpha != PETSC_DEFAULT) kctx->alpha = alpha;
2794: if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2;
2795: if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
2796:
2797: if (kctx->version < 1 || kctx->version > 3) {
2798: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 and 3 are supported: %D",kctx->version);
2799: }
2800: if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
2801: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %G",kctx->rtol_0);
2802: }
2803: if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
2804: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%G) < 1.0\n",kctx->rtol_max);
2805: }
2806: if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
2807: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%G) <= 1.0\n",kctx->gamma);
2808: }
2809: if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
2810: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%G) <= 2.0\n",kctx->alpha);
2811: }
2812: if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
2813: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%G) < 1.0\n",kctx->threshold);
2814: }
2815: return(0);
2816: }
2820: /*@
2821: SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
2822: convergence criteria for the linear solvers within an inexact
2823: Newton method.
2825: Not Collective
2826:
2827: Input Parameters:
2828: snes - SNES context
2830: Output Parameters:
2831: + version - version 1, 2 (default is 2) or 3
2832: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
2833: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
2834: . gamma - multiplicative factor for version 2 rtol computation
2835: (0 <= gamma2 <= 1)
2836: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
2837: . alpha2 - power for safeguard
2838: - threshold - threshold for imposing safeguard (0 < threshold < 1)
2840: Level: advanced
2842: .keywords: SNES, KSP, Eisenstat, Walker, get, parameters
2844: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPSetParametersEW()
2845: @*/
2846: PetscErrorCode SNESKSPGetParametersEW(SNES snes,PetscInt *version,PetscReal *rtol_0,PetscReal *rtol_max,
2847: PetscReal *gamma,PetscReal *alpha,PetscReal *alpha2,PetscReal *threshold)
2848: {
2849: SNESKSPEW *kctx;
2852: kctx = (SNESKSPEW*)snes->kspconvctx;
2853: if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
2854: if(version) *version = kctx->version;
2855: if(rtol_0) *rtol_0 = kctx->rtol_0;
2856: if(rtol_max) *rtol_max = kctx->rtol_max;
2857: if(gamma) *gamma = kctx->gamma;
2858: if(alpha) *alpha = kctx->alpha;
2859: if(alpha2) *alpha2 = kctx->alpha2;
2860: if(threshold) *threshold = kctx->threshold;
2861: return(0);
2862: }
2866: static PetscErrorCode SNESKSPEW_PreSolve(SNES snes, KSP ksp, Vec b, Vec x)
2867: {
2869: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
2870: PetscReal rtol=PETSC_DEFAULT,stol;
2873: if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists");
2874: if (!snes->iter) { /* first time in, so use the original user rtol */
2875: rtol = kctx->rtol_0;
2876: } else {
2877: if (kctx->version == 1) {
2878: rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
2879: if (rtol < 0.0) rtol = -rtol;
2880: stol = pow(kctx->rtol_last,kctx->alpha2);
2881: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
2882: } else if (kctx->version == 2) {
2883: rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
2884: stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
2885: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
2886: } else if (kctx->version == 3) {/* contributed by Luis Chacon, June 2006. */
2887: rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
2888: /* safeguard: avoid sharp decrease of rtol */
2889: stol = kctx->gamma*pow(kctx->rtol_last,kctx->alpha);
2890: stol = PetscMax(rtol,stol);
2891: rtol = PetscMin(kctx->rtol_0,stol);
2892: /* safeguard: avoid oversolving */
2893: stol = kctx->gamma*(snes->ttol)/snes->norm;
2894: stol = PetscMax(rtol,stol);
2895: rtol = PetscMin(kctx->rtol_0,stol);
2896: } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 or 3 are supported: %D",kctx->version);
2897: }
2898: /* safeguard: avoid rtol greater than one */
2899: rtol = PetscMin(rtol,kctx->rtol_max);
2900: KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
2901: PetscInfo3(snes,"iter %D, Eisenstat-Walker (version %D) KSP rtol=%G\n",snes->iter,kctx->version,rtol);
2902: return(0);
2903: }
2907: static PetscErrorCode SNESKSPEW_PostSolve(SNES snes, KSP ksp, Vec b, Vec x)
2908: {
2910: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
2911: PCSide pcside;
2912: Vec lres;
2915: if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists");
2916: KSPGetTolerances(ksp,&kctx->rtol_last,0,0,0);
2917: SNESGetFunctionNorm(snes,&kctx->norm_last);
2918: if (kctx->version == 1) {
2919: KSPGetPreconditionerSide(ksp,&pcside);
2920: if (pcside == PC_RIGHT) { /* XXX Should we also test KSP_UNPRECONDITIONED_NORM ? */
2921: /* KSP residual is true linear residual */
2922: KSPGetResidualNorm(ksp,&kctx->lresid_last);
2923: } else {
2924: /* KSP residual is preconditioned residual */
2925: /* compute true linear residual norm */
2926: VecDuplicate(b,&lres);
2927: MatMult(snes->jacobian,x,lres);
2928: VecAYPX(lres,-1.0,b);
2929: VecNorm(lres,NORM_2,&kctx->lresid_last);
2930: VecDestroy(lres);
2931: }
2932: }
2933: return(0);
2934: }
2938: PetscErrorCode SNES_KSPSolve(SNES snes, KSP ksp, Vec b, Vec x)
2939: {
2943: if (snes->ksp_ewconv) { SNESKSPEW_PreSolve(snes,ksp,b,x); }
2944: KSPSolve(ksp,b,x);
2945: if (snes->ksp_ewconv) { SNESKSPEW_PostSolve(snes,ksp,b,x); }
2946: return(0);
2947: }