Actual source code: snes.c
1: #define PETSCSNES_DLL
3: #include include/private/snesimpl.h
5: PetscTruth SNESRegisterAllCalled = PETSC_FALSE;
6: PetscFList SNESList = PETSC_NULL;
8: /* Logging support */
9: PetscCookie SNES_COOKIE = 0;
10: PetscEvent SNES_Solve = 0, SNES_LineSearch = 0, SNES_FunctionEval = 0, SNES_JacobianEval = 0;
14: /*@C
15: SNESView - Prints the SNES data structure.
17: Collective on SNES
19: Input Parameters:
20: + SNES - the SNES context
21: - viewer - visualization context
23: Options Database Key:
24: . -snes_view - Calls SNESView() at end of SNESSolve()
26: Notes:
27: The available visualization contexts include
28: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
29: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
30: output where only the first processor opens
31: the file. All other processors send their
32: data to the first processor to print.
34: The user can open an alternative visualization context with
35: PetscViewerASCIIOpen() - output to a specified file.
37: Level: beginner
39: .keywords: SNES, view
41: .seealso: PetscViewerASCIIOpen()
42: @*/
43: PetscErrorCode SNESView(SNES snes,PetscViewer viewer)
44: {
45: SNESKSPEW *kctx;
46: PetscErrorCode ierr;
47: KSP ksp;
48: SNESType type;
49: PetscTruth iascii,isstring;
53: if (!viewer) {
54: PetscViewerASCIIGetStdout(((PetscObject)snes)->comm,&viewer);
55: }
59: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
60: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
61: if (iascii) {
62: if (((PetscObject)snes)->prefix) {
63: PetscViewerASCIIPrintf(viewer,"SNES Object:(%s)\n",((PetscObject)snes)->prefix);
64: } else {
65: PetscViewerASCIIPrintf(viewer,"SNES Object:\n");
66: }
67: SNESGetType(snes,&type);
68: if (type) {
69: PetscViewerASCIIPrintf(viewer," type: %s\n",type);
70: } else {
71: PetscViewerASCIIPrintf(viewer," type: not set yet\n");
72: }
73: if (snes->ops->view) {
74: PetscViewerASCIIPushTab(viewer);
75: (*snes->ops->view)(snes,viewer);
76: PetscViewerASCIIPopTab(viewer);
77: }
78: PetscViewerASCIIPrintf(viewer," maximum iterations=%D, maximum function evaluations=%D\n",snes->max_its,snes->max_funcs);
79: PetscViewerASCIIPrintf(viewer," tolerances: relative=%G, absolute=%G, solution=%G\n",
80: snes->rtol,snes->abstol,snes->xtol);
81: PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",snes->linear_its);
82: PetscViewerASCIIPrintf(viewer," total number of function evaluations=%D\n",snes->nfuncs);
83: if (snes->ksp_ewconv) {
84: kctx = (SNESKSPEW *)snes->kspconvctx;
85: if (kctx) {
86: PetscViewerASCIIPrintf(viewer," Eisenstat-Walker computation of KSP relative tolerance (version %D)\n",kctx->version);
87: PetscViewerASCIIPrintf(viewer," rtol_0=%G, rtol_max=%G, threshold=%G\n",kctx->rtol_0,kctx->rtol_max,kctx->threshold);
88: PetscViewerASCIIPrintf(viewer," gamma=%G, alpha=%G, alpha2=%G\n",kctx->gamma,kctx->alpha,kctx->alpha2);
89: }
90: }
91: } else if (isstring) {
92: SNESGetType(snes,&type);
93: PetscViewerStringSPrintf(viewer," %-3.3s",type);
94: }
95: SNESGetKSP(snes,&ksp);
96: PetscViewerASCIIPushTab(viewer);
97: KSPView(ksp,viewer);
98: PetscViewerASCIIPopTab(viewer);
99: return(0);
100: }
102: /*
103: We retain a list of functions that also take SNES command
104: line options. These are called at the end SNESSetFromOptions()
105: */
106: #define MAXSETFROMOPTIONS 5
107: static PetscInt numberofsetfromoptions;
108: static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
112: /*@C
113: SNESAddOptionsChecker - Adds an additional function to check for SNES options.
115: Not Collective
117: Input Parameter:
118: . snescheck - function that checks for options
120: Level: developer
122: .seealso: SNESSetFromOptions()
123: @*/
124: PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES))
125: {
127: if (numberofsetfromoptions >= MAXSETFROMOPTIONS) {
128: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %D allowed", MAXSETFROMOPTIONS);
129: }
130: othersetfromoptions[numberofsetfromoptions++] = snescheck;
131: return(0);
132: }
136: /*@
137: SNESSetFromOptions - Sets various SNES and KSP parameters from user options.
139: Collective on SNES
141: Input Parameter:
142: . snes - the SNES context
144: Options Database Keys:
145: + -snes_type <type> - ls, tr, umls, umtr, test
146: . -snes_stol - convergence tolerance in terms of the norm
147: of the change in the solution between steps
148: . -snes_atol <abstol> - absolute tolerance of residual norm
149: . -snes_rtol <rtol> - relative decrease in tolerance norm from initial
150: . -snes_max_it <max_it> - maximum number of iterations
151: . -snes_max_funcs <max_funcs> - maximum number of function evaluations
152: . -snes_max_fail <max_fail> - maximum number of failures
153: . -snes_trtol <trtol> - trust region tolerance
154: . -snes_no_convergence_test - skip convergence test in nonlinear
155: solver; hence iterations will continue until max_it
156: or some other criterion is reached. Saves expense
157: of convergence test
158: . -snes_monitor <optional filename> - prints residual norm at each iteration. if no
159: filename given prints to stdout
160: . -snes_monitor_solution - plots solution at each iteration
161: . -snes_monitor_residual - plots residual (not its norm) at each iteration
162: . -snes_monitor_solution_update - plots update to solution at each iteration
163: . -snes_monitor_draw - plots residual norm at each iteration
164: . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
165: . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration
166: - -snes_converged_reason - print the reason for convergence/divergence after each solve
168: Options Database for Eisenstat-Walker method:
169: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
170: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
171: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
172: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
173: . -snes_ksp_ew_gamma <gamma> - Sets gamma
174: . -snes_ksp_ew_alpha <alpha> - Sets alpha
175: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
176: - -snes_ksp_ew_threshold <threshold> - Sets threshold
178: Notes:
179: To see all options, run your program with the -help option or consult
180: the users manual.
182: Level: beginner
184: .keywords: SNES, nonlinear, set, options, database
186: .seealso: SNESSetOptionsPrefix()
187: @*/
188: PetscErrorCode SNESSetFromOptions(SNES snes)
189: {
190: PetscTruth flg;
191: PetscInt i,indx;
192: const char *deft = SNESLS;
193: const char *convtests[] = {"default","skip"};
194: SNESKSPEW *kctx = NULL;
195: char type[256], monfilename[PETSC_MAX_PATH_LEN];
196: PetscViewerASCIIMonitor monviewer;
197: PetscErrorCode ierr;
202: PetscOptionsBegin(((PetscObject)snes)->comm,((PetscObject)snes)->prefix,"Nonlinear solver (SNES) options","SNES");
203: if (!SNESRegisterAllCalled) {SNESRegisterAll(PETSC_NULL);}
204: if (((PetscObject)snes)->type_name) { deft = ((PetscObject)snes)->type_name; }
205: PetscOptionsList("-snes_type","Nonlinear solver method","SNESSetType",SNESList,deft,type,256,&flg);
206: if (flg) {
207: SNESSetType(snes,type);
208: } else if (!((PetscObject)snes)->type_name) {
209: SNESSetType(snes,deft);
210: }
211: PetscOptionsName("-snes_view","Print detailed information on solver used","SNESView",0);
213: PetscOptionsReal("-snes_stol","Stop if step length less then","SNESSetTolerances",snes->xtol,&snes->xtol,0);
214: PetscOptionsReal("-snes_atol","Stop if function norm less then","SNESSetTolerances",snes->abstol,&snes->abstol,0);
216: PetscOptionsReal("-snes_rtol","Stop if decrease in function norm less then","SNESSetTolerances",snes->rtol,&snes->rtol,0);
217: PetscOptionsInt("-snes_max_it","Maximum iterations","SNESSetTolerances",snes->max_its,&snes->max_its,PETSC_NULL);
218: PetscOptionsInt("-snes_max_funcs","Maximum function evaluations","SNESSetTolerances",snes->max_funcs,&snes->max_funcs,PETSC_NULL);
219: PetscOptionsInt("-snes_max_fail","Maximum failures","SNESSetTolerances",snes->maxFailures,&snes->maxFailures,PETSC_NULL);
221: PetscOptionsEList("-snes_convergence_test","Convergence test","SNESSetConvergenceTest",convtests,2,"default",&indx,&flg);
222: if (flg) {
223: switch (indx) {
224: case 0: SNESSetConvergenceTest(snes,SNESDefaultConverged,PETSC_NULL); break;
225: case 1: SNESSetConvergenceTest(snes,SNESSkipConverged,PETSC_NULL); break;
226: }
227: }
229: PetscOptionsName("-snes_converged_reason","Print reason for converged or diverged","SNESSolve",&flg);
230: if (flg) {
231: snes->printreason = PETSC_TRUE;
232: }
234: kctx = (SNESKSPEW *)snes->kspconvctx;
236: PetscOptionsTruth("-snes_ksp_ew","Use Eisentat-Walker linear system convergence test","SNESKSPSetUseEW",snes->ksp_ewconv,&snes->ksp_ewconv,PETSC_NULL);
238: PetscOptionsInt("-snes_ksp_ew_version","Version 1, 2 or 3","SNESKSPSetParametersEW",kctx->version,&kctx->version,0);
239: PetscOptionsReal("-snes_ksp_ew_rtol0","0 <= rtol0 < 1","SNESKSPSetParametersEW",kctx->rtol_0,&kctx->rtol_0,0);
240: PetscOptionsReal("-snes_ksp_ew_rtolmax","0 <= rtolmax < 1","SNESKSPSetParametersEW",kctx->rtol_max,&kctx->rtol_max,0);
241: PetscOptionsReal("-snes_ksp_ew_gamma","0 <= gamma <= 1","SNESKSPSetParametersEW",kctx->gamma,&kctx->gamma,0);
242: PetscOptionsReal("-snes_ksp_ew_alpha","1 < alpha <= 2","SNESKSPSetParametersEW",kctx->alpha,&kctx->alpha,0);
243: PetscOptionsReal("-snes_ksp_ew_alpha2","alpha2","SNESKSPSetParametersEW",kctx->alpha2,&kctx->alpha2,0);
244: PetscOptionsReal("-snes_ksp_ew_threshold","0 < threshold < 1","SNESKSPSetParametersEW",kctx->threshold,&kctx->threshold,0);
246: PetscOptionsName("-snes_monitor_cancel","Remove all monitors","SNESMonitorCancel",&flg);
247: if (flg) {SNESMonitorCancel(snes);}
249: PetscOptionsString("-snes_monitor","Monitor norm of function","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
250: if (flg) {
251: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,monfilename,0,&monviewer);
252: SNESMonitorSet(snes,SNESMonitorDefault,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
253: }
255: PetscOptionsString("-snes_ratiomonitor","Monitor ratios of norms of function","SNESMonitorSetRatio","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
256: if (flg) {
257: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,monfilename,0,&monviewer);
258: SNESMonitorSetRatio(snes,monviewer);
259: }
261: PetscOptionsString("-snes_monitor_short","Monitor norm of function (fewer digits)","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
262: if (flg) {
263: PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,monfilename,0,&monviewer);
264: SNESMonitorSet(snes,SNESMonitorDefaultShort,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
265: }
267: PetscOptionsName("-snes_monitor_solution","Plot solution at each iteration","SNESMonitorSolution",&flg);
268: if (flg) {SNESMonitorSet(snes,SNESMonitorSolution,0,0);}
269: PetscOptionsName("-snes_monitor_solution_update","Plot correction at each iteration","SNESMonitorSolutionUpdate",&flg);
270: if (flg) {SNESMonitorSet(snes,SNESMonitorSolutionUpdate,0,0);}
271: PetscOptionsName("-snes_monitor_residual","Plot residual at each iteration","SNESMonitorResidual",&flg);
272: if (flg) {SNESMonitorSet(snes,SNESMonitorResidual,0,0);}
273: PetscOptionsName("-snes_monitor_draw","Plot function norm at each iteration","SNESMonitorLG",&flg);
274: if (flg) {SNESMonitorSet(snes,SNESMonitorLG,PETSC_NULL,PETSC_NULL);}
276: PetscOptionsName("-snes_fd","Use finite differences (slow) to compute Jacobian","SNESDefaultComputeJacobian",&flg);
277: if (flg) {
278: SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESDefaultComputeJacobian,snes->funP);
279: PetscInfo(snes,"Setting default finite difference Jacobian matrix\n");
280: }
282: for(i = 0; i < numberofsetfromoptions; i++) {
283: (*othersetfromoptions[i])(snes);
284: }
286: if (snes->ops->setfromoptions) {
287: (*snes->ops->setfromoptions)(snes);
288: }
289: PetscOptionsEnd();
291: KSPSetFromOptions(snes->ksp);
293: return(0);
294: }
299: /*@
300: SNESSetApplicationContext - Sets the optional user-defined context for
301: the nonlinear solvers.
303: Collective on SNES
305: Input Parameters:
306: + snes - the SNES context
307: - usrP - optional user context
309: Level: intermediate
311: .keywords: SNES, nonlinear, set, application, context
313: .seealso: SNESGetApplicationContext()
314: @*/
315: PetscErrorCode SNESSetApplicationContext(SNES snes,void *usrP)
316: {
319: snes->user = usrP;
320: return(0);
321: }
325: /*@C
326: SNESGetApplicationContext - Gets the user-defined context for the
327: nonlinear solvers.
329: Not Collective
331: Input Parameter:
332: . snes - SNES context
334: Output Parameter:
335: . usrP - user context
337: Level: intermediate
339: .keywords: SNES, nonlinear, get, application, context
341: .seealso: SNESSetApplicationContext()
342: @*/
343: PetscErrorCode SNESGetApplicationContext(SNES snes,void **usrP)
344: {
347: *usrP = snes->user;
348: return(0);
349: }
353: /*@
354: SNESGetIterationNumber - Gets the number of nonlinear iterations completed
355: at this time.
357: Not Collective
359: Input Parameter:
360: . snes - SNES context
362: Output Parameter:
363: . iter - iteration number
365: Notes:
366: For example, during the computation of iteration 2 this would return 1.
368: This is useful for using lagged Jacobians (where one does not recompute the
369: Jacobian at each SNES iteration). For example, the code
370: .vb
371: SNESGetIterationNumber(snes,&it);
372: if (!(it % 2)) {
373: [compute Jacobian here]
374: }
375: .ve
376: can be used in your ComputeJacobian() function to cause the Jacobian to be
377: recomputed every second SNES iteration.
379: Level: intermediate
381: .keywords: SNES, nonlinear, get, iteration, number,
383: .seealso: SNESGetFunctionNorm(), SNESGetLinearSolveIterations()
384: @*/
385: PetscErrorCode SNESGetIterationNumber(SNES snes,PetscInt* iter)
386: {
390: *iter = snes->iter;
391: return(0);
392: }
396: /*@
397: SNESGetFunctionNorm - Gets the norm of the current function that was set
398: with SNESSSetFunction().
400: Collective on SNES
402: Input Parameter:
403: . snes - SNES context
405: Output Parameter:
406: . fnorm - 2-norm of function
408: Level: intermediate
410: .keywords: SNES, nonlinear, get, function, norm
412: .seealso: SNESGetFunction(), SNESGetIterationNumber(), SNESGetLinearSolveIterations()
413: @*/
414: PetscErrorCode SNESGetFunctionNorm(SNES snes,PetscReal *fnorm)
415: {
419: *fnorm = snes->norm;
420: return(0);
421: }
425: /*@
426: SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
427: attempted by the nonlinear solver.
429: Not Collective
431: Input Parameter:
432: . snes - SNES context
434: Output Parameter:
435: . nfails - number of unsuccessful steps attempted
437: Notes:
438: This counter is reset to zero for each successive call to SNESSolve().
440: Level: intermediate
442: .keywords: SNES, nonlinear, get, number, unsuccessful, steps
444: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolverIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
445: SNESSetMaxNonlinearStepFailures(), SNESGetMaxNonlinearStepFailures()
446: @*/
447: PetscErrorCode SNESGetNonlinearStepFailures(SNES snes,PetscInt* nfails)
448: {
452: *nfails = snes->numFailures;
453: return(0);
454: }
458: /*@
459: SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
460: attempted by the nonlinear solver before it gives up.
462: Not Collective
464: Input Parameters:
465: + snes - SNES context
466: - maxFails - maximum of unsuccessful steps
468: Level: intermediate
470: .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps
472: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolverIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
473: SNESGetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
474: @*/
475: PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
476: {
479: snes->maxFailures = maxFails;
480: return(0);
481: }
485: /*@
486: SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
487: attempted by the nonlinear solver before it gives up.
489: Not Collective
491: Input Parameter:
492: . snes - SNES context
494: Output Parameter:
495: . maxFails - maximum of unsuccessful steps
497: Level: intermediate
499: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
501: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolverIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
502: SNESSetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
503:
504: @*/
505: PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
506: {
510: *maxFails = snes->maxFailures;
511: return(0);
512: }
516: /*@
517: SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
518: done by SNES.
520: Not Collective
522: Input Parameter:
523: . snes - SNES context
525: Output Parameter:
526: . nfuncs - number of evaluations
528: Level: intermediate
530: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
532: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolverIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures()
533: @*/
534: PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
535: {
539: *nfuncs = snes->nfuncs;
540: return(0);
541: }
545: /*@
546: SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
547: linear solvers.
549: Not Collective
551: Input Parameter:
552: . snes - SNES context
554: Output Parameter:
555: . nfails - number of failed solves
557: Notes:
558: This counter is reset to zero for each successive call to SNESSolve().
560: Level: intermediate
562: .keywords: SNES, nonlinear, get, number, unsuccessful, steps
564: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolverIterations(), SNESSetMaxLinearSolveFailures()
565: @*/
566: PetscErrorCode SNESGetLinearSolveFailures(SNES snes,PetscInt* nfails)
567: {
571: *nfails = snes->numLinearSolveFailures;
572: return(0);
573: }
577: /*@
578: SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
579: allowed before SNES returns with a diverged reason of SNES_DIVERGED_LINEAR_SOLVE
581: Collective on SNES
583: Input Parameters:
584: + snes - SNES context
585: - maxFails - maximum allowed linear solve failures
587: Level: intermediate
589: Notes: By default this is 1; that is SNES returns on the first failed linear solve
591: .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps
593: .seealso: SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations()
594: @*/
595: PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
596: {
599: snes->maxLinearSolveFailures = maxFails;
600: return(0);
601: }
605: /*@
606: SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
607: are allowed before SNES terminates
609: Not Collective
611: Input Parameter:
612: . snes - SNES context
614: Output Parameter:
615: . maxFails - maximum of unsuccessful solves allowed
617: Level: intermediate
619: Notes: By default this is 1; that is SNES returns on the first failed linear solve
621: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
623: .seealso: SNESGetLinearSolveFailures(), SNESGetLinearSolverIterations(), SNESSetMaxLinearSolveFailures(),
624: @*/
625: PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
626: {
630: *maxFails = snes->maxLinearSolveFailures;
631: return(0);
632: }
636: /*@
637: SNESGetLinearSolveIterations - Gets the total number of linear iterations
638: used by the nonlinear solver.
640: Not Collective
642: Input Parameter:
643: . snes - SNES context
645: Output Parameter:
646: . lits - number of linear iterations
648: Notes:
649: This counter is reset to zero for each successive call to SNESSolve().
651: Level: intermediate
653: .keywords: SNES, nonlinear, get, number, linear, iterations
655: .seealso: SNESGetIterationNumber(), SNESGetFunctionNorm()S, NESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures()
656: @*/
657: PetscErrorCode SNESGetLinearSolveIterations(SNES snes,PetscInt* lits)
658: {
662: *lits = snes->linear_its;
663: return(0);
664: }
668: /*@
669: SNESGetKSP - Returns the KSP context for a SNES solver.
671: Not Collective, but if SNES object is parallel, then KSP object is parallel
673: Input Parameter:
674: . snes - the SNES context
676: Output Parameter:
677: . ksp - the KSP context
679: Notes:
680: The user can then directly manipulate the KSP context to set various
681: options, etc. Likewise, the user can then extract and manipulate the
682: PC contexts as well.
684: Level: beginner
686: .keywords: SNES, nonlinear, get, KSP, context
688: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
689: @*/
690: PetscErrorCode SNESGetKSP(SNES snes,KSP *ksp)
691: {
695: *ksp = snes->ksp;
696: return(0);
697: }
701: /*@
702: SNESSetKSP - Sets a KSP context for the SNES object to use
704: Not Collective, but the SNES and KSP objects must live on the same MPI_Comm
706: Input Parameters:
707: + snes - the SNES context
708: - ksp - the KSP context
710: Notes:
711: The SNES object already has its KSP object, you can obtain with SNESGetKSP()
712: so this routine is rarely needed.
714: The KSP object that is already in the SNES object has its reference count
715: decreased by one.
717: Level: developer
719: .keywords: SNES, nonlinear, get, KSP, context
721: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
722: @*/
723: PetscErrorCode SNESSetKSP(SNES snes,KSP ksp)
724: {
731: PetscObjectReference((PetscObject)ksp);
732: if (snes->ksp) {PetscObjectDereference((PetscObject)snes->ksp);}
733: snes->ksp = ksp;
734: return(0);
735: }
737: #if 0
740: static PetscErrorCode SNESPublish_Petsc(PetscObject obj)
741: {
743: return(0);
744: }
745: #endif
747: /* -----------------------------------------------------------*/
750: /*@
751: SNESCreate - Creates a nonlinear solver context.
753: Collective on MPI_Comm
755: Input Parameters:
756: . comm - MPI communicator
758: Output Parameter:
759: . outsnes - the new SNES context
761: Options Database Keys:
762: + -snes_mf - Activates default matrix-free Jacobian-vector products,
763: and no preconditioning matrix
764: . -snes_mf_operator - Activates default matrix-free Jacobian-vector
765: products, and a user-provided preconditioning matrix
766: as set by SNESSetJacobian()
767: - -snes_fd - Uses (slow!) finite differences to compute Jacobian
769: Level: beginner
771: .keywords: SNES, nonlinear, create, context
773: .seealso: SNESSolve(), SNESDestroy(), SNES
774: @*/
775: PetscErrorCode SNESCreate(MPI_Comm comm,SNES *outsnes)
776: {
777: PetscErrorCode ierr;
778: SNES snes;
779: SNESKSPEW *kctx;
783: *outsnes = PETSC_NULL;
784: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
785: SNESInitializePackage(PETSC_NULL);
786: #endif
788: PetscHeaderCreate(snes,_p_SNES,struct _SNESOps,SNES_COOKIE,0,"SNES",comm,SNESDestroy,SNESView);
790: snes->ops->converged = SNESDefaultConverged;
791: snes->max_its = 50;
792: snes->max_funcs = 10000;
793: snes->norm = 0.0;
794: snes->rtol = 1.e-8;
795: snes->ttol = 0.0;
796: snes->abstol = 1.e-50;
797: snes->xtol = 1.e-8;
798: snes->deltatol = 1.e-12;
799: snes->nfuncs = 0;
800: snes->numFailures = 0;
801: snes->maxFailures = 1;
802: snes->linear_its = 0;
803: snes->numbermonitors = 0;
804: snes->data = 0;
805: snes->setupcalled = PETSC_FALSE;
806: snes->ksp_ewconv = PETSC_FALSE;
807: snes->vwork = 0;
808: snes->nwork = 0;
809: snes->conv_hist_len = 0;
810: snes->conv_hist_max = 0;
811: snes->conv_hist = PETSC_NULL;
812: snes->conv_hist_its = PETSC_NULL;
813: snes->conv_hist_reset = PETSC_TRUE;
814: snes->reason = SNES_CONVERGED_ITERATING;
816: snes->numLinearSolveFailures = 0;
817: snes->maxLinearSolveFailures = 1;
819: /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
820: PetscNewLog(snes,SNESKSPEW,&kctx);
821: snes->kspconvctx = (void*)kctx;
822: kctx->version = 2;
823: kctx->rtol_0 = .3; /* Eisenstat and Walker suggest rtol_0=.5, but
824: this was too large for some test cases */
825: kctx->rtol_last = 0;
826: kctx->rtol_max = .9;
827: kctx->gamma = 1.0;
828: kctx->alpha = .5*(1.0 + sqrt(5.0));
829: kctx->alpha2 = kctx->alpha;
830: kctx->threshold = .1;
831: kctx->lresid_last = 0;
832: kctx->norm_last = 0;
834: KSPCreate(comm,&snes->ksp);
835: PetscLogObjectParent(snes,snes->ksp);
837: *outsnes = snes;
838: PetscPublishAll(snes);
839: return(0);
840: }
844: /*@C
845: SNESSetFunction - Sets the function evaluation routine and function
846: vector for use by the SNES routines in solving systems of nonlinear
847: equations.
849: Collective on SNES
851: Input Parameters:
852: + snes - the SNES context
853: . r - vector to store function value
854: . func - function evaluation routine
855: - ctx - [optional] user-defined context for private data for the
856: function evaluation routine (may be PETSC_NULL)
858: Calling sequence of func:
859: $ func (SNES snes,Vec x,Vec f,void *ctx);
861: . f - function vector
862: - ctx - optional user-defined function context
864: Notes:
865: The Newton-like methods typically solve linear systems of the form
866: $ f'(x) x = -f(x),
867: where f'(x) denotes the Jacobian matrix and f(x) is the function.
869: Level: beginner
871: .keywords: SNES, nonlinear, set, function
873: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian()
874: @*/
875: PetscErrorCode SNESSetFunction(SNES snes,Vec r,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx)
876: {
882: PetscObjectReference((PetscObject)r);
883: if (snes->vec_func) { VecDestroy(snes->vec_func); }
884: snes->ops->computefunction = func;
885: snes->vec_func = r;
886: snes->funP = ctx;
887: return(0);
888: }
890: /* --------------------------------------------------------------- */
893: /*@C
894: SNESGetRhs - Gets the vector for solving F(x) = rhs. If rhs is not set
895: it assumes a zero right hand side.
897: Collective on SNES
899: Input Parameter:
900: . snes - the SNES context
902: Output Parameter:
903: . rhs - the right hand side vector or PETSC_NULL if the right hand side vector is null
905: Level: intermediate
907: .keywords: SNES, nonlinear, get, function, right hand side
909: .seealso: SNESGetSolution(), SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
910: @*/
911: PetscErrorCode SNESGetRhs(SNES snes,Vec *rhs)
912: {
916: *rhs = snes->vec_rhs;
917: return(0);
918: }
922: /*@
923: SNESComputeFunction - Calls the function that has been set with
924: SNESSetFunction().
926: Collective on SNES
928: Input Parameters:
929: + snes - the SNES context
930: - x - input vector
932: Output Parameter:
933: . y - function vector, as set by SNESSetFunction()
935: Notes:
936: SNESComputeFunction() is typically used within nonlinear solvers
937: implementations, so most users would not generally call this routine
938: themselves.
940: Level: developer
942: .keywords: SNES, nonlinear, compute, function
944: .seealso: SNESSetFunction(), SNESGetFunction()
945: @*/
946: PetscErrorCode SNESComputeFunction(SNES snes,Vec x,Vec y)
947: {
958: if (snes->ops->computefunction) {
959: PetscStackPush("SNES user function");
960: CHKMEMQ;
961: (*snes->ops->computefunction)(snes,x,y,snes->funP);
962: CHKMEMQ;
963: PetscStackPop;
964: if (PetscExceptionValue(ierr)) {
966: }
967:
968: } else if (snes->vec_rhs) {
969: MatMult(snes->jacobian, x, y);
970: } else {
971: SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() before SNESComputeFunction(), likely called from SNESSolve().");
972: }
973: if (snes->vec_rhs) {
974: VecAXPY(y,-1.0,snes->vec_rhs);
975: }
976: snes->nfuncs++;
978: return(0);
979: }
983: /*@
984: SNESComputeJacobian - Computes the Jacobian matrix that has been
985: set with SNESSetJacobian().
987: Collective on SNES and Mat
989: Input Parameters:
990: + snes - the SNES context
991: - x - input vector
993: Output Parameters:
994: + A - Jacobian matrix
995: . B - optional preconditioning matrix
996: - flag - flag indicating matrix structure (one of, SAME_NONZERO_PATTERN,DIFFERENT_NONZERO_PATTERN,SAME_PRECONDITIONER)
998: Notes:
999: Most users should not need to explicitly call this routine, as it
1000: is used internally within the nonlinear solvers.
1002: See KSPSetOperators() for important information about setting the
1003: flag parameter.
1005: Level: developer
1007: .keywords: SNES, compute, Jacobian, matrix
1009: .seealso: SNESSetJacobian(), KSPSetOperators(), MatStructure
1010: @*/
1011: PetscErrorCode SNESComputeJacobian(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *flg)
1012: {
1020: if (!snes->ops->computejacobian) return(0);
1022: *flg = DIFFERENT_NONZERO_PATTERN;
1023: PetscStackPush("SNES user Jacobian function");
1024: CHKMEMQ;
1025: (*snes->ops->computejacobian)(snes,X,A,B,flg,snes->jacP);
1026: CHKMEMQ;
1027: PetscStackPop;
1029: /* make sure user returned a correct Jacobian and preconditioner */
1032: return(0);
1033: }
1037: /*@C
1038: SNESSetJacobian - Sets the function to compute Jacobian as well as the
1039: location to store the matrix.
1041: Collective on SNES and Mat
1043: Input Parameters:
1044: + snes - the SNES context
1045: . A - Jacobian matrix
1046: . B - preconditioner matrix (usually same as the Jacobian)
1047: . func - Jacobian evaluation routine
1048: - ctx - [optional] user-defined context for private data for the
1049: Jacobian evaluation routine (may be PETSC_NULL)
1051: Calling sequence of func:
1052: $ func (SNES snes,Vec x,Mat *A,Mat *B,int *flag,void *ctx);
1054: + x - input vector
1055: . A - Jacobian matrix
1056: . B - preconditioner matrix, usually the same as A
1057: . flag - flag indicating information about the preconditioner matrix
1058: structure (same as flag in KSPSetOperators()), one of SAME_NONZERO_PATTERN,DIFFERENT_NONZERO_PATTERN,SAME_PRECONDITIONER
1059: - ctx - [optional] user-defined Jacobian context
1061: Notes:
1062: See KSPSetOperators() for important information about setting the flag
1063: output parameter in the routine func(). Be sure to read this information!
1065: The routine func() takes Mat * as the matrix arguments rather than Mat.
1066: This allows the Jacobian evaluation routine to replace A and/or B with a
1067: completely new new matrix structure (not just different matrix elements)
1068: when appropriate, for instance, if the nonzero structure is changing
1069: throughout the global iterations.
1071: Level: beginner
1073: .keywords: SNES, nonlinear, set, Jacobian, matrix
1075: .seealso: KSPSetOperators(), SNESSetFunction(), MatMFFDComputeJacobian(), SNESDefaultComputeJacobianColor(), MatStructure
1076: @*/
1077: PetscErrorCode SNESSetJacobian(SNES snes,Mat A,Mat B,PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
1078: {
1087: if (func) snes->ops->computejacobian = func;
1088: if (ctx) snes->jacP = ctx;
1089: if (A) {
1090: PetscObjectReference((PetscObject)A);
1091: if (snes->jacobian) {MatDestroy(snes->jacobian);}
1092: snes->jacobian = A;
1093: }
1094: if (B) {
1095: PetscObjectReference((PetscObject)B);
1096: if (snes->jacobian_pre) {MatDestroy(snes->jacobian_pre);}
1097: snes->jacobian_pre = B;
1098: }
1099: return(0);
1100: }
1104: /*@C
1105: SNESGetJacobian - Returns the Jacobian matrix and optionally the user
1106: provided context for evaluating the Jacobian.
1108: Not Collective, but Mat object will be parallel if SNES object is
1110: Input Parameter:
1111: . snes - the nonlinear solver context
1113: Output Parameters:
1114: + A - location to stash Jacobian matrix (or PETSC_NULL)
1115: . B - location to stash preconditioner matrix (or PETSC_NULL)
1116: . func - location to put Jacobian function (or PETSC_NULL)
1117: - ctx - location to stash Jacobian ctx (or PETSC_NULL)
1119: Level: advanced
1121: .seealso: SNESSetJacobian(), SNESComputeJacobian()
1122: @*/
1123: PetscErrorCode SNESGetJacobian(SNES snes,Mat *A,Mat *B,PetscErrorCode (**func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
1124: {
1127: if (A) *A = snes->jacobian;
1128: if (B) *B = snes->jacobian_pre;
1129: if (func) *func = snes->ops->computejacobian;
1130: if (ctx) *ctx = snes->jacP;
1131: return(0);
1132: }
1134: /* ----- Routines to initialize and destroy a nonlinear solver ---- */
1135: EXTERN PetscErrorCode SNESDefaultMatrixFreeCreate2(SNES,Vec,Mat*);
1139: /*@
1140: SNESSetUp - Sets up the internal data structures for the later use
1141: of a nonlinear solver.
1143: Collective on SNES
1145: Input Parameters:
1146: . snes - the SNES context
1148: Notes:
1149: For basic use of the SNES solvers the user need not explicitly call
1150: SNESSetUp(), since these actions will automatically occur during
1151: the call to SNESSolve(). However, if one wishes to control this
1152: phase separately, SNESSetUp() should be called after SNESCreate()
1153: and optional routines of the form SNESSetXXX(), but before SNESSolve().
1155: Level: advanced
1157: .keywords: SNES, nonlinear, setup
1159: .seealso: SNESCreate(), SNESSolve(), SNESDestroy()
1160: @*/
1161: PetscErrorCode SNESSetUp(SNES snes)
1162: {
1164: PetscTruth flg;
1168: if (snes->setupcalled) return(0);
1170: if (!((PetscObject)snes)->type_name) {
1171: SNESSetType(snes,SNESLS);
1172: }
1174: PetscOptionsHasName(((PetscObject)snes)->prefix,"-snes_mf_operator",&flg);
1175: /*
1176: This version replaces the user provided Jacobian matrix with a
1177: matrix-free version but still employs the user-provided preconditioner matrix
1178: */
1179: if (flg) {
1180: Mat J;
1181: MatCreateSNESMF(snes,&J);
1182: MatMFFDSetFromOptions(J);
1183: PetscInfo(snes,"Setting default matrix-free operator routines\n");
1184: SNESSetJacobian(snes,J,0,0,0);
1185: MatDestroy(J);
1186: }
1188: #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE) && !defined(PETSC_USE_MAT_SINGLE) && !defined(PETSC_USE_LONG_DOUBLE) && !defined(PETSC_USE_INT)
1189: PetscOptionsHasName(((PetscObject)snes)->prefix,"-snes_mf_operator2",&flg);
1190: if (flg) {
1191: Mat J;
1192: SNESDefaultMatrixFreeCreate2(snes,snes->vec_sol,&J);
1193: PetscInfo(snes,"Setting default matrix-free operator routines (version 2)\n");
1194: SNESSetJacobian(snes,J,0,0,0);
1195: MatDestroy(J);
1196: }
1197: #endif
1199: PetscOptionsHasName(((PetscObject)snes)->prefix,"-snes_mf",&flg);
1200: /*
1201: This version replaces both the user-provided Jacobian and the user-
1202: provided preconditioner matrix with the default matrix free version.
1203: */
1204: if (flg) {
1205: Mat J;
1206: KSP ksp;
1207: PC pc;
1208: /* create and set matrix-free operator */
1209: MatCreateSNESMF(snes,&J);
1210: MatMFFDSetFromOptions(J);
1211: PetscInfo(snes,"Setting default matrix-free operator routines\n");
1212: SNESSetJacobian(snes,J,J,MatMFFDComputeJacobian,snes->funP);
1213: MatDestroy(J);
1214: /* force no preconditioner */
1215: SNESGetKSP(snes,&ksp);
1216: KSPGetPC(ksp,&pc);
1217: PetscTypeCompare((PetscObject)pc,PCSHELL,&flg);
1218: if (!flg) {
1219: PetscInfo(snes,"Setting default matrix-free preconditioner routines;\nThat is no preconditioner is being used\n");
1220: PCSetType(pc,PCNONE);
1221: }
1222: }
1224: if (!snes->vec_func && !snes->vec_rhs) {
1225: SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
1226: }
1227: if (!snes->ops->computefunction && !snes->vec_rhs) {
1228: SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
1229: }
1230: if (!snes->jacobian) {
1231: SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetJacobian() first \n or use -snes_mf option");
1232: }
1233: if (snes->vec_func == snes->vec_sol) {
1234: SETERRQ(PETSC_ERR_ARG_IDN,"Solution vector cannot be function vector");
1235: }
1236:
1237: if (snes->ops->setup) {
1238: (*snes->ops->setup)(snes);
1239: }
1240: snes->setupcalled = PETSC_TRUE;
1241: return(0);
1242: }
1246: /*@
1247: SNESDestroy - Destroys the nonlinear solver context that was created
1248: with SNESCreate().
1250: Collective on SNES
1252: Input Parameter:
1253: . snes - the SNES context
1255: Level: beginner
1257: .keywords: SNES, nonlinear, destroy
1259: .seealso: SNESCreate(), SNESSolve()
1260: @*/
1261: PetscErrorCode SNESDestroy(SNES snes)
1262: {
1267: if (--((PetscObject)snes)->refct > 0) return(0);
1269: /* if memory was published with AMS then destroy it */
1270: PetscObjectDepublish(snes);
1271: if (snes->ops->destroy) {(*(snes)->ops->destroy)(snes);}
1272:
1273: if (snes->vec_rhs) {VecDestroy(snes->vec_rhs);}
1274: if (snes->vec_sol) {VecDestroy(snes->vec_sol);}
1275: if (snes->vec_func) {VecDestroy(snes->vec_func);}
1276: if (snes->jacobian) {MatDestroy(snes->jacobian);}
1277: if (snes->jacobian_pre) {MatDestroy(snes->jacobian_pre);}
1278: KSPDestroy(snes->ksp);
1279: PetscFree(snes->kspconvctx);
1280: if (snes->vwork) {VecDestroyVecs(snes->vwork,snes->nvwork);}
1281: SNESMonitorCancel(snes);
1282: PetscHeaderDestroy(snes);
1283: return(0);
1284: }
1286: /* ----------- Routines to set solver parameters ---------- */
1290: /*@
1291: SNESSetTolerances - Sets various parameters used in convergence tests.
1293: Collective on SNES
1295: Input Parameters:
1296: + snes - the SNES context
1297: . abstol - absolute convergence tolerance
1298: . rtol - relative convergence tolerance
1299: . stol - convergence tolerance in terms of the norm
1300: of the change in the solution between steps
1301: . maxit - maximum number of iterations
1302: - maxf - maximum number of function evaluations
1304: Options Database Keys:
1305: + -snes_atol <abstol> - Sets abstol
1306: . -snes_rtol <rtol> - Sets rtol
1307: . -snes_stol <stol> - Sets stol
1308: . -snes_max_it <maxit> - Sets maxit
1309: - -snes_max_funcs <maxf> - Sets maxf
1311: Notes:
1312: The default maximum number of iterations is 50.
1313: The default maximum number of function evaluations is 1000.
1315: Level: intermediate
1317: .keywords: SNES, nonlinear, set, convergence, tolerances
1319: .seealso: SNESSetTrustRegionTolerance()
1320: @*/
1321: PetscErrorCode SNESSetTolerances(SNES snes,PetscReal abstol,PetscReal rtol,PetscReal stol,PetscInt maxit,PetscInt maxf)
1322: {
1325: if (abstol != PETSC_DEFAULT) snes->abstol = abstol;
1326: if (rtol != PETSC_DEFAULT) snes->rtol = rtol;
1327: if (stol != PETSC_DEFAULT) snes->xtol = stol;
1328: if (maxit != PETSC_DEFAULT) snes->max_its = maxit;
1329: if (maxf != PETSC_DEFAULT) snes->max_funcs = maxf;
1330: return(0);
1331: }
1335: /*@
1336: SNESGetTolerances - Gets various parameters used in convergence tests.
1338: Not Collective
1340: Input Parameters:
1341: + snes - the SNES context
1342: . atol - absolute convergence tolerance
1343: . rtol - relative convergence tolerance
1344: . stol - convergence tolerance in terms of the norm
1345: of the change in the solution between steps
1346: . maxit - maximum number of iterations
1347: - maxf - maximum number of function evaluations
1349: Notes:
1350: The user can specify PETSC_NULL for any parameter that is not needed.
1352: Level: intermediate
1354: .keywords: SNES, nonlinear, get, convergence, tolerances
1356: .seealso: SNESSetTolerances()
1357: @*/
1358: PetscErrorCode SNESGetTolerances(SNES snes,PetscReal *atol,PetscReal *rtol,PetscReal *stol,PetscInt *maxit,PetscInt *maxf)
1359: {
1362: if (atol) *atol = snes->abstol;
1363: if (rtol) *rtol = snes->rtol;
1364: if (stol) *stol = snes->xtol;
1365: if (maxit) *maxit = snes->max_its;
1366: if (maxf) *maxf = snes->max_funcs;
1367: return(0);
1368: }
1372: /*@
1373: SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
1375: Collective on SNES
1377: Input Parameters:
1378: + snes - the SNES context
1379: - tol - tolerance
1380:
1381: Options Database Key:
1382: . -snes_trtol <tol> - Sets tol
1384: Level: intermediate
1386: .keywords: SNES, nonlinear, set, trust region, tolerance
1388: .seealso: SNESSetTolerances()
1389: @*/
1390: PetscErrorCode SNESSetTrustRegionTolerance(SNES snes,PetscReal tol)
1391: {
1394: snes->deltatol = tol;
1395: return(0);
1396: }
1398: /*
1399: Duplicate the lg monitors for SNES from KSP; for some reason with
1400: dynamic libraries things don't work under Sun4 if we just use
1401: macros instead of functions
1402: */
1405: PetscErrorCode SNESMonitorLG(SNES snes,PetscInt it,PetscReal norm,void *ctx)
1406: {
1411: KSPMonitorLG((KSP)snes,it,norm,ctx);
1412: return(0);
1413: }
1417: PetscErrorCode SNESMonitorLGCreate(const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *draw)
1418: {
1422: KSPMonitorLGCreate(host,label,x,y,m,n,draw);
1423: return(0);
1424: }
1428: PetscErrorCode SNESMonitorLGDestroy(PetscDrawLG draw)
1429: {
1433: KSPMonitorLGDestroy(draw);
1434: return(0);
1435: }
1437: /* ------------ Routines to set performance monitoring options ----------- */
1441: /*@C
1442: SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
1443: iteration of the nonlinear solver to display the iteration's
1444: progress.
1446: Collective on SNES
1448: Input Parameters:
1449: + snes - the SNES context
1450: . func - monitoring routine
1451: . mctx - [optional] user-defined context for private data for the
1452: monitor routine (use PETSC_NULL if no context is desired)
1453: - monitordestroy - [optional] routine that frees monitor context
1454: (may be PETSC_NULL)
1456: Calling sequence of func:
1457: $ int func(SNES snes,PetscInt its, PetscReal norm,void *mctx)
1459: + snes - the SNES context
1460: . its - iteration number
1461: . norm - 2-norm function value (may be estimated)
1462: - mctx - [optional] monitoring context
1464: Options Database Keys:
1465: + -snes_monitor - sets SNESMonitorDefault()
1466: . -snes_monitor_draw - sets line graph monitor,
1467: uses SNESMonitorLGCreate()
1468: _ -snes_monitor_cancel - cancels all monitors that have
1469: been hardwired into a code by
1470: calls to SNESMonitorSet(), but
1471: does not cancel those set via
1472: the options database.
1474: Notes:
1475: Several different monitoring routines may be set by calling
1476: SNESMonitorSet() multiple times; all will be called in the
1477: order in which they were set.
1479: Level: intermediate
1481: .keywords: SNES, nonlinear, set, monitor
1483: .seealso: SNESMonitorDefault(), SNESMonitorCancel()
1484: @*/
1485: PetscErrorCode SNESMonitorSet(SNES snes,PetscErrorCode (*monitor)(SNES,PetscInt,PetscReal,void*),void *mctx,PetscErrorCode (*monitordestroy)(void*))
1486: {
1487: PetscInt i;
1491: if (snes->numbermonitors >= MAXSNESMONITORS) {
1492: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
1493: }
1494: for (i=0; i<snes->numbermonitors;i++) {
1495: if (monitor == snes->monitor[i] && monitordestroy == snes->monitordestroy[i] && mctx == snes->monitorcontext[i]) return(0);
1497: /* check if both default monitors that share common ASCII viewer */
1498: if (monitor == snes->monitor[i] && monitor == SNESMonitorDefault) {
1499: if (mctx && snes->monitorcontext[i]) {
1500: PetscErrorCode ierr;
1501: PetscViewerASCIIMonitor viewer1 = (PetscViewerASCIIMonitor) mctx;
1502: PetscViewerASCIIMonitor viewer2 = (PetscViewerASCIIMonitor) snes->monitorcontext[i];
1503: if (viewer1->viewer == viewer2->viewer) {
1504: (*monitordestroy)(mctx);
1505: return(0);
1506: }
1507: }
1508: }
1509: }
1510: snes->monitor[snes->numbermonitors] = monitor;
1511: snes->monitordestroy[snes->numbermonitors] = monitordestroy;
1512: snes->monitorcontext[snes->numbermonitors++] = (void*)mctx;
1513: return(0);
1514: }
1518: /*@C
1519: SNESMonitorCancel - Clears all the monitor functions for a SNES object.
1521: Collective on SNES
1523: Input Parameters:
1524: . snes - the SNES context
1526: Options Database Key:
1527: . -snes_monitor_cancel - cancels all monitors that have been hardwired
1528: into a code by calls to SNESMonitorSet(), but does not cancel those
1529: set via the options database
1531: Notes:
1532: There is no way to clear one specific monitor from a SNES object.
1534: Level: intermediate
1536: .keywords: SNES, nonlinear, set, monitor
1538: .seealso: SNESMonitorDefault(), SNESMonitorSet()
1539: @*/
1540: PetscErrorCode SNESMonitorCancel(SNES snes)
1541: {
1543: PetscInt i;
1547: for (i=0; i<snes->numbermonitors; i++) {
1548: if (snes->monitordestroy[i]) {
1549: (*snes->monitordestroy[i])(snes->monitorcontext[i]);
1550: }
1551: }
1552: snes->numbermonitors = 0;
1553: return(0);
1554: }
1558: /*@C
1559: SNESSetConvergenceTest - Sets the function that is to be used
1560: to test for convergence of the nonlinear iterative solution.
1562: Collective on SNES
1564: Input Parameters:
1565: + snes - the SNES context
1566: . func - routine to test for convergence
1567: - cctx - [optional] context for private data for the convergence routine
1568: (may be PETSC_NULL)
1570: Calling sequence of func:
1571: $ PetscErrorCode func (SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx)
1573: + snes - the SNES context
1574: . it - current iteration (0 is the first and is before any Newton step)
1575: . cctx - [optional] convergence context
1576: . reason - reason for convergence/divergence
1577: . xnorm - 2-norm of current iterate
1578: . gnorm - 2-norm of current step
1579: - f - 2-norm of function
1581: Level: advanced
1583: .keywords: SNES, nonlinear, set, convergence, test
1585: .seealso: SNESDefaultConverged(), SNESSkipConverged()
1586: @*/
1587: PetscErrorCode SNESSetConvergenceTest(SNES snes,PetscErrorCode (*func)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void *cctx)
1588: {
1591: if (!func) func = SNESSkipConverged;
1592: snes->ops->converged = func;
1593: snes->cnvP = cctx;
1594: return(0);
1595: }
1599: /*@
1600: SNESGetConvergedReason - Gets the reason the SNES iteration was stopped.
1602: Not Collective
1604: Input Parameter:
1605: . snes - the SNES context
1607: Output Parameter:
1608: . reason - negative value indicates diverged, positive value converged, see petscsnes.h or the
1609: manual pages for the individual convergence tests for complete lists
1611: Level: intermediate
1613: Notes: Can only be called after the call the SNESSolve() is complete.
1615: .keywords: SNES, nonlinear, set, convergence, test
1617: .seealso: SNESSetConvergenceTest(), SNESConvergedReason
1618: @*/
1619: PetscErrorCode SNESGetConvergedReason(SNES snes,SNESConvergedReason *reason)
1620: {
1624: *reason = snes->reason;
1625: return(0);
1626: }
1630: /*@
1631: SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
1633: Collective on SNES
1635: Input Parameters:
1636: + snes - iterative context obtained from SNESCreate()
1637: . a - array to hold history
1638: . its - integer array holds the number of linear iterations for each solve.
1639: . na - size of a and its
1640: - reset - PETSC_TRUE indicates each new nonlinear solve resets the history counter to zero,
1641: else it continues storing new values for new nonlinear solves after the old ones
1643: Notes:
1644: If set, this array will contain the function norms computed
1645: at each step.
1647: This routine is useful, e.g., when running a code for purposes
1648: of accurate performance monitoring, when no I/O should be done
1649: during the section of code that is being timed.
1651: Level: intermediate
1653: .keywords: SNES, set, convergence, history
1655: .seealso: SNESGetConvergenceHistory()
1657: @*/
1658: PetscErrorCode SNESSetConvergenceHistory(SNES snes,PetscReal a[],PetscInt its[],PetscInt na,PetscTruth reset)
1659: {
1664: snes->conv_hist = a;
1665: snes->conv_hist_its = its;
1666: snes->conv_hist_max = na;
1667: snes->conv_hist_reset = reset;
1668: return(0);
1669: }
1673: /*@C
1674: SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
1676: Collective on SNES
1678: Input Parameter:
1679: . snes - iterative context obtained from SNESCreate()
1681: Output Parameters:
1682: . a - array to hold history
1683: . its - integer array holds the number of linear iterations (or
1684: negative if not converged) for each solve.
1685: - na - size of a and its
1687: Notes:
1688: The calling sequence for this routine in Fortran is
1689: $ call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
1691: This routine is useful, e.g., when running a code for purposes
1692: of accurate performance monitoring, when no I/O should be done
1693: during the section of code that is being timed.
1695: Level: intermediate
1697: .keywords: SNES, get, convergence, history
1699: .seealso: SNESSetConvergencHistory()
1701: @*/
1702: PetscErrorCode SNESGetConvergenceHistory(SNES snes,PetscReal *a[],PetscInt *its[],PetscInt *na)
1703: {
1706: if (a) *a = snes->conv_hist;
1707: if (its) *its = snes->conv_hist_its;
1708: if (na) *na = snes->conv_hist_len;
1709: return(0);
1710: }
1714: /*@C
1715: SNESSetUpdate - Sets the general-purpose update function called
1716: at the beginning o every iteration of the nonlinear solve. Specifically
1717: it is called just before the Jacobian is "evaluated".
1719: Collective on SNES
1721: Input Parameters:
1722: . snes - The nonlinear solver context
1723: . func - The function
1725: Calling sequence of func:
1726: . func (SNES snes, PetscInt step);
1728: . step - The current step of the iteration
1730: Level: intermediate
1732: .keywords: SNES, update
1734: .seealso SNESDefaultUpdate(), SNESSetJacobian(), SNESSolve()
1735: @*/
1736: PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
1737: {
1740: snes->ops->update = func;
1741: return(0);
1742: }
1746: /*@
1747: SNESDefaultUpdate - The default update function which does nothing.
1749: Not collective
1751: Input Parameters:
1752: . snes - The nonlinear solver context
1753: . step - The current step of the iteration
1755: Level: intermediate
1757: .keywords: SNES, update
1758: .seealso SNESSetUpdate(), SNESDefaultRhsBC(), SNESDefaultShortolutionBC()
1759: @*/
1760: PetscErrorCode SNESDefaultUpdate(SNES snes, PetscInt step)
1761: {
1763: return(0);
1764: }
1768: /*
1769: SNESScaleStep_Private - Scales a step so that its length is less than the
1770: positive parameter delta.
1772: Input Parameters:
1773: + snes - the SNES context
1774: . y - approximate solution of linear system
1775: . fnorm - 2-norm of current function
1776: - delta - trust region size
1778: Output Parameters:
1779: + gpnorm - predicted function norm at the new point, assuming local
1780: linearization. The value is zero if the step lies within the trust
1781: region, and exceeds zero otherwise.
1782: - ynorm - 2-norm of the step
1784: Note:
1785: For non-trust region methods such as SNESLS, the parameter delta
1786: is set to be the maximum allowable step size.
1788: .keywords: SNES, nonlinear, scale, step
1789: */
1790: PetscErrorCode SNESScaleStep_Private(SNES snes,Vec y,PetscReal *fnorm,PetscReal *delta,PetscReal *gpnorm,PetscReal *ynorm)
1791: {
1792: PetscReal nrm;
1793: PetscScalar cnorm;
1801: VecNorm(y,NORM_2,&nrm);
1802: if (nrm > *delta) {
1803: nrm = *delta/nrm;
1804: *gpnorm = (1.0 - nrm)*(*fnorm);
1805: cnorm = nrm;
1806: VecScale(y,cnorm);
1807: *ynorm = *delta;
1808: } else {
1809: *gpnorm = 0.0;
1810: *ynorm = nrm;
1811: }
1812: return(0);
1813: }
1817: /*@C
1818: SNESSolve - Solves a nonlinear system F(x) = b.
1819: Call SNESSolve() after calling SNESCreate() and optional routines of the form SNESSetXXX().
1821: Collective on SNES
1823: Input Parameters:
1824: + snes - the SNES context
1825: . b - the constant part of the equation, or PETSC_NULL to use zero.
1826: - x - the solution vector.
1828: Notes:
1829: The user should initialize the vector,x, with the initial guess
1830: for the nonlinear solve prior to calling SNESSolve. In particular,
1831: to employ an initial guess of zero, the user should explicitly set
1832: this vector to zero by calling VecSet().
1834: Level: beginner
1836: .keywords: SNES, nonlinear, solve
1838: .seealso: SNESCreate(), SNESDestroy(), SNESSetFunction(), SNESSetJacobian()
1839: @*/
1840: PetscErrorCode SNESSolve(SNES snes,Vec b,Vec x)
1841: {
1843: PetscTruth flg;
1844: char filename[PETSC_MAX_PATH_LEN];
1845: PetscViewer viewer;
1854: /* set solution vector */
1855: PetscObjectReference((PetscObject)x);
1856: if (snes->vec_sol) { VecDestroy(snes->vec_sol); }
1857: snes->vec_sol = x;
1858: /* set afine vector if provided */
1859: if (b) { PetscObjectReference((PetscObject)b); }
1860: if (snes->vec_rhs) { VecDestroy(snes->vec_rhs); }
1861: snes->vec_rhs = b;
1862:
1863: if (!snes->vec_func && snes->vec_rhs) {
1864: VecDuplicate(b, &snes->vec_func);
1865: }
1867: SNESSetUp(snes);
1869: if (snes->conv_hist_reset) snes->conv_hist_len = 0;
1870: snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;
1873:
1874: PetscExceptionTry1((*(snes)->ops->solve)(snes),PETSC_ERR_ARG_DOMAIN);
1875: if (PetscExceptionValue(ierr)) {
1876: /* this means that a caller above me has also tryed this exception so I don't handle it here, pass it up */
1878: } else if (PetscExceptionCaught(ierr,PETSC_ERR_ARG_DOMAIN)) {
1879: /* translate exception into SNES not converged reason */
1880: snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1881: 0;
1882: }
1883:
1886: if (!snes->reason) {
1887: SETERRQ(PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");
1888: }
1889:
1890: PetscOptionsGetString(((PetscObject)snes)->prefix,"-snes_view",filename,PETSC_MAX_PATH_LEN,&flg);
1891: if (flg && !PetscPreLoadingOn) {
1892: PetscViewerASCIIOpen(((PetscObject)snes)->comm,filename,&viewer);
1893: SNESView(snes,viewer);
1894: PetscViewerDestroy(viewer);
1895: }
1897: PetscOptionsHasName(((PetscObject)snes)->prefix,"-snes_test_local_min",&flg);
1898: if (flg && !PetscPreLoadingOn) { SNESTestLocalMin(snes); }
1899: if (snes->printreason) {
1900: if (snes->reason > 0) {
1901: PetscPrintf(((PetscObject)snes)->comm,"Nonlinear solve converged due to %s\n",SNESConvergedReasons[snes->reason]);
1902: } else {
1903: PetscPrintf(((PetscObject)snes)->comm,"Nonlinear solve did not converge due to %s\n",SNESConvergedReasons[snes->reason]);
1904: }
1905: }
1907: return(0);
1908: }
1910: /* --------- Internal routines for SNES Package --------- */
1914: /*@C
1915: SNESSetType - Sets the method for the nonlinear solver.
1917: Collective on SNES
1919: Input Parameters:
1920: + snes - the SNES context
1921: - type - a known method
1923: Options Database Key:
1924: . -snes_type <type> - Sets the method; use -help for a list
1925: of available methods (for instance, ls or tr)
1927: Notes:
1928: See "petsc/include/petscsnes.h" for available methods (for instance)
1929: + SNESLS - Newton's method with line search
1930: (systems of nonlinear equations)
1931: . SNESTR - Newton's method with trust region
1932: (systems of nonlinear equations)
1934: Normally, it is best to use the SNESSetFromOptions() command and then
1935: set the SNES solver type from the options database rather than by using
1936: this routine. Using the options database provides the user with
1937: maximum flexibility in evaluating the many nonlinear solvers.
1938: The SNESSetType() routine is provided for those situations where it
1939: is necessary to set the nonlinear solver independently of the command
1940: line or options database. This might be the case, for example, when
1941: the choice of solver changes during the execution of the program,
1942: and the user's application is taking responsibility for choosing the
1943: appropriate method.
1945: Level: intermediate
1947: .keywords: SNES, set, type
1949: .seealso: SNESType, SNESCreate()
1951: @*/
1952: PetscErrorCode SNESSetType(SNES snes,SNESType type)
1953: {
1954: PetscErrorCode ierr,(*r)(SNES);
1955: PetscTruth match;
1961: PetscTypeCompare((PetscObject)snes,type,&match);
1962: if (match) return(0);
1964: PetscFListFind(SNESList,((PetscObject)snes)->comm,type,(void (**)(void)) &r);
1965: if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested SNES type %s",type);
1966: /* Destroy the previous private SNES context */
1967: if (snes->ops->destroy) { (*(snes)->ops->destroy)(snes); }
1968: /* Reinitialize function pointers in SNESOps structure */
1969: snes->ops->setup = 0;
1970: snes->ops->solve = 0;
1971: snes->ops->view = 0;
1972: snes->ops->setfromoptions = 0;
1973: snes->ops->destroy = 0;
1974: /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
1975: snes->setupcalled = PETSC_FALSE;
1976: (*r)(snes);
1977: PetscObjectChangeTypeName((PetscObject)snes,type);
1978: return(0);
1979: }
1982: /* --------------------------------------------------------------------- */
1985: /*@
1986: SNESRegisterDestroy - Frees the list of nonlinear solvers that were
1987: registered by SNESRegisterDynamic().
1989: Not Collective
1991: Level: advanced
1993: .keywords: SNES, nonlinear, register, destroy
1995: .seealso: SNESRegisterAll(), SNESRegisterAll()
1996: @*/
1997: PetscErrorCode SNESRegisterDestroy(void)
1998: {
2002: PetscFListDestroy(&SNESList);
2003: SNESRegisterAllCalled = PETSC_FALSE;
2004: return(0);
2005: }
2009: /*@C
2010: SNESGetType - Gets the SNES method type and name (as a string).
2012: Not Collective
2014: Input Parameter:
2015: . snes - nonlinear solver context
2017: Output Parameter:
2018: . type - SNES method (a character string)
2020: Level: intermediate
2022: .keywords: SNES, nonlinear, get, type, name
2023: @*/
2024: PetscErrorCode SNESGetType(SNES snes,SNESType *type)
2025: {
2029: *type = ((PetscObject)snes)->type_name;
2030: return(0);
2031: }
2035: /*@
2036: SNESGetSolution - Returns the vector where the approximate solution is
2037: stored.
2039: Not Collective, but Vec is parallel if SNES is parallel
2041: Input Parameter:
2042: . snes - the SNES context
2044: Output Parameter:
2045: . x - the solution
2047: Level: intermediate
2049: .keywords: SNES, nonlinear, get, solution
2051: .seealso: SNESGetSolutionUpdate(), SNESGetFunction()
2052: @*/
2053: PetscErrorCode SNESGetSolution(SNES snes,Vec *x)
2054: {
2058: *x = snes->vec_sol;
2059: return(0);
2060: }
2064: /*@
2065: SNESGetSolutionUpdate - Returns the vector where the solution update is
2066: stored.
2068: Not Collective, but Vec is parallel if SNES is parallel
2070: Input Parameter:
2071: . snes - the SNES context
2073: Output Parameter:
2074: . x - the solution update
2076: Level: advanced
2078: .keywords: SNES, nonlinear, get, solution, update
2080: .seealso: SNESGetSolution(), SNESGetFunction()
2081: @*/
2082: PetscErrorCode SNESGetSolutionUpdate(SNES snes,Vec *x)
2083: {
2087: *x = snes->vec_sol_update;
2088: return(0);
2089: }
2093: /*@C
2094: SNESGetFunction - Returns the vector where the function is stored.
2096: Not Collective, but Vec is parallel if SNES is parallel
2098: Input Parameter:
2099: . snes - the SNES context
2101: Output Parameter:
2102: + r - the function (or PETSC_NULL)
2103: . func - the function (or PETSC_NULL)
2104: - ctx - the function context (or PETSC_NULL)
2106: Level: advanced
2108: .keywords: SNES, nonlinear, get, function
2110: .seealso: SNESSetFunction(), SNESGetSolution()
2111: @*/
2112: PetscErrorCode SNESGetFunction(SNES snes,Vec *r,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx)
2113: {
2116: if (r) *r = snes->vec_func;
2117: if (func) *func = snes->ops->computefunction;
2118: if (ctx) *ctx = snes->funP;
2119: return(0);
2120: }
2124: /*@C
2125: SNESSetOptionsPrefix - Sets the prefix used for searching for all
2126: SNES options in the database.
2128: Collective on SNES
2130: Input Parameter:
2131: + snes - the SNES context
2132: - prefix - the prefix to prepend to all option names
2134: Notes:
2135: A hyphen (-) must NOT be given at the beginning of the prefix name.
2136: The first character of all runtime options is AUTOMATICALLY the hyphen.
2138: Level: advanced
2140: .keywords: SNES, set, options, prefix, database
2142: .seealso: SNESSetFromOptions()
2143: @*/
2144: PetscErrorCode SNESSetOptionsPrefix(SNES snes,const char prefix[])
2145: {
2150: PetscObjectSetOptionsPrefix((PetscObject)snes,prefix);
2151: KSPSetOptionsPrefix(snes->ksp,prefix);
2152: return(0);
2153: }
2157: /*@C
2158: SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
2159: SNES options in the database.
2161: Collective on SNES
2163: Input Parameters:
2164: + snes - the SNES context
2165: - prefix - the prefix to prepend to all option names
2167: Notes:
2168: A hyphen (-) must NOT be given at the beginning of the prefix name.
2169: The first character of all runtime options is AUTOMATICALLY the hyphen.
2171: Level: advanced
2173: .keywords: SNES, append, options, prefix, database
2175: .seealso: SNESGetOptionsPrefix()
2176: @*/
2177: PetscErrorCode SNESAppendOptionsPrefix(SNES snes,const char prefix[])
2178: {
2180:
2183: PetscObjectAppendOptionsPrefix((PetscObject)snes,prefix);
2184: KSPAppendOptionsPrefix(snes->ksp,prefix);
2185: return(0);
2186: }
2190: /*@C
2191: SNESGetOptionsPrefix - Sets the prefix used for searching for all
2192: SNES options in the database.
2194: Not Collective
2196: Input Parameter:
2197: . snes - the SNES context
2199: Output Parameter:
2200: . prefix - pointer to the prefix string used
2202: Notes: On the fortran side, the user should pass in a string 'prifix' of
2203: sufficient length to hold the prefix.
2205: Level: advanced
2207: .keywords: SNES, get, options, prefix, database
2209: .seealso: SNESAppendOptionsPrefix()
2210: @*/
2211: PetscErrorCode SNESGetOptionsPrefix(SNES snes,const char *prefix[])
2212: {
2217: PetscObjectGetOptionsPrefix((PetscObject)snes,prefix);
2218: return(0);
2219: }
2224: /*@C
2225: SNESRegister - See SNESRegisterDynamic()
2227: Level: advanced
2228: @*/
2229: PetscErrorCode SNESRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(SNES))
2230: {
2231: char fullname[PETSC_MAX_PATH_LEN];
2235: PetscFListConcat(path,name,fullname);
2236: PetscFListAdd(&SNESList,sname,fullname,(void (*)(void))function);
2237: return(0);
2238: }
2242: PetscErrorCode SNESTestLocalMin(SNES snes)
2243: {
2245: PetscInt N,i,j;
2246: Vec u,uh,fh;
2247: PetscScalar value;
2248: PetscReal norm;
2251: SNESGetSolution(snes,&u);
2252: VecDuplicate(u,&uh);
2253: VecDuplicate(u,&fh);
2255: /* currently only works for sequential */
2256: PetscPrintf(PETSC_COMM_WORLD,"Testing FormFunction() for local min\n");
2257: VecGetSize(u,&N);
2258: for (i=0; i<N; i++) {
2259: VecCopy(u,uh);
2260: PetscPrintf(PETSC_COMM_WORLD,"i = %D\n",i);
2261: for (j=-10; j<11; j++) {
2262: value = PetscSign(j)*exp(PetscAbs(j)-10.0);
2263: VecSetValue(uh,i,value,ADD_VALUES);
2264: SNESComputeFunction(snes,uh,fh);
2265: VecNorm(fh,NORM_2,&norm);
2266: PetscPrintf(PETSC_COMM_WORLD," j norm %D %18.16e\n",j,norm);
2267: value = -value;
2268: VecSetValue(uh,i,value,ADD_VALUES);
2269: }
2270: }
2271: VecDestroy(uh);
2272: VecDestroy(fh);
2273: return(0);
2274: }
2278: /*@
2279: SNESKSPSetUseEW - Sets SNES use Eisenstat-Walker method for
2280: computing relative tolerance for linear solvers within an inexact
2281: Newton method.
2283: Collective on SNES
2285: Input Parameters:
2286: + snes - SNES context
2287: - flag - PETSC_TRUE or PETSC_FALSE
2289: Notes:
2290: Currently, the default is to use a constant relative tolerance for
2291: the inner linear solvers. Alternatively, one can use the
2292: Eisenstat-Walker method, where the relative convergence tolerance
2293: is reset at each Newton iteration according progress of the nonlinear
2294: solver.
2296: Level: advanced
2298: Reference:
2299: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
2300: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
2302: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
2304: .seealso: SNESKSPGetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
2305: @*/
2306: PetscErrorCode SNESKSPSetUseEW(SNES snes,PetscTruth flag)
2307: {
2310: snes->ksp_ewconv = flag;
2311: return(0);
2312: }
2316: /*@
2317: SNESKSPGetUseEW - Gets if SNES is using Eisenstat-Walker method
2318: for computing relative tolerance for linear solvers within an
2319: inexact Newton method.
2321: Not Collective
2323: Input Parameter:
2324: . snes - SNES context
2326: Output Parameter:
2327: . flag - PETSC_TRUE or PETSC_FALSE
2329: Notes:
2330: Currently, the default is to use a constant relative tolerance for
2331: the inner linear solvers. Alternatively, one can use the
2332: Eisenstat-Walker method, where the relative convergence tolerance
2333: is reset at each Newton iteration according progress of the nonlinear
2334: solver.
2336: Level: advanced
2338: Reference:
2339: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
2340: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
2342: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
2344: .seealso: SNESKSPSetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
2345: @*/
2346: PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscTruth *flag)
2347: {
2351: *flag = snes->ksp_ewconv;
2352: return(0);
2353: }
2357: /*@
2358: SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
2359: convergence criteria for the linear solvers within an inexact
2360: Newton method.
2362: Collective on SNES
2363:
2364: Input Parameters:
2365: + snes - SNES context
2366: . version - version 1, 2 (default is 2) or 3
2367: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
2368: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
2369: . gamma - multiplicative factor for version 2 rtol computation
2370: (0 <= gamma2 <= 1)
2371: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
2372: . alpha2 - power for safeguard
2373: - threshold - threshold for imposing safeguard (0 < threshold < 1)
2375: Note:
2376: Version 3 was contributed by Luis Chacon, June 2006.
2378: Use PETSC_DEFAULT to retain the default for any of the parameters.
2380: Level: advanced
2382: Reference:
2383: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
2384: inexact Newton method", Utah State University Math. Stat. Dept. Res.
2385: Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
2387: .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
2389: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPGetParametersEW()
2390: @*/
2391: PetscErrorCode SNESKSPSetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,
2392: PetscReal gamma,PetscReal alpha,PetscReal alpha2,PetscReal threshold)
2393: {
2394: SNESKSPEW *kctx;
2397: kctx = (SNESKSPEW*)snes->kspconvctx;
2398: if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
2400: if (version != PETSC_DEFAULT) kctx->version = version;
2401: if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
2402: if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max;
2403: if (gamma != PETSC_DEFAULT) kctx->gamma = gamma;
2404: if (alpha != PETSC_DEFAULT) kctx->alpha = alpha;
2405: if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2;
2406: if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
2407:
2408: if (kctx->version < 1 || kctx->version > 3) {
2409: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 and 3 are supported: %D",kctx->version);
2410: }
2411: if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
2412: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %G",kctx->rtol_0);
2413: }
2414: if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
2415: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%G) < 1.0\n",kctx->rtol_max);
2416: }
2417: if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
2418: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%G) <= 1.0\n",kctx->gamma);
2419: }
2420: if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
2421: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%G) <= 2.0\n",kctx->alpha);
2422: }
2423: if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
2424: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%G) < 1.0\n",kctx->threshold);
2425: }
2426: return(0);
2427: }
2431: /*@
2432: SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
2433: convergence criteria for the linear solvers within an inexact
2434: Newton method.
2436: Not Collective
2437:
2438: Input Parameters:
2439: snes - SNES context
2441: Output Parameters:
2442: + version - version 1, 2 (default is 2) or 3
2443: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
2444: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
2445: . gamma - multiplicative factor for version 2 rtol computation
2446: (0 <= gamma2 <= 1)
2447: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
2448: . alpha2 - power for safeguard
2449: - threshold - threshold for imposing safeguard (0 < threshold < 1)
2451: Level: advanced
2453: .keywords: SNES, KSP, Eisenstat, Walker, get, parameters
2455: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPSetParametersEW()
2456: @*/
2457: PetscErrorCode SNESKSPGetParametersEW(SNES snes,PetscInt *version,PetscReal *rtol_0,PetscReal *rtol_max,
2458: PetscReal *gamma,PetscReal *alpha,PetscReal *alpha2,PetscReal *threshold)
2459: {
2460: SNESKSPEW *kctx;
2463: kctx = (SNESKSPEW*)snes->kspconvctx;
2464: if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
2465: if(version) *version = kctx->version;
2466: if(rtol_0) *rtol_0 = kctx->rtol_0;
2467: if(rtol_max) *rtol_max = kctx->rtol_max;
2468: if(gamma) *gamma = kctx->gamma;
2469: if(alpha) *alpha = kctx->alpha;
2470: if(alpha2) *alpha2 = kctx->alpha2;
2471: if(threshold) *threshold = kctx->threshold;
2472: return(0);
2473: }
2477: static PetscErrorCode SNESKSPEW_PreSolve(SNES snes, KSP ksp, Vec b, Vec x)
2478: {
2480: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
2481: PetscReal rtol=PETSC_DEFAULT,stol;
2484: if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists");
2485: if (!snes->iter) { /* first time in, so use the original user rtol */
2486: rtol = kctx->rtol_0;
2487: } else {
2488: if (kctx->version == 1) {
2489: rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
2490: if (rtol < 0.0) rtol = -rtol;
2491: stol = pow(kctx->rtol_last,kctx->alpha2);
2492: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
2493: } else if (kctx->version == 2) {
2494: rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
2495: stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
2496: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
2497: } else if (kctx->version == 3) {/* contributed by Luis Chacon, June 2006. */
2498: rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
2499: /* safeguard: avoid sharp decrease of rtol */
2500: stol = kctx->gamma*pow(kctx->rtol_last,kctx->alpha);
2501: stol = PetscMax(rtol,stol);
2502: rtol = PetscMin(kctx->rtol_0,stol);
2503: /* safeguard: avoid oversolving */
2504: stol = kctx->gamma*(snes->ttol)/snes->norm;
2505: stol = PetscMax(rtol,stol);
2506: rtol = PetscMin(kctx->rtol_0,stol);
2507: } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 or 3 are supported: %D",kctx->version);
2508: }
2509: /* safeguard: avoid rtol greater than one */
2510: rtol = PetscMin(rtol,kctx->rtol_max);
2511: KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
2512: PetscInfo3(snes,"iter %D, Eisenstat-Walker (version %D) KSP rtol=%G\n",snes->iter,kctx->version,rtol);
2513: return(0);
2514: }
2518: static PetscErrorCode SNESKSPEW_PostSolve(SNES snes, KSP ksp, Vec b, Vec x)
2519: {
2521: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
2522: PCSide pcside;
2523: Vec lres;
2526: if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists");
2527: KSPGetTolerances(ksp,&kctx->rtol_last,0,0,0);
2528: SNESGetFunctionNorm(snes,&kctx->norm_last);
2529: if (kctx->version == 1) {
2530: KSPGetPreconditionerSide(ksp,&pcside);
2531: if (pcside == PC_RIGHT) { /* XXX Should we also test KSP_UNPRECONDITIONED_NORM ? */
2532: /* KSP residual is true linear residual */
2533: KSPGetResidualNorm(ksp,&kctx->lresid_last);
2534: } else {
2535: /* KSP residual is preconditioned residual */
2536: /* compute true linear residual norm */
2537: VecDuplicate(b,&lres);
2538: MatMult(snes->jacobian,x,lres);
2539: VecAYPX(lres,-1.0,b);
2540: VecNorm(lres,NORM_2,&kctx->lresid_last);
2541: VecDestroy(lres);
2542: }
2543: }
2544: return(0);
2545: }
2549: PetscErrorCode SNES_KSPSolve(SNES snes, KSP ksp, Vec b, Vec x)
2550: {
2554: if (snes->ksp_ewconv) { SNESKSPEW_PreSolve(snes,ksp,b,x); }
2555: KSPSolve(ksp,b,x);
2556: if (snes->ksp_ewconv) { SNESKSPEW_PostSolve(snes,ksp,b,x); }
2557: return(0);
2558: }