Actual source code: snes.c
1: #include <petsc/private/snesimpl.h>
2: #include <petscdmshell.h>
3: #include <petscdraw.h>
4: #include <petscds.h>
5: #include <petscdmadaptor.h>
6: #include <petscconvest.h>
8: PetscBool SNESRegisterAllCalled = PETSC_FALSE;
9: PetscFunctionList SNESList = NULL;
11: /* Logging support */
12: PetscClassId SNES_CLASSID, DMSNES_CLASSID;
13: PetscLogEvent SNES_Solve, SNES_Setup, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval;
15: /*@
16: SNESSetErrorIfNotConverged - Causes SNESSolve() to generate an error if the solver has not converged.
18: Logically Collective on SNES
20: Input Parameters:
21: + snes - iterative context obtained from SNESCreate()
22: - flg - PETSC_TRUE indicates you want the error generated
24: Options database keys:
25: . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge
27: Level: intermediate
29: Notes:
30: Normally PETSc continues if a linear solver fails to converge, you can call SNESGetConvergedReason() after a SNESSolve()
31: to determine if it has converged.
33: .seealso: SNESGetErrorIfNotConverged(), KSPGetErrorIfNotConverged(), KSPSetErrorIfNotConverged()
34: @*/
35: PetscErrorCode SNESSetErrorIfNotConverged(SNES snes,PetscBool flg)
36: {
39: snes->errorifnotconverged = flg;
40: return 0;
41: }
43: /*@
44: SNESGetErrorIfNotConverged - Will SNESSolve() generate an error if the solver does not converge?
46: Not Collective
48: Input Parameter:
49: . snes - iterative context obtained from SNESCreate()
51: Output Parameter:
52: . flag - PETSC_TRUE if it will generate an error, else PETSC_FALSE
54: Level: intermediate
56: .seealso: SNESSetErrorIfNotConverged(), KSPGetErrorIfNotConverged(), KSPSetErrorIfNotConverged()
57: @*/
58: PetscErrorCode SNESGetErrorIfNotConverged(SNES snes,PetscBool *flag)
59: {
62: *flag = snes->errorifnotconverged;
63: return 0;
64: }
66: /*@
67: SNESSetAlwaysComputesFinalResidual - does the SNES always compute the residual at the final solution?
69: Logically Collective on SNES
71: Input Parameters:
72: + snes - the shell SNES
73: - flg - is the residual computed?
75: Level: advanced
77: .seealso: SNESGetAlwaysComputesFinalResidual()
78: @*/
79: PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg)
80: {
82: snes->alwayscomputesfinalresidual = flg;
83: return 0;
84: }
86: /*@
87: SNESGetAlwaysComputesFinalResidual - does the SNES always compute the residual at the final solution?
89: Logically Collective on SNES
91: Input Parameter:
92: . snes - the shell SNES
94: Output Parameter:
95: . flg - is the residual computed?
97: Level: advanced
99: .seealso: SNESSetAlwaysComputesFinalResidual()
100: @*/
101: PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg)
102: {
104: *flg = snes->alwayscomputesfinalresidual;
105: return 0;
106: }
108: /*@
109: SNESSetFunctionDomainError - tells SNES that the input vector to your SNESFunction is not
110: in the functions domain. For example, negative pressure.
112: Logically Collective on SNES
114: Input Parameters:
115: . snes - the SNES context
117: Level: advanced
119: .seealso: SNESCreate(), SNESSetFunction(), SNESFunction
120: @*/
121: PetscErrorCode SNESSetFunctionDomainError(SNES snes)
122: {
125: snes->domainerror = PETSC_TRUE;
126: return 0;
127: }
129: /*@
130: SNESSetJacobianDomainError - tells SNES that computeJacobian does not make sense any more. For example there is a negative element transformation.
132: Logically Collective on SNES
134: Input Parameters:
135: . snes - the SNES context
137: Level: advanced
139: .seealso: SNESCreate(), SNESSetFunction(), SNESFunction(), SNESSetFunctionDomainError()
140: @*/
141: PetscErrorCode SNESSetJacobianDomainError(SNES snes)
142: {
145: snes->jacobiandomainerror = PETSC_TRUE;
146: return 0;
147: }
149: /*@
150: SNESSetCheckJacobianDomainError - if or not to check jacobian domain error after each Jacobian evaluation. By default, we check Jacobian domain error
151: in the debug mode, and do not check it in the optimized mode.
153: Logically Collective on SNES
155: Input Parameters:
156: + snes - the SNES context
157: - flg - indicates if or not to check jacobian domain error after each Jacobian evaluation
159: Level: advanced
161: .seealso: SNESCreate(), SNESSetFunction(), SNESFunction(), SNESSetFunctionDomainError(), SNESGetCheckJacobianDomainError()
162: @*/
163: PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
164: {
166: snes->checkjacdomainerror = flg;
167: return 0;
168: }
170: /*@
171: SNESGetCheckJacobianDomainError - Get an indicator whether or not we are checking Jacobian domain errors after each Jacobian evaluation.
173: Logically Collective on SNES
175: Input Parameters:
176: . snes - the SNES context
178: Output Parameters:
179: . flg - PETSC_FALSE indicates that we don't check jacobian domain errors after each Jacobian evaluation
181: Level: advanced
183: .seealso: SNESCreate(), SNESSetFunction(), SNESFunction(), SNESSetFunctionDomainError(), SNESSetCheckJacobianDomainError()
184: @*/
185: PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
186: {
189: *flg = snes->checkjacdomainerror;
190: return 0;
191: }
193: /*@
194: SNESGetFunctionDomainError - Gets the status of the domain error after a call to SNESComputeFunction;
196: Logically Collective on SNES
198: Input Parameters:
199: . snes - the SNES context
201: Output Parameters:
202: . domainerror - Set to PETSC_TRUE if there's a domain error; PETSC_FALSE otherwise.
204: Level: advanced
206: .seealso: SNESSetFunctionDomainError(), SNESComputeFunction()
207: @*/
208: PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
209: {
212: *domainerror = snes->domainerror;
213: return 0;
214: }
216: /*@
217: SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to SNESComputeJacobian;
219: Logically Collective on SNES
221: Input Parameters:
222: . snes - the SNES context
224: Output Parameters:
225: . domainerror - Set to PETSC_TRUE if there's a jacobian domain error; PETSC_FALSE otherwise.
227: Level: advanced
229: .seealso: SNESSetFunctionDomainError(), SNESComputeFunction(),SNESGetFunctionDomainError()
230: @*/
231: PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror)
232: {
235: *domainerror = snes->jacobiandomainerror;
236: return 0;
237: }
239: /*@C
240: SNESLoad - Loads a SNES that has been stored in binary with SNESView().
242: Collective on PetscViewer
244: Input Parameters:
245: + newdm - the newly loaded SNES, this needs to have been created with SNESCreate() or
246: some related function before a call to SNESLoad().
247: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
249: Level: intermediate
251: Notes:
252: The type is determined by the data in the file, any type set into the SNES before this call is ignored.
254: Notes for advanced users:
255: Most users should not need to know the details of the binary storage
256: format, since SNESLoad() and TSView() completely hide these details.
257: But for anyone who's interested, the standard binary matrix storage
258: format is
259: .vb
260: has not yet been determined
261: .ve
263: .seealso: PetscViewerBinaryOpen(), SNESView(), MatLoad(), VecLoad()
264: @*/
265: PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
266: {
267: PetscBool isbinary;
268: PetscInt classid;
269: char type[256];
270: KSP ksp;
271: DM dm;
272: DMSNES dmsnes;
276: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
279: PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
281: PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
282: SNESSetType(snes, type);
283: if (snes->ops->load) {
284: (*snes->ops->load)(snes,viewer);
285: }
286: SNESGetDM(snes,&dm);
287: DMGetDMSNES(dm,&dmsnes);
288: DMSNESLoad(dmsnes,viewer);
289: SNESGetKSP(snes,&ksp);
290: KSPLoad(ksp,viewer);
291: return 0;
292: }
294: #include <petscdraw.h>
295: #if defined(PETSC_HAVE_SAWS)
296: #include <petscviewersaws.h>
297: #endif
299: /*@C
300: SNESViewFromOptions - View from Options
302: Collective on SNES
304: Input Parameters:
305: + A - the application ordering context
306: . obj - Optional object
307: - name - command line option
309: Level: intermediate
310: .seealso: SNES, SNESView, PetscObjectViewFromOptions(), SNESCreate()
311: @*/
312: PetscErrorCode SNESViewFromOptions(SNES A,PetscObject obj,const char name[])
313: {
315: PetscObjectViewFromOptions((PetscObject)A,obj,name);
316: return 0;
317: }
319: PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES,Vec,Mat,Mat,void*);
321: /*@C
322: SNESView - Prints the SNES data structure.
324: Collective on SNES
326: Input Parameters:
327: + SNES - the SNES context
328: - viewer - visualization context
330: Options Database Key:
331: . -snes_view - Calls SNESView() at end of SNESSolve()
333: Notes:
334: The available visualization contexts include
335: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
336: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
337: output where only the first processor opens
338: the file. All other processors send their
339: data to the first processor to print.
341: The available formats include
342: + PETSC_VIEWER_DEFAULT - standard output (default)
343: - PETSC_VIEWER_ASCII_INFO_DETAIL - more verbose output for SNESNASM
345: The user can open an alternative visualization context with
346: PetscViewerASCIIOpen() - output to a specified file.
348: In the debugger you can do "call SNESView(snes,0)" to display the SNES solver. (The same holds for any PETSc object viewer).
350: Level: beginner
352: .seealso: PetscViewerASCIIOpen()
353: @*/
354: PetscErrorCode SNESView(SNES snes,PetscViewer viewer)
355: {
356: SNESKSPEW *kctx;
357: KSP ksp;
358: SNESLineSearch linesearch;
359: PetscBool iascii,isstring,isbinary,isdraw;
360: DMSNES dmsnes;
361: #if defined(PETSC_HAVE_SAWS)
362: PetscBool issaws;
363: #endif
366: if (!viewer) {
367: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);
368: }
372: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
373: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
374: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
375: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
376: #if defined(PETSC_HAVE_SAWS)
377: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);
378: #endif
379: if (iascii) {
380: SNESNormSchedule normschedule;
381: DM dm;
382: PetscErrorCode (*cJ)(SNES,Vec,Mat,Mat,void*);
383: void *ctx;
384: const char *pre = "";
386: PetscObjectPrintClassNamePrefixType((PetscObject)snes,viewer);
387: if (!snes->setupcalled) {
388: PetscViewerASCIIPrintf(viewer," SNES has not been set up so information may be incomplete\n");
389: }
390: if (snes->ops->view) {
391: PetscViewerASCIIPushTab(viewer);
392: (*snes->ops->view)(snes,viewer);
393: PetscViewerASCIIPopTab(viewer);
394: }
395: PetscViewerASCIIPrintf(viewer," maximum iterations=%D, maximum function evaluations=%D\n",snes->max_its,snes->max_funcs);
396: PetscViewerASCIIPrintf(viewer," tolerances: relative=%g, absolute=%g, solution=%g\n",(double)snes->rtol,(double)snes->abstol,(double)snes->stol);
397: if (snes->usesksp) {
398: PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",snes->linear_its);
399: }
400: PetscViewerASCIIPrintf(viewer," total number of function evaluations=%D\n",snes->nfuncs);
401: SNESGetNormSchedule(snes, &normschedule);
402: if (normschedule > 0) PetscViewerASCIIPrintf(viewer," norm schedule %s\n",SNESNormSchedules[normschedule]);
403: if (snes->gridsequence) {
404: PetscViewerASCIIPrintf(viewer," total number of grid sequence refinements=%D\n",snes->gridsequence);
405: }
406: if (snes->ksp_ewconv) {
407: kctx = (SNESKSPEW*)snes->kspconvctx;
408: if (kctx) {
409: PetscViewerASCIIPrintf(viewer," Eisenstat-Walker computation of KSP relative tolerance (version %D)\n",kctx->version);
410: PetscViewerASCIIPrintf(viewer," rtol_0=%g, rtol_max=%g, threshold=%g\n",(double)kctx->rtol_0,(double)kctx->rtol_max,(double)kctx->threshold);
411: PetscViewerASCIIPrintf(viewer," gamma=%g, alpha=%g, alpha2=%g\n",(double)kctx->gamma,(double)kctx->alpha,(double)kctx->alpha2);
412: }
413: }
414: if (snes->lagpreconditioner == -1) {
415: PetscViewerASCIIPrintf(viewer," Preconditioned is never rebuilt\n");
416: } else if (snes->lagpreconditioner > 1) {
417: PetscViewerASCIIPrintf(viewer," Preconditioned is rebuilt every %D new Jacobians\n",snes->lagpreconditioner);
418: }
419: if (snes->lagjacobian == -1) {
420: PetscViewerASCIIPrintf(viewer," Jacobian is never rebuilt\n");
421: } else if (snes->lagjacobian > 1) {
422: PetscViewerASCIIPrintf(viewer," Jacobian is rebuilt every %D SNES iterations\n",snes->lagjacobian);
423: }
424: SNESGetDM(snes,&dm);
425: DMSNESGetJacobian(dm,&cJ,&ctx);
426: if (snes->mf_operator) {
427: PetscViewerASCIIPrintf(viewer," Jacobian is applied matrix-free with differencing\n");
428: pre = "Preconditioning ";
429: }
430: if (cJ == SNESComputeJacobianDefault) {
431: PetscViewerASCIIPrintf(viewer," %sJacobian is built using finite differences one column at a time\n",pre);
432: } else if (cJ == SNESComputeJacobianDefaultColor) {
433: PetscViewerASCIIPrintf(viewer," %sJacobian is built using finite differences with coloring\n",pre);
434: /* it slightly breaks data encapsulation for access the DMDA information directly */
435: } else if (cJ == SNESComputeJacobian_DMDA) {
436: MatFDColoring fdcoloring;
437: PetscObjectQuery((PetscObject)dm,"DMDASNES_FDCOLORING",(PetscObject*)&fdcoloring);
438: if (fdcoloring) {
439: PetscViewerASCIIPrintf(viewer," %sJacobian is built using colored finite differences on a DMDA\n",pre);
440: } else {
441: PetscViewerASCIIPrintf(viewer," %sJacobian is built using a DMDA local Jacobian\n",pre);
442: }
443: } else if (snes->mf) {
444: PetscViewerASCIIPrintf(viewer," Jacobian is applied matrix-free with differencing, no explicit Jacobian\n");
445: }
446: } else if (isstring) {
447: const char *type;
448: SNESGetType(snes,&type);
449: PetscViewerStringSPrintf(viewer," SNESType: %-7.7s",type);
450: if (snes->ops->view) (*snes->ops->view)(snes,viewer);
451: } else if (isbinary) {
452: PetscInt classid = SNES_FILE_CLASSID;
453: MPI_Comm comm;
454: PetscMPIInt rank;
455: char type[256];
457: PetscObjectGetComm((PetscObject)snes,&comm);
458: MPI_Comm_rank(comm,&rank);
459: if (rank == 0) {
460: PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT);
461: PetscStrncpy(type,((PetscObject)snes)->type_name,sizeof(type));
462: PetscViewerBinaryWrite(viewer,type,sizeof(type),PETSC_CHAR);
463: }
464: if (snes->ops->view) {
465: (*snes->ops->view)(snes,viewer);
466: }
467: } else if (isdraw) {
468: PetscDraw draw;
469: char str[36];
470: PetscReal x,y,bottom,h;
472: PetscViewerDrawGetDraw(viewer,0,&draw);
473: PetscDrawGetCurrentPoint(draw,&x,&y);
474: PetscStrncpy(str,"SNES: ",sizeof(str));
475: PetscStrlcat(str,((PetscObject)snes)->type_name,sizeof(str));
476: PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_BLUE,PETSC_DRAW_BLACK,str,NULL,&h);
477: bottom = y - h;
478: PetscDrawPushCurrentPoint(draw,x,bottom);
479: if (snes->ops->view) {
480: (*snes->ops->view)(snes,viewer);
481: }
482: #if defined(PETSC_HAVE_SAWS)
483: } else if (issaws) {
484: PetscMPIInt rank;
485: const char *name;
487: PetscObjectGetName((PetscObject)snes,&name);
488: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
489: if (!((PetscObject)snes)->amsmem && rank == 0) {
490: char dir[1024];
492: PetscObjectViewSAWs((PetscObject)snes,viewer);
493: PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/its",name);
494: PetscStackCallSAWs(SAWs_Register,(dir,&snes->iter,1,SAWs_READ,SAWs_INT));
495: if (!snes->conv_hist) {
496: SNESSetConvergenceHistory(snes,NULL,NULL,PETSC_DECIDE,PETSC_TRUE);
497: }
498: PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/conv_hist",name);
499: PetscStackCallSAWs(SAWs_Register,(dir,snes->conv_hist,10,SAWs_READ,SAWs_DOUBLE));
500: }
501: #endif
502: }
503: if (snes->linesearch) {
504: SNESGetLineSearch(snes, &linesearch);
505: PetscViewerASCIIPushTab(viewer);
506: SNESLineSearchView(linesearch, viewer);
507: PetscViewerASCIIPopTab(viewer);
508: }
509: if (snes->npc && snes->usesnpc) {
510: PetscViewerASCIIPushTab(viewer);
511: SNESView(snes->npc, viewer);
512: PetscViewerASCIIPopTab(viewer);
513: }
514: PetscViewerASCIIPushTab(viewer);
515: DMGetDMSNES(snes->dm,&dmsnes);
516: DMSNESView(dmsnes, viewer);
517: PetscViewerASCIIPopTab(viewer);
518: if (snes->usesksp) {
519: SNESGetKSP(snes,&ksp);
520: PetscViewerASCIIPushTab(viewer);
521: KSPView(ksp,viewer);
522: PetscViewerASCIIPopTab(viewer);
523: }
524: if (isdraw) {
525: PetscDraw draw;
526: PetscViewerDrawGetDraw(viewer,0,&draw);
527: PetscDrawPopCurrentPoint(draw);
528: }
529: return 0;
530: }
532: /*
533: We retain a list of functions that also take SNES command
534: line options. These are called at the end SNESSetFromOptions()
535: */
536: #define MAXSETFROMOPTIONS 5
537: static PetscInt numberofsetfromoptions;
538: static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
540: /*@C
541: SNESAddOptionsChecker - Adds an additional function to check for SNES options.
543: Not Collective
545: Input Parameter:
546: . snescheck - function that checks for options
548: Level: developer
550: .seealso: SNESSetFromOptions()
551: @*/
552: PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES))
553: {
555: othersetfromoptions[numberofsetfromoptions++] = snescheck;
556: return 0;
557: }
559: PETSC_INTERN PetscErrorCode SNESDefaultMatrixFreeCreate2(SNES,Vec,Mat*);
561: static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
562: {
563: Mat J;
564: MatNullSpace nullsp;
568: if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
569: Mat A = snes->jacobian, B = snes->jacobian_pre;
570: MatCreateVecs(A ? A : B, NULL,&snes->vec_func);
571: }
573: if (version == 1) {
574: MatCreateSNESMF(snes,&J);
575: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
576: MatSetFromOptions(J);
577: /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
578: } else if (version == 2) {
580: #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
581: SNESDefaultMatrixFreeCreate2(snes,snes->vec_func,&J);
582: #else
583: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
584: #endif
585: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
587: /* attach any user provided null space that was on Amat to the newly created matrix free matrix */
588: if (snes->jacobian) {
589: MatGetNullSpace(snes->jacobian,&nullsp);
590: if (nullsp) {
591: MatSetNullSpace(J,nullsp);
592: }
593: }
595: PetscInfo(snes,"Setting default matrix-free operator routines (version %D)\n", version);
596: if (hasOperator) {
598: /* This version replaces the user provided Jacobian matrix with a
599: matrix-free version but still employs the user-provided preconditioner matrix. */
600: SNESSetJacobian(snes,J,NULL,NULL,NULL);
601: } else {
602: /* This version replaces both the user-provided Jacobian and the user-
603: provided preconditioner Jacobian with the default matrix free version. */
604: if (snes->npcside == PC_LEFT && snes->npc) {
605: if (!snes->jacobian) SNESSetJacobian(snes,J,NULL,NULL,NULL);
606: } else {
607: KSP ksp;
608: PC pc;
609: PetscBool match;
611: SNESSetJacobian(snes,J,J,MatMFFDComputeJacobian,NULL);
612: /* Force no preconditioner */
613: SNESGetKSP(snes,&ksp);
614: KSPGetPC(ksp,&pc);
615: PetscObjectTypeCompare((PetscObject)pc,PCSHELL,&match);
616: if (!match) {
617: PetscInfo(snes,"Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n");
618: PCSetType(pc,PCNONE);
619: }
620: }
621: }
622: MatDestroy(&J);
623: return 0;
624: }
626: static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine,Mat Restrict,Vec Rscale,Mat Inject,DM dmcoarse,void *ctx)
627: {
628: SNES snes = (SNES)ctx;
629: Vec Xfine,Xfine_named = NULL,Xcoarse;
631: if (PetscLogPrintInfo) {
632: PetscInt finelevel,coarselevel,fineclevel,coarseclevel;
633: DMGetRefineLevel(dmfine,&finelevel);
634: DMGetCoarsenLevel(dmfine,&fineclevel);
635: DMGetRefineLevel(dmcoarse,&coarselevel);
636: DMGetCoarsenLevel(dmcoarse,&coarseclevel);
637: PetscInfo(dmfine,"Restricting SNES solution vector from level %D-%D to level %D-%D\n",finelevel,fineclevel,coarselevel,coarseclevel);
638: }
639: if (dmfine == snes->dm) Xfine = snes->vec_sol;
640: else {
641: DMGetNamedGlobalVector(dmfine,"SNESVecSol",&Xfine_named);
642: Xfine = Xfine_named;
643: }
644: DMGetNamedGlobalVector(dmcoarse,"SNESVecSol",&Xcoarse);
645: if (Inject) {
646: MatRestrict(Inject,Xfine,Xcoarse);
647: } else {
648: MatRestrict(Restrict,Xfine,Xcoarse);
649: VecPointwiseMult(Xcoarse,Xcoarse,Rscale);
650: }
651: DMRestoreNamedGlobalVector(dmcoarse,"SNESVecSol",&Xcoarse);
652: if (Xfine_named) DMRestoreNamedGlobalVector(dmfine,"SNESVecSol",&Xfine_named);
653: return 0;
654: }
656: static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm,DM dmc,void *ctx)
657: {
658: DMCoarsenHookAdd(dmc,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,ctx);
659: return 0;
660: }
662: /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
663: * safely call SNESGetDM() in their residual evaluation routine. */
664: static PetscErrorCode KSPComputeOperators_SNES(KSP ksp,Mat A,Mat B,void *ctx)
665: {
666: SNES snes = (SNES)ctx;
667: Vec X,Xnamed = NULL;
668: DM dmsave;
669: void *ctxsave;
670: PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*) = NULL;
672: dmsave = snes->dm;
673: KSPGetDM(ksp,&snes->dm);
674: if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
675: else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */
676: DMGetNamedGlobalVector(snes->dm,"SNESVecSol",&Xnamed);
677: X = Xnamed;
678: SNESGetJacobian(snes,NULL,NULL,&jac,&ctxsave);
679: /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
680: if (jac == SNESComputeJacobianDefaultColor) {
681: SNESSetJacobian(snes,NULL,NULL,SNESComputeJacobianDefaultColor,NULL);
682: }
683: }
684: /* Make sure KSP DM has the Jacobian computation routine */
685: {
686: DMSNES sdm;
688: DMGetDMSNES(snes->dm, &sdm);
689: if (!sdm->ops->computejacobian) {
690: DMCopyDMSNES(dmsave, snes->dm);
691: }
692: }
693: /* Compute the operators */
694: SNESComputeJacobian(snes,X,A,B);
695: /* Put the previous context back */
696: if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) {
697: SNESSetJacobian(snes,NULL,NULL,jac,ctxsave);
698: }
700: if (Xnamed) DMRestoreNamedGlobalVector(snes->dm,"SNESVecSol",&Xnamed);
701: snes->dm = dmsave;
702: return 0;
703: }
705: /*@
706: SNESSetUpMatrices - ensures that matrices are available for SNES, to be called by SNESSetUp_XXX()
708: Collective
710: Input Parameter:
711: . snes - snes to configure
713: Level: developer
715: .seealso: SNESSetUp()
716: @*/
717: PetscErrorCode SNESSetUpMatrices(SNES snes)
718: {
719: DM dm;
720: DMSNES sdm;
722: SNESGetDM(snes,&dm);
723: DMGetDMSNES(dm,&sdm);
724: if (!snes->jacobian && snes->mf) {
725: Mat J;
726: void *functx;
727: MatCreateSNESMF(snes,&J);
728: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
729: MatSetFromOptions(J);
730: SNESGetFunction(snes,NULL,NULL,&functx);
731: SNESSetJacobian(snes,J,J,NULL,NULL);
732: MatDestroy(&J);
733: } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
734: Mat J,B;
735: MatCreateSNESMF(snes,&J);
736: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
737: MatSetFromOptions(J);
738: DMCreateMatrix(snes->dm,&B);
739: /* sdm->computejacobian was already set to reach here */
740: SNESSetJacobian(snes,J,B,NULL,NULL);
741: MatDestroy(&J);
742: MatDestroy(&B);
743: } else if (!snes->jacobian_pre) {
744: PetscDS prob;
745: Mat J, B;
746: PetscBool hasPrec = PETSC_FALSE;
748: J = snes->jacobian;
749: DMGetDS(dm, &prob);
750: if (prob) PetscDSHasJacobianPreconditioner(prob, &hasPrec);
751: if (J) PetscObjectReference((PetscObject) J);
752: else if (hasPrec) DMCreateMatrix(snes->dm, &J);
753: DMCreateMatrix(snes->dm, &B);
754: SNESSetJacobian(snes, J ? J : B, B, NULL, NULL);
755: MatDestroy(&J);
756: MatDestroy(&B);
757: }
758: {
759: KSP ksp;
760: SNESGetKSP(snes,&ksp);
761: KSPSetComputeOperators(ksp,KSPComputeOperators_SNES,snes);
762: DMCoarsenHookAdd(snes->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,snes);
763: }
764: return 0;
765: }
767: static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
768: {
769: PetscInt i;
771: if (!snes->pauseFinal) return 0;
772: for (i = 0; i < snes->numbermonitors; ++i) {
773: PetscViewerAndFormat *vf = (PetscViewerAndFormat *) snes->monitorcontext[i];
774: PetscDraw draw;
775: PetscReal lpause;
777: if (!vf) continue;
778: if (vf->lg) {
780: if (((PetscObject) vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
781: PetscDrawLGGetDraw(vf->lg, &draw);
782: PetscDrawGetPause(draw, &lpause);
783: PetscDrawSetPause(draw, -1.0);
784: PetscDrawPause(draw);
785: PetscDrawSetPause(draw, lpause);
786: } else {
787: PetscBool isdraw;
790: if (((PetscObject) vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
791: PetscObjectTypeCompare((PetscObject) vf->viewer, PETSCVIEWERDRAW, &isdraw);
792: if (!isdraw) continue;
793: PetscViewerDrawGetDraw(vf->viewer, 0, &draw);
794: PetscDrawGetPause(draw, &lpause);
795: PetscDrawSetPause(draw, -1.0);
796: PetscDrawPause(draw);
797: PetscDrawSetPause(draw, lpause);
798: }
799: }
800: return 0;
801: }
803: /*@C
804: SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
806: Collective on SNES
808: Input Parameters:
809: + snes - SNES object you wish to monitor
810: . name - the monitor type one is seeking
811: . help - message indicating what monitoring is done
812: . manual - manual page for the monitor
813: . monitor - the monitor function
814: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the SNES or PetscViewer objects
816: Level: developer
818: .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
819: PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
820: PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
821: PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
822: PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
823: PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
824: PetscOptionsFList(), PetscOptionsEList()
825: @*/
826: PetscErrorCode SNESMonitorSetFromOptions(SNES snes,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(SNES,PetscInt,PetscReal,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(SNES,PetscViewerAndFormat*))
827: {
828: PetscViewer viewer;
829: PetscViewerFormat format;
830: PetscBool flg;
832: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,name,&viewer,&format,&flg);
833: if (flg) {
834: PetscViewerAndFormat *vf;
835: PetscViewerAndFormatCreate(viewer,format,&vf);
836: PetscObjectDereference((PetscObject)viewer);
837: if (monitorsetup) {
838: (*monitorsetup)(snes,vf);
839: }
840: SNESMonitorSet(snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);
841: }
842: return 0;
843: }
845: /*@
846: SNESSetFromOptions - Sets various SNES and KSP parameters from user options.
848: Collective on SNES
850: Input Parameter:
851: . snes - the SNES context
853: Options Database Keys:
854: + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, SNESType for complete list
855: . -snes_stol - convergence tolerance in terms of the norm
856: of the change in the solution between steps
857: . -snes_atol <abstol> - absolute tolerance of residual norm
858: . -snes_rtol <rtol> - relative decrease in tolerance norm from initial
859: . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
860: . -snes_force_iteration <force> - force SNESSolve() to take at least one iteration
861: . -snes_max_it <max_it> - maximum number of iterations
862: . -snes_max_funcs <max_funcs> - maximum number of function evaluations
863: . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
864: . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
865: . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild)
866: . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve()
867: . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild)
868: . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve()
869: . -snes_trtol <trtol> - trust region tolerance
870: . -snes_no_convergence_test - skip convergence test in nonlinear
871: solver; hence iterations will continue until max_it
872: or some other criterion is reached. Saves expense
873: of convergence test
874: . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout
875: . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
876: . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration
877: . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
878: . -snes_monitor_lg_residualnorm - plots residual norm at each iteration
879: . -snes_monitor_lg_range - plots residual norm at each iteration
880: . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends
881: . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
882: . -snes_fd_color - use finite differences with coloring to compute Jacobian
883: . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration
884: . -snes_converged_reason - print the reason for convergence/divergence after each solve
885: . -npc_snes_type <type> - the SNES type to use as a nonlinear preconditioner
886: . -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one computed via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold.
887: - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian.
889: Options Database for Eisenstat-Walker method:
890: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
891: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
892: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
893: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
894: . -snes_ksp_ew_gamma <gamma> - Sets gamma
895: . -snes_ksp_ew_alpha <alpha> - Sets alpha
896: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
897: - -snes_ksp_ew_threshold <threshold> - Sets threshold
899: Notes:
900: To see all options, run your program with the -help option or consult the users manual
902: Notes:
903: SNES supports three approaches for computing (approximate) Jacobians: user provided via SNESSetJacobian(), matrix free, and computing explicitly with
904: finite differences and coloring using MatFDColoring. It is also possible to use automatic differentiation and the MatFDColoring object.
906: Level: beginner
908: .seealso: SNESSetOptionsPrefix(), SNESResetFromOptions(), SNES, SNESCreate()
909: @*/
910: PetscErrorCode SNESSetFromOptions(SNES snes)
911: {
912: PetscBool flg,pcset,persist,set;
913: PetscInt i,indx,lag,grids;
914: const char *deft = SNESNEWTONLS;
915: const char *convtests[] = {"default","skip","correct_pressure"};
916: SNESKSPEW *kctx = NULL;
917: char type[256], monfilename[PETSC_MAX_PATH_LEN];
919: PCSide pcside;
920: const char *optionsprefix;
923: SNESRegisterAll();
924: PetscObjectOptionsBegin((PetscObject)snes);
925: if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
926: PetscOptionsFList("-snes_type","Nonlinear solver method","SNESSetType",SNESList,deft,type,256,&flg);
927: if (flg) {
928: SNESSetType(snes,type);
929: } else if (!((PetscObject)snes)->type_name) {
930: SNESSetType(snes,deft);
931: }
932: PetscOptionsReal("-snes_stol","Stop if step length less than","SNESSetTolerances",snes->stol,&snes->stol,NULL);
933: PetscOptionsReal("-snes_atol","Stop if function norm less than","SNESSetTolerances",snes->abstol,&snes->abstol,NULL);
935: PetscOptionsReal("-snes_rtol","Stop if decrease in function norm less than","SNESSetTolerances",snes->rtol,&snes->rtol,NULL);
936: PetscOptionsReal("-snes_divergence_tolerance","Stop if residual norm increases by this factor","SNESSetDivergenceTolerance",snes->divtol,&snes->divtol,NULL);
937: PetscOptionsInt("-snes_max_it","Maximum iterations","SNESSetTolerances",snes->max_its,&snes->max_its,NULL);
938: PetscOptionsInt("-snes_max_funcs","Maximum function evaluations","SNESSetTolerances",snes->max_funcs,&snes->max_funcs,NULL);
939: PetscOptionsInt("-snes_max_fail","Maximum nonlinear step failures","SNESSetMaxNonlinearStepFailures",snes->maxFailures,&snes->maxFailures,NULL);
940: PetscOptionsInt("-snes_max_linear_solve_fail","Maximum failures in linear solves allowed","SNESSetMaxLinearSolveFailures",snes->maxLinearSolveFailures,&snes->maxLinearSolveFailures,NULL);
941: PetscOptionsBool("-snes_error_if_not_converged","Generate error if solver does not converge","SNESSetErrorIfNotConverged",snes->errorifnotconverged,&snes->errorifnotconverged,NULL);
942: PetscOptionsBool("-snes_force_iteration","Force SNESSolve() to take at least one iteration","SNESSetForceIteration",snes->forceiteration,&snes->forceiteration,NULL);
943: PetscOptionsBool("-snes_check_jacobian_domain_error","Check Jacobian domain error after Jacobian evaluation","SNESCheckJacobianDomainError",snes->checkjacdomainerror,&snes->checkjacdomainerror,NULL);
945: PetscOptionsInt("-snes_lag_preconditioner","How often to rebuild preconditioner","SNESSetLagPreconditioner",snes->lagpreconditioner,&lag,&flg);
946: if (flg) {
948: SNESSetLagPreconditioner(snes,lag);
949: }
950: PetscOptionsBool("-snes_lag_preconditioner_persists","Preconditioner lagging through multiple SNES solves","SNESSetLagPreconditionerPersists",snes->lagjac_persist,&persist,&flg);
951: if (flg) {
952: SNESSetLagPreconditionerPersists(snes,persist);
953: }
954: PetscOptionsInt("-snes_lag_jacobian","How often to rebuild Jacobian","SNESSetLagJacobian",snes->lagjacobian,&lag,&flg);
955: if (flg) {
957: SNESSetLagJacobian(snes,lag);
958: }
959: PetscOptionsBool("-snes_lag_jacobian_persists","Jacobian lagging through multiple SNES solves","SNESSetLagJacobianPersists",snes->lagjac_persist,&persist,&flg);
960: if (flg) {
961: SNESSetLagJacobianPersists(snes,persist);
962: }
964: PetscOptionsInt("-snes_grid_sequence","Use grid sequencing to generate initial guess","SNESSetGridSequence",snes->gridsequence,&grids,&flg);
965: if (flg) {
966: SNESSetGridSequence(snes,grids);
967: }
969: PetscOptionsEList("-snes_convergence_test","Convergence test","SNESSetConvergenceTest",convtests,sizeof(convtests)/sizeof(char*),"default",&indx,&flg);
970: if (flg) {
971: switch (indx) {
972: case 0: SNESSetConvergenceTest(snes,SNESConvergedDefault,NULL,NULL); break;
973: case 1: SNESSetConvergenceTest(snes,SNESConvergedSkip,NULL,NULL); break;
974: case 2: SNESSetConvergenceTest(snes,SNESConvergedCorrectPressure,NULL,NULL); break;
975: }
976: }
978: PetscOptionsEList("-snes_norm_schedule","SNES Norm schedule","SNESSetNormSchedule",SNESNormSchedules,5,"function",&indx,&flg);
979: if (flg) SNESSetNormSchedule(snes,(SNESNormSchedule)indx);
981: PetscOptionsEList("-snes_function_type","SNES Norm schedule","SNESSetFunctionType",SNESFunctionTypes,2,"unpreconditioned",&indx,&flg);
982: if (flg) SNESSetFunctionType(snes,(SNESFunctionType)indx);
984: kctx = (SNESKSPEW*)snes->kspconvctx;
986: PetscOptionsBool("-snes_ksp_ew","Use Eisentat-Walker linear system convergence test","SNESKSPSetUseEW",snes->ksp_ewconv,&snes->ksp_ewconv,NULL);
988: PetscOptionsInt("-snes_ksp_ew_version","Version 1, 2 or 3","SNESKSPSetParametersEW",kctx->version,&kctx->version,NULL);
989: PetscOptionsReal("-snes_ksp_ew_rtol0","0 <= rtol0 < 1","SNESKSPSetParametersEW",kctx->rtol_0,&kctx->rtol_0,NULL);
990: PetscOptionsReal("-snes_ksp_ew_rtolmax","0 <= rtolmax < 1","SNESKSPSetParametersEW",kctx->rtol_max,&kctx->rtol_max,NULL);
991: PetscOptionsReal("-snes_ksp_ew_gamma","0 <= gamma <= 1","SNESKSPSetParametersEW",kctx->gamma,&kctx->gamma,NULL);
992: PetscOptionsReal("-snes_ksp_ew_alpha","1 < alpha <= 2","SNESKSPSetParametersEW",kctx->alpha,&kctx->alpha,NULL);
993: PetscOptionsReal("-snes_ksp_ew_alpha2","alpha2","SNESKSPSetParametersEW",kctx->alpha2,&kctx->alpha2,NULL);
994: PetscOptionsReal("-snes_ksp_ew_threshold","0 < threshold < 1","SNESKSPSetParametersEW",kctx->threshold,&kctx->threshold,NULL);
996: flg = PETSC_FALSE;
997: PetscOptionsBool("-snes_monitor_cancel","Remove all monitors","SNESMonitorCancel",flg,&flg,&set);
998: if (set && flg) SNESMonitorCancel(snes);
1000: SNESMonitorSetFromOptions(snes,"-snes_monitor","Monitor norm of function","SNESMonitorDefault",SNESMonitorDefault,SNESMonitorDefaultSetUp);
1001: SNESMonitorSetFromOptions(snes,"-snes_monitor_short","Monitor norm of function with fewer digits","SNESMonitorDefaultShort",SNESMonitorDefaultShort,NULL);
1002: SNESMonitorSetFromOptions(snes,"-snes_monitor_range","Monitor range of elements of function","SNESMonitorRange",SNESMonitorRange,NULL);
1004: SNESMonitorSetFromOptions(snes,"-snes_monitor_ratio","Monitor ratios of the norm of function for consecutive steps","SNESMonitorRatio",SNESMonitorRatio,SNESMonitorRatioSetUp);
1005: SNESMonitorSetFromOptions(snes,"-snes_monitor_field","Monitor norm of function (split into fields)","SNESMonitorDefaultField",SNESMonitorDefaultField,NULL);
1006: SNESMonitorSetFromOptions(snes,"-snes_monitor_solution","View solution at each iteration","SNESMonitorSolution",SNESMonitorSolution,NULL);
1007: SNESMonitorSetFromOptions(snes,"-snes_monitor_solution_update","View correction at each iteration","SNESMonitorSolutionUpdate",SNESMonitorSolutionUpdate,NULL);
1008: SNESMonitorSetFromOptions(snes,"-snes_monitor_residual","View residual at each iteration","SNESMonitorResidual",SNESMonitorResidual,NULL);
1009: SNESMonitorSetFromOptions(snes,"-snes_monitor_jacupdate_spectrum","Print the change in the spectrum of the Jacobian","SNESMonitorJacUpdateSpectrum",SNESMonitorJacUpdateSpectrum,NULL);
1010: SNESMonitorSetFromOptions(snes,"-snes_monitor_fields","Monitor norm of function per field","SNESMonitorSet",SNESMonitorFields,NULL);
1011: PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL);
1013: PetscOptionsString("-snes_monitor_python","Use Python function","SNESMonitorSet",NULL,monfilename,sizeof(monfilename),&flg);
1014: if (flg) PetscPythonMonitorSet((PetscObject)snes,monfilename);
1016: flg = PETSC_FALSE;
1017: PetscOptionsBool("-snes_monitor_lg_range","Plot function range at each iteration","SNESMonitorLGRange",flg,&flg,NULL);
1018: if (flg) {
1019: PetscViewer ctx;
1021: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&ctx);
1022: SNESMonitorSet(snes,SNESMonitorLGRange,ctx,(PetscErrorCode (*)(void**))PetscViewerDestroy);
1023: }
1025: flg = PETSC_FALSE;
1026: PetscOptionsBool("-snes_converged_reason_view_cancel","Remove all converged reason viewers","SNESConvergedReasonViewCancel",flg,&flg,&set);
1027: if (set && flg) SNESConvergedReasonViewCancel(snes);
1029: flg = PETSC_FALSE;
1030: PetscOptionsBool("-snes_fd","Use finite differences (slow) to compute Jacobian","SNESComputeJacobianDefault",flg,&flg,NULL);
1031: if (flg) {
1032: void *functx;
1033: DM dm;
1034: DMSNES sdm;
1035: SNESGetDM(snes,&dm);
1036: DMGetDMSNES(dm,&sdm);
1037: sdm->jacobianctx = NULL;
1038: SNESGetFunction(snes,NULL,NULL,&functx);
1039: SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESComputeJacobianDefault,functx);
1040: PetscInfo(snes,"Setting default finite difference Jacobian matrix\n");
1041: }
1043: flg = PETSC_FALSE;
1044: PetscOptionsBool("-snes_fd_function","Use finite differences (slow) to compute function from user objective","SNESObjectiveComputeFunctionDefaultFD",flg,&flg,NULL);
1045: if (flg) {
1046: SNESSetFunction(snes,NULL,SNESObjectiveComputeFunctionDefaultFD,NULL);
1047: }
1049: flg = PETSC_FALSE;
1050: PetscOptionsBool("-snes_fd_color","Use finite differences with coloring to compute Jacobian","SNESComputeJacobianDefaultColor",flg,&flg,NULL);
1051: if (flg) {
1052: DM dm;
1053: DMSNES sdm;
1054: SNESGetDM(snes,&dm);
1055: DMGetDMSNES(dm,&sdm);
1056: sdm->jacobianctx = NULL;
1057: SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESComputeJacobianDefaultColor,NULL);
1058: PetscInfo(snes,"Setting default finite difference coloring Jacobian matrix\n");
1059: }
1061: flg = PETSC_FALSE;
1062: PetscOptionsBool("-snes_mf_operator","Use a Matrix-Free Jacobian with user-provided preconditioner matrix","SNESSetUseMatrixFree",PETSC_FALSE,&snes->mf_operator,&flg);
1063: if (flg && snes->mf_operator) {
1064: snes->mf_operator = PETSC_TRUE;
1065: snes->mf = PETSC_TRUE;
1066: }
1067: flg = PETSC_FALSE;
1068: PetscOptionsBool("-snes_mf","Use a Matrix-Free Jacobian with no preconditioner matrix","SNESSetUseMatrixFree",PETSC_FALSE,&snes->mf,&flg);
1069: if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
1070: PetscOptionsInt("-snes_mf_version","Matrix-Free routines version 1 or 2","None",snes->mf_version,&snes->mf_version,NULL);
1072: flg = PETSC_FALSE;
1073: SNESGetNPCSide(snes,&pcside);
1074: PetscOptionsEnum("-snes_npc_side","SNES nonlinear preconditioner side","SNESSetNPCSide",PCSides,(PetscEnum)pcside,(PetscEnum*)&pcside,&flg);
1075: if (flg) SNESSetNPCSide(snes,pcside);
1077: #if defined(PETSC_HAVE_SAWS)
1078: /*
1079: Publish convergence information using SAWs
1080: */
1081: flg = PETSC_FALSE;
1082: PetscOptionsBool("-snes_monitor_saws","Publish SNES progress using SAWs","SNESMonitorSet",flg,&flg,NULL);
1083: if (flg) {
1084: void *ctx;
1085: SNESMonitorSAWsCreate(snes,&ctx);
1086: SNESMonitorSet(snes,SNESMonitorSAWs,ctx,SNESMonitorSAWsDestroy);
1087: }
1088: #endif
1089: #if defined(PETSC_HAVE_SAWS)
1090: {
1091: PetscBool set;
1092: flg = PETSC_FALSE;
1093: PetscOptionsBool("-snes_saws_block","Block for SAWs at end of SNESSolve","PetscObjectSAWsBlock",((PetscObject)snes)->amspublishblock,&flg,&set);
1094: if (set) {
1095: PetscObjectSAWsSetBlock((PetscObject)snes,flg);
1096: }
1097: }
1098: #endif
1100: for (i = 0; i < numberofsetfromoptions; i++) {
1101: (*othersetfromoptions[i])(snes);
1102: }
1104: if (snes->ops->setfromoptions) {
1105: (*snes->ops->setfromoptions)(PetscOptionsObject,snes);
1106: }
1108: /* process any options handlers added with PetscObjectAddOptionsHandler() */
1109: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)snes);
1110: PetscOptionsEnd();
1112: if (snes->linesearch) {
1113: SNESGetLineSearch(snes, &snes->linesearch);
1114: SNESLineSearchSetFromOptions(snes->linesearch);
1115: }
1117: if (snes->usesksp) {
1118: if (!snes->ksp) SNESGetKSP(snes,&snes->ksp);
1119: KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);
1120: KSPSetFromOptions(snes->ksp);
1121: }
1123: /* if user has set the SNES NPC type via options database, create it. */
1124: SNESGetOptionsPrefix(snes, &optionsprefix);
1125: PetscOptionsHasName(((PetscObject)snes)->options,optionsprefix, "-npc_snes_type", &pcset);
1126: if (pcset && (!snes->npc)) {
1127: SNESGetNPC(snes, &snes->npc);
1128: }
1129: if (snes->npc) {
1130: SNESSetFromOptions(snes->npc);
1131: }
1132: snes->setfromoptionscalled++;
1133: return 0;
1134: }
1136: /*@
1137: SNESResetFromOptions - Sets various SNES and KSP parameters from user options ONLY if the SNES was previously set from options
1139: Collective on SNES
1141: Input Parameter:
1142: . snes - the SNES context
1144: Level: beginner
1146: .seealso: SNESSetFromOptions(), SNESSetOptionsPrefix()
1147: @*/
1148: PetscErrorCode SNESResetFromOptions(SNES snes)
1149: {
1150: if (snes->setfromoptionscalled) SNESSetFromOptions(snes);
1151: return 0;
1152: }
1154: /*@C
1155: SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1156: the nonlinear solvers.
1158: Logically Collective on SNES
1160: Input Parameters:
1161: + snes - the SNES context
1162: . compute - function to compute the context
1163: - destroy - function to destroy the context
1165: Level: intermediate
1167: Notes:
1168: This function is currently not available from Fortran.
1170: .seealso: SNESGetApplicationContext(), SNESSetComputeApplicationContext(), SNESGetApplicationContext()
1171: @*/
1172: PetscErrorCode SNESSetComputeApplicationContext(SNES snes,PetscErrorCode (*compute)(SNES,void**),PetscErrorCode (*destroy)(void**))
1173: {
1175: snes->ops->usercompute = compute;
1176: snes->ops->userdestroy = destroy;
1177: return 0;
1178: }
1180: /*@
1181: SNESSetApplicationContext - Sets the optional user-defined context for
1182: the nonlinear solvers.
1184: Logically Collective on SNES
1186: Input Parameters:
1187: + snes - the SNES context
1188: - usrP - optional user context
1190: Level: intermediate
1192: Fortran Notes:
1193: To use this from Fortran you must write a Fortran interface definition for this
1194: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1196: .seealso: SNESGetApplicationContext()
1197: @*/
1198: PetscErrorCode SNESSetApplicationContext(SNES snes,void *usrP)
1199: {
1200: KSP ksp;
1203: SNESGetKSP(snes,&ksp);
1204: KSPSetApplicationContext(ksp,usrP);
1205: snes->user = usrP;
1206: return 0;
1207: }
1209: /*@
1210: SNESGetApplicationContext - Gets the user-defined context for the
1211: nonlinear solvers.
1213: Not Collective
1215: Input Parameter:
1216: . snes - SNES context
1218: Output Parameter:
1219: . usrP - user context
1221: Fortran Notes:
1222: To use this from Fortran you must write a Fortran interface definition for this
1223: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1225: Level: intermediate
1227: .seealso: SNESSetApplicationContext()
1228: @*/
1229: PetscErrorCode SNESGetApplicationContext(SNES snes,void *usrP)
1230: {
1232: *(void**)usrP = snes->user;
1233: return 0;
1234: }
1236: /*@
1237: SNESSetUseMatrixFree - indicates that SNES should use matrix free finite difference matrix vector products internally to apply the Jacobian.
1239: Collective on SNES
1241: Input Parameters:
1242: + snes - SNES context
1243: . mf_operator - use matrix-free only for the Amat used by SNESSetJacobian(), this means the user provided Pmat will continue to be used
1244: - mf - use matrix-free for both the Amat and Pmat used by SNESSetJacobian(), both the Amat and Pmat set in SNESSetJacobian() will be ignored
1246: Options Database:
1247: + -snes_mf - use matrix free for both the mat and pmat operator
1248: . -snes_mf_operator - use matrix free only for the mat operator
1249: . -snes_fd_color - compute the Jacobian via coloring and finite differences.
1250: - -snes_fd - compute the Jacobian via finite differences (slow)
1252: Level: intermediate
1254: Notes:
1255: SNES supports three approaches for computing (approximate) Jacobians: user provided via SNESSetJacobian(), matrix free, and computing explicitly with
1256: finite differences and coloring using MatFDColoring. It is also possible to use automatic differentiation and the MatFDColoring object.
1258: .seealso: SNESGetUseMatrixFree(), MatCreateSNESMF(), SNESComputeJacobianDefaultColor()
1259: @*/
1260: PetscErrorCode SNESSetUseMatrixFree(SNES snes,PetscBool mf_operator,PetscBool mf)
1261: {
1265: snes->mf = mf_operator ? PETSC_TRUE : mf;
1266: snes->mf_operator = mf_operator;
1267: return 0;
1268: }
1270: /*@
1271: SNESGetUseMatrixFree - indicates if the SNES uses matrix free finite difference matrix vector products to apply the Jacobian.
1273: Collective on SNES
1275: Input Parameter:
1276: . snes - SNES context
1278: Output Parameters:
1279: + mf_operator - use matrix-free only for the Amat used by SNESSetJacobian(), this means the user provided Pmat will continue to be used
1280: - mf - use matrix-free for both the Amat and Pmat used by SNESSetJacobian(), both the Amat and Pmat set in SNESSetJacobian() will be ignored
1282: Options Database:
1283: + -snes_mf - use matrix free for both the mat and pmat operator
1284: - -snes_mf_operator - use matrix free only for the mat operator
1286: Level: intermediate
1288: .seealso: SNESSetUseMatrixFree(), MatCreateSNESMF()
1289: @*/
1290: PetscErrorCode SNESGetUseMatrixFree(SNES snes,PetscBool *mf_operator,PetscBool *mf)
1291: {
1293: if (mf) *mf = snes->mf;
1294: if (mf_operator) *mf_operator = snes->mf_operator;
1295: return 0;
1296: }
1298: /*@
1299: SNESGetIterationNumber - Gets the number of nonlinear iterations completed
1300: at this time.
1302: Not Collective
1304: Input Parameter:
1305: . snes - SNES context
1307: Output Parameter:
1308: . iter - iteration number
1310: Notes:
1311: For example, during the computation of iteration 2 this would return 1.
1313: This is useful for using lagged Jacobians (where one does not recompute the
1314: Jacobian at each SNES iteration). For example, the code
1315: .vb
1316: SNESGetIterationNumber(snes,&it);
1317: if (!(it % 2)) {
1318: [compute Jacobian here]
1319: }
1320: .ve
1321: can be used in your ComputeJacobian() function to cause the Jacobian to be
1322: recomputed every second SNES iteration.
1324: After the SNES solve is complete this will return the number of nonlinear iterations used.
1326: Level: intermediate
1328: .seealso: SNESGetLinearSolveIterations()
1329: @*/
1330: PetscErrorCode SNESGetIterationNumber(SNES snes,PetscInt *iter)
1331: {
1334: *iter = snes->iter;
1335: return 0;
1336: }
1338: /*@
1339: SNESSetIterationNumber - Sets the current iteration number.
1341: Not Collective
1343: Input Parameters:
1344: + snes - SNES context
1345: - iter - iteration number
1347: Level: developer
1349: .seealso: SNESGetLinearSolveIterations()
1350: @*/
1351: PetscErrorCode SNESSetIterationNumber(SNES snes,PetscInt iter)
1352: {
1354: PetscObjectSAWsTakeAccess((PetscObject)snes);
1355: snes->iter = iter;
1356: PetscObjectSAWsGrantAccess((PetscObject)snes);
1357: return 0;
1358: }
1360: /*@
1361: SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1362: attempted by the nonlinear solver.
1364: Not Collective
1366: Input Parameter:
1367: . snes - SNES context
1369: Output Parameter:
1370: . nfails - number of unsuccessful steps attempted
1372: Notes:
1373: This counter is reset to zero for each successive call to SNESSolve().
1375: Level: intermediate
1377: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1378: SNESSetMaxNonlinearStepFailures(), SNESGetMaxNonlinearStepFailures()
1379: @*/
1380: PetscErrorCode SNESGetNonlinearStepFailures(SNES snes,PetscInt *nfails)
1381: {
1384: *nfails = snes->numFailures;
1385: return 0;
1386: }
1388: /*@
1389: SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1390: attempted by the nonlinear solver before it gives up.
1392: Not Collective
1394: Input Parameters:
1395: + snes - SNES context
1396: - maxFails - maximum of unsuccessful steps
1398: Level: intermediate
1400: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1401: SNESGetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
1402: @*/
1403: PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1404: {
1406: snes->maxFailures = maxFails;
1407: return 0;
1408: }
1410: /*@
1411: SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1412: attempted by the nonlinear solver before it gives up.
1414: Not Collective
1416: Input Parameter:
1417: . snes - SNES context
1419: Output Parameter:
1420: . maxFails - maximum of unsuccessful steps
1422: Level: intermediate
1424: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1425: SNESSetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
1427: @*/
1428: PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1429: {
1432: *maxFails = snes->maxFailures;
1433: return 0;
1434: }
1436: /*@
1437: SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1438: done by SNES.
1440: Not Collective
1442: Input Parameter:
1443: . snes - SNES context
1445: Output Parameter:
1446: . nfuncs - number of evaluations
1448: Level: intermediate
1450: Notes:
1451: Reset every time SNESSolve is called unless SNESSetCountersReset() is used.
1453: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(), SNESSetCountersReset()
1454: @*/
1455: PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1456: {
1459: *nfuncs = snes->nfuncs;
1460: return 0;
1461: }
1463: /*@
1464: SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1465: linear solvers.
1467: Not Collective
1469: Input Parameter:
1470: . snes - SNES context
1472: Output Parameter:
1473: . nfails - number of failed solves
1475: Level: intermediate
1477: Options Database Keys:
1478: . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
1480: Notes:
1481: This counter is reset to zero for each successive call to SNESSolve().
1483: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures()
1484: @*/
1485: PetscErrorCode SNESGetLinearSolveFailures(SNES snes,PetscInt *nfails)
1486: {
1489: *nfails = snes->numLinearSolveFailures;
1490: return 0;
1491: }
1493: /*@
1494: SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1495: allowed before SNES returns with a diverged reason of SNES_DIVERGED_LINEAR_SOLVE
1497: Logically Collective on SNES
1499: Input Parameters:
1500: + snes - SNES context
1501: - maxFails - maximum allowed linear solve failures
1503: Level: intermediate
1505: Options Database Keys:
1506: . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
1508: Notes:
1509: By default this is 0; that is SNES returns on the first failed linear solve
1511: .seealso: SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations()
1512: @*/
1513: PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1514: {
1517: snes->maxLinearSolveFailures = maxFails;
1518: return 0;
1519: }
1521: /*@
1522: SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1523: are allowed before SNES terminates
1525: Not Collective
1527: Input Parameter:
1528: . snes - SNES context
1530: Output Parameter:
1531: . maxFails - maximum of unsuccessful solves allowed
1533: Level: intermediate
1535: Notes:
1536: By default this is 1; that is SNES returns on the first failed linear solve
1538: .seealso: SNESGetLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(),
1539: @*/
1540: PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1541: {
1544: *maxFails = snes->maxLinearSolveFailures;
1545: return 0;
1546: }
1548: /*@
1549: SNESGetLinearSolveIterations - Gets the total number of linear iterations
1550: used by the nonlinear solver.
1552: Not Collective
1554: Input Parameter:
1555: . snes - SNES context
1557: Output Parameter:
1558: . lits - number of linear iterations
1560: Notes:
1561: This counter is reset to zero for each successive call to SNESSolve() unless SNESSetCountersReset() is used.
1563: If the linear solver fails inside the SNESSolve() the iterations for that call to the linear solver are not included. If you wish to count them
1564: then call KSPGetIterationNumber() after the failed solve.
1566: Level: intermediate
1568: .seealso: SNESGetIterationNumber(), SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESSetCountersReset()
1569: @*/
1570: PetscErrorCode SNESGetLinearSolveIterations(SNES snes,PetscInt *lits)
1571: {
1574: *lits = snes->linear_its;
1575: return 0;
1576: }
1578: /*@
1579: SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1580: are reset every time SNESSolve() is called.
1582: Logically Collective on SNES
1584: Input Parameters:
1585: + snes - SNES context
1586: - reset - whether to reset the counters or not
1588: Notes:
1589: This defaults to PETSC_TRUE
1591: Level: developer
1593: .seealso: SNESGetNumberFunctionEvals(), SNESGetLinearSolveIterations(), SNESGetNPC()
1594: @*/
1595: PetscErrorCode SNESSetCountersReset(SNES snes,PetscBool reset)
1596: {
1599: snes->counters_reset = reset;
1600: return 0;
1601: }
1603: /*@
1604: SNESSetKSP - Sets a KSP context for the SNES object to use
1606: Not Collective, but the SNES and KSP objects must live on the same MPI_Comm
1608: Input Parameters:
1609: + snes - the SNES context
1610: - ksp - the KSP context
1612: Notes:
1613: The SNES object already has its KSP object, you can obtain with SNESGetKSP()
1614: so this routine is rarely needed.
1616: The KSP object that is already in the SNES object has its reference count
1617: decreased by one.
1619: Level: developer
1621: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
1622: @*/
1623: PetscErrorCode SNESSetKSP(SNES snes,KSP ksp)
1624: {
1628: PetscObjectReference((PetscObject)ksp);
1629: if (snes->ksp) PetscObjectDereference((PetscObject)snes->ksp);
1630: snes->ksp = ksp;
1631: return 0;
1632: }
1634: /* -----------------------------------------------------------*/
1635: /*@
1636: SNESCreate - Creates a nonlinear solver context.
1638: Collective
1640: Input Parameters:
1641: . comm - MPI communicator
1643: Output Parameter:
1644: . outsnes - the new SNES context
1646: Options Database Keys:
1647: + -snes_mf - Activates default matrix-free Jacobian-vector products,
1648: and no preconditioning matrix
1649: . -snes_mf_operator - Activates default matrix-free Jacobian-vector
1650: products, and a user-provided preconditioning matrix
1651: as set by SNESSetJacobian()
1652: - -snes_fd - Uses (slow!) finite differences to compute Jacobian
1654: Level: beginner
1656: Developer Notes:
1657: SNES always creates a KSP object even though many SNES methods do not use it. This is
1658: unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1659: particular method does use KSP and regulates if the information about the KSP is printed
1660: in SNESView(). TSSetFromOptions() does call SNESSetFromOptions() which can lead to users being confused
1661: by help messages about meaningless SNES options.
1663: SNES always creates the snes->kspconvctx even though it is used by only one type. This should
1664: be fixed.
1666: .seealso: SNESSolve(), SNESDestroy(), SNES, SNESSetLagPreconditioner(), SNESSetLagJacobian()
1668: @*/
1669: PetscErrorCode SNESCreate(MPI_Comm comm,SNES *outsnes)
1670: {
1671: SNES snes;
1672: SNESKSPEW *kctx;
1675: *outsnes = NULL;
1676: SNESInitializePackage();
1678: PetscHeaderCreate(snes,SNES_CLASSID,"SNES","Nonlinear solver","SNES",comm,SNESDestroy,SNESView);
1680: snes->ops->converged = SNESConvergedDefault;
1681: snes->usesksp = PETSC_TRUE;
1682: snes->tolerancesset = PETSC_FALSE;
1683: snes->max_its = 50;
1684: snes->max_funcs = 10000;
1685: snes->norm = 0.0;
1686: snes->xnorm = 0.0;
1687: snes->ynorm = 0.0;
1688: snes->normschedule = SNES_NORM_ALWAYS;
1689: snes->functype = SNES_FUNCTION_DEFAULT;
1690: #if defined(PETSC_USE_REAL_SINGLE)
1691: snes->rtol = 1.e-5;
1692: #else
1693: snes->rtol = 1.e-8;
1694: #endif
1695: snes->ttol = 0.0;
1696: #if defined(PETSC_USE_REAL_SINGLE)
1697: snes->abstol = 1.e-25;
1698: #else
1699: snes->abstol = 1.e-50;
1700: #endif
1701: #if defined(PETSC_USE_REAL_SINGLE)
1702: snes->stol = 1.e-5;
1703: #else
1704: snes->stol = 1.e-8;
1705: #endif
1706: #if defined(PETSC_USE_REAL_SINGLE)
1707: snes->deltatol = 1.e-6;
1708: #else
1709: snes->deltatol = 1.e-12;
1710: #endif
1711: snes->divtol = 1.e4;
1712: snes->rnorm0 = 0;
1713: snes->nfuncs = 0;
1714: snes->numFailures = 0;
1715: snes->maxFailures = 1;
1716: snes->linear_its = 0;
1717: snes->lagjacobian = 1;
1718: snes->jac_iter = 0;
1719: snes->lagjac_persist = PETSC_FALSE;
1720: snes->lagpreconditioner = 1;
1721: snes->pre_iter = 0;
1722: snes->lagpre_persist = PETSC_FALSE;
1723: snes->numbermonitors = 0;
1724: snes->numberreasonviews = 0;
1725: snes->data = NULL;
1726: snes->setupcalled = PETSC_FALSE;
1727: snes->ksp_ewconv = PETSC_FALSE;
1728: snes->nwork = 0;
1729: snes->work = NULL;
1730: snes->nvwork = 0;
1731: snes->vwork = NULL;
1732: snes->conv_hist_len = 0;
1733: snes->conv_hist_max = 0;
1734: snes->conv_hist = NULL;
1735: snes->conv_hist_its = NULL;
1736: snes->conv_hist_reset = PETSC_TRUE;
1737: snes->counters_reset = PETSC_TRUE;
1738: snes->vec_func_init_set = PETSC_FALSE;
1739: snes->reason = SNES_CONVERGED_ITERATING;
1740: snes->npcside = PC_RIGHT;
1741: snes->setfromoptionscalled = 0;
1743: snes->mf = PETSC_FALSE;
1744: snes->mf_operator = PETSC_FALSE;
1745: snes->mf_version = 1;
1747: snes->numLinearSolveFailures = 0;
1748: snes->maxLinearSolveFailures = 1;
1750: snes->vizerotolerance = 1.e-8;
1751: snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1753: /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
1754: snes->alwayscomputesfinalresidual = PETSC_FALSE;
1756: /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
1757: PetscNewLog(snes,&kctx);
1759: snes->kspconvctx = (void*)kctx;
1760: kctx->version = 2;
1761: kctx->rtol_0 = .3; /* Eisenstat and Walker suggest rtol_0=.5, but
1762: this was too large for some test cases */
1763: kctx->rtol_last = 0.0;
1764: kctx->rtol_max = .9;
1765: kctx->gamma = 1.0;
1766: kctx->alpha = .5*(1.0 + PetscSqrtReal(5.0));
1767: kctx->alpha2 = kctx->alpha;
1768: kctx->threshold = .1;
1769: kctx->lresid_last = 0.0;
1770: kctx->norm_last = 0.0;
1772: *outsnes = snes;
1773: return 0;
1774: }
1776: /*MC
1777: SNESFunction - Functional form used to convey the nonlinear function to be solved by SNES
1779: Synopsis:
1780: #include "petscsnes.h"
1781: PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
1783: Collective on snes
1785: Input Parameters:
1786: + snes - the SNES context
1787: . x - state at which to evaluate residual
1788: - ctx - optional user-defined function context, passed in with SNESSetFunction()
1790: Output Parameter:
1791: . f - vector to put residual (function value)
1793: Level: intermediate
1795: .seealso: SNESSetFunction(), SNESGetFunction()
1796: M*/
1798: /*@C
1799: SNESSetFunction - Sets the function evaluation routine and function
1800: vector for use by the SNES routines in solving systems of nonlinear
1801: equations.
1803: Logically Collective on SNES
1805: Input Parameters:
1806: + snes - the SNES context
1807: . r - vector to store function values, may be NULL
1808: . f - function evaluation routine; see SNESFunction for calling sequence details
1809: - ctx - [optional] user-defined context for private data for the
1810: function evaluation routine (may be NULL)
1812: Notes:
1813: The Newton-like methods typically solve linear systems of the form
1814: $ f'(x) x = -f(x),
1815: where f'(x) denotes the Jacobian matrix and f(x) is the function.
1817: Level: beginner
1819: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetPicard(), SNESFunction
1820: @*/
1821: PetscErrorCode SNESSetFunction(SNES snes,Vec r,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
1822: {
1823: DM dm;
1826: if (r) {
1829: PetscObjectReference((PetscObject)r);
1830: VecDestroy(&snes->vec_func);
1831: snes->vec_func = r;
1832: }
1833: SNESGetDM(snes,&dm);
1834: DMSNESSetFunction(dm,f,ctx);
1835: if (f == SNESPicardComputeFunction) {
1836: DMSNESSetMFFunction(dm,SNESPicardComputeMFFunction,ctx);
1837: }
1838: return 0;
1839: }
1841: /*@C
1842: SNESSetInitialFunction - Sets the function vector to be used as the
1843: function norm at the initialization of the method. In some
1844: instances, the user has precomputed the function before calling
1845: SNESSolve. This function allows one to avoid a redundant call
1846: to SNESComputeFunction in that case.
1848: Logically Collective on SNES
1850: Input Parameters:
1851: + snes - the SNES context
1852: - f - vector to store function value
1854: Notes:
1855: This should not be modified during the solution procedure.
1857: This is used extensively in the SNESFAS hierarchy and in nonlinear preconditioning.
1859: Level: developer
1861: .seealso: SNESSetFunction(), SNESComputeFunction(), SNESSetInitialFunctionNorm()
1862: @*/
1863: PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1864: {
1865: Vec vec_func;
1870: if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1871: snes->vec_func_init_set = PETSC_FALSE;
1872: return 0;
1873: }
1874: SNESGetFunction(snes,&vec_func,NULL,NULL);
1875: VecCopy(f,vec_func);
1877: snes->vec_func_init_set = PETSC_TRUE;
1878: return 0;
1879: }
1881: /*@
1882: SNESSetNormSchedule - Sets the SNESNormSchedule used in convergence and monitoring
1883: of the SNES method.
1885: Logically Collective on SNES
1887: Input Parameters:
1888: + snes - the SNES context
1889: - normschedule - the frequency of norm computation
1891: Options Database Key:
1892: . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1894: Notes:
1895: Only certain SNES methods support certain SNESNormSchedules. Most require evaluation
1896: of the nonlinear function and the taking of its norm at every iteration to
1897: even ensure convergence at all. However, methods such as custom Gauss-Seidel methods
1898: (SNESNGS) and the like do not require the norm of the function to be computed, and therefore
1899: may either be monitored for convergence or not. As these are often used as nonlinear
1900: preconditioners, monitoring the norm of their error is not a useful enterprise within
1901: their solution.
1903: Level: developer
1905: .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1906: @*/
1907: PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1908: {
1910: snes->normschedule = normschedule;
1911: return 0;
1912: }
1914: /*@
1915: SNESGetNormSchedule - Gets the SNESNormSchedule used in convergence and monitoring
1916: of the SNES method.
1918: Logically Collective on SNES
1920: Input Parameters:
1921: + snes - the SNES context
1922: - normschedule - the type of the norm used
1924: Level: advanced
1926: .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1927: @*/
1928: PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1929: {
1931: *normschedule = snes->normschedule;
1932: return 0;
1933: }
1935: /*@
1936: SNESSetFunctionNorm - Sets the last computed residual norm.
1938: Logically Collective on SNES
1940: Input Parameters:
1941: + snes - the SNES context
1943: - normschedule - the frequency of norm computation
1945: Level: developer
1947: .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1948: @*/
1949: PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1950: {
1952: snes->norm = norm;
1953: return 0;
1954: }
1956: /*@
1957: SNESGetFunctionNorm - Gets the last computed norm of the residual
1959: Not Collective
1961: Input Parameter:
1962: . snes - the SNES context
1964: Output Parameter:
1965: . norm - the last computed residual norm
1967: Level: developer
1969: .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1970: @*/
1971: PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
1972: {
1975: *norm = snes->norm;
1976: return 0;
1977: }
1979: /*@
1980: SNESGetUpdateNorm - Gets the last computed norm of the Newton update
1982: Not Collective
1984: Input Parameter:
1985: . snes - the SNES context
1987: Output Parameter:
1988: . ynorm - the last computed update norm
1990: Level: developer
1992: .seealso: SNESSetNormSchedule(), SNESComputeFunction(), SNESGetFunctionNorm()
1993: @*/
1994: PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
1995: {
1998: *ynorm = snes->ynorm;
1999: return 0;
2000: }
2002: /*@
2003: SNESGetSolutionNorm - Gets the last computed norm of the solution
2005: Not Collective
2007: Input Parameter:
2008: . snes - the SNES context
2010: Output Parameter:
2011: . xnorm - the last computed solution norm
2013: Level: developer
2015: .seealso: SNESSetNormSchedule(), SNESComputeFunction(), SNESGetFunctionNorm(), SNESGetUpdateNorm()
2016: @*/
2017: PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2018: {
2021: *xnorm = snes->xnorm;
2022: return 0;
2023: }
2025: /*@C
2026: SNESSetFunctionType - Sets the SNESNormSchedule used in convergence and monitoring
2027: of the SNES method.
2029: Logically Collective on SNES
2031: Input Parameters:
2032: + snes - the SNES context
2033: - normschedule - the frequency of norm computation
2035: Notes:
2036: Only certain SNES methods support certain SNESNormSchedules. Most require evaluation
2037: of the nonlinear function and the taking of its norm at every iteration to
2038: even ensure convergence at all. However, methods such as custom Gauss-Seidel methods
2039: (SNESNGS) and the like do not require the norm of the function to be computed, and therefore
2040: may either be monitored for convergence or not. As these are often used as nonlinear
2041: preconditioners, monitoring the norm of their error is not a useful enterprise within
2042: their solution.
2044: Level: developer
2046: .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
2047: @*/
2048: PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2049: {
2051: snes->functype = type;
2052: return 0;
2053: }
2055: /*@C
2056: SNESGetFunctionType - Gets the SNESNormSchedule used in convergence and monitoring
2057: of the SNES method.
2059: Logically Collective on SNES
2061: Input Parameters:
2062: + snes - the SNES context
2063: - normschedule - the type of the norm used
2065: Level: advanced
2067: .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
2068: @*/
2069: PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2070: {
2072: *type = snes->functype;
2073: return 0;
2074: }
2076: /*MC
2077: SNESNGSFunction - function used to convey a Gauss-Seidel sweep on the nonlinear function
2079: Synopsis:
2080: #include <petscsnes.h>
2081: $ SNESNGSFunction(SNES snes,Vec x,Vec b,void *ctx);
2083: Collective on snes
2085: Input Parameters:
2086: + X - solution vector
2087: . B - RHS vector
2088: - ctx - optional user-defined Gauss-Seidel context
2090: Output Parameter:
2091: . X - solution vector
2093: Level: intermediate
2095: .seealso: SNESSetNGS(), SNESGetNGS()
2096: M*/
2098: /*@C
2099: SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2100: use with composed nonlinear solvers.
2102: Input Parameters:
2103: + snes - the SNES context
2104: . f - function evaluation routine to apply Gauss-Seidel see SNESNGSFunction
2105: - ctx - [optional] user-defined context for private data for the
2106: smoother evaluation routine (may be NULL)
2108: Notes:
2109: The NGS routines are used by the composed nonlinear solver to generate
2110: a problem appropriate update to the solution, particularly FAS.
2112: Level: intermediate
2114: .seealso: SNESGetFunction(), SNESComputeNGS()
2115: @*/
2116: PetscErrorCode SNESSetNGS(SNES snes,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
2117: {
2118: DM dm;
2121: SNESGetDM(snes,&dm);
2122: DMSNESSetNGS(dm,f,ctx);
2123: return 0;
2124: }
2126: /*
2127: This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2128: changed during the KSPSolve()
2129: */
2130: PetscErrorCode SNESPicardComputeMFFunction(SNES snes,Vec x,Vec f,void *ctx)
2131: {
2132: DM dm;
2133: DMSNES sdm;
2135: SNESGetDM(snes,&dm);
2136: DMGetDMSNES(dm,&sdm);
2138: /* A(x)*x - b(x) */
2139: if (sdm->ops->computepfunction) {
2140: PetscStackPush("SNES Picard user function");
2141: (*sdm->ops->computepfunction)(snes,x,f,sdm->pctx);
2142: PetscStackPop;
2143: VecScale(f,-1.0);
2144: if (!snes->picard) {
2145: /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2146: MatDuplicate(snes->jacobian_pre,MAT_DO_NOT_COPY_VALUES,&snes->picard);
2147: }
2148: PetscStackPush("SNES Picard user Jacobian");
2149: (*sdm->ops->computepjacobian)(snes,x,snes->picard,snes->picard,sdm->pctx);
2150: PetscStackPop;
2151: MatMultAdd(snes->picard,x,f,f);
2152: } else {
2153: PetscStackPush("SNES Picard user Jacobian");
2154: (*sdm->ops->computepjacobian)(snes,x,snes->picard,snes->picard,sdm->pctx);
2155: PetscStackPop;
2156: MatMult(snes->picard,x,f);
2157: }
2158: return 0;
2159: }
2161: PetscErrorCode SNESPicardComputeFunction(SNES snes,Vec x,Vec f,void *ctx)
2162: {
2163: DM dm;
2164: DMSNES sdm;
2166: SNESGetDM(snes,&dm);
2167: DMGetDMSNES(dm,&sdm);
2169: /* A(x)*x - b(x) */
2170: if (sdm->ops->computepfunction) {
2171: PetscStackPush("SNES Picard user function");
2172: (*sdm->ops->computepfunction)(snes,x,f,sdm->pctx);
2173: PetscStackPop;
2174: VecScale(f,-1.0);
2175: PetscStackPush("SNES Picard user Jacobian");
2176: (*sdm->ops->computepjacobian)(snes,x,snes->jacobian,snes->jacobian_pre,sdm->pctx);
2177: PetscStackPop;
2178: MatMultAdd(snes->jacobian_pre,x,f,f);
2179: } else {
2180: PetscStackPush("SNES Picard user Jacobian");
2181: (*sdm->ops->computepjacobian)(snes,x,snes->jacobian,snes->jacobian_pre,sdm->pctx);
2182: PetscStackPop;
2183: MatMult(snes->jacobian_pre,x,f);
2184: }
2185: return 0;
2186: }
2188: PetscErrorCode SNESPicardComputeJacobian(SNES snes,Vec x1,Mat J,Mat B,void *ctx)
2189: {
2190: /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2191: /* must assembly if matrix-free to get the last SNES solution */
2192: MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
2193: MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
2194: return 0;
2195: }
2197: /*@C
2198: SNESSetPicard - Use SNES to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization)
2200: Logically Collective on SNES
2202: Input Parameters:
2203: + snes - the SNES context
2204: . r - vector to store function values, may be NULL
2205: . bp - function evaluation routine, may be NULL
2206: . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2207: . Pmat - matrix from which preconditioner is computed (usually the same as Amat)
2208: . J - function to compute matrix values, see SNESJacobianFunction() for details on its calling sequence
2209: - ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
2211: Notes:
2212: It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2213: an approximate Newton solver. This interface is provided to allow porting/testing a previous Picard based code in PETSc before converting it to approximate Newton.
2215: One can call SNESSetPicard() or SNESSetFunction() (and possibly SNESSetJacobian()) but cannot call both
2217: $ Solves the equation A(x) x = bp(x) - b via the defect correction algorithm A(x^{n}) (x^{n+1} - x^{n}) = bp(x^{n}) + b - A(x^{n})x^{n}
2218: $ Note that when an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration.
2220: Run with -snes_mf_operator to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
2222: We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
2223: the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b
2225: There is some controversity over the definition of a Picard iteration for nonlinear systems but almost everyone agrees that it involves a linear solve and some
2226: believe it is the iteration A(x^{n}) x^{n+1} = b(x^{n}) hence we use the name Picard. If anyone has an authoritative reference that defines the Picard iteration
2227: different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
2229: When used with -snes_mf_operator this will run matrix-free Newton's method where the matrix-vector product is of the true Jacobian of A(x)x - bp(x) -b.
2231: When used with -snes_fd this will compute the true Jacobian (very slowly one column at at time) and thus represent Newton's method.
2233: When used with -snes_fd_coloring this will compute the Jacobian via coloring and thus represent a faster implementation of Newton's method. But the
2234: the nonzero structure of the Jacobian is, in general larger than that of the Picard matrix A so you must provide in A the needed nonzero structure for the correct
2235: coloring. When using DMDA this may mean creating the matrix A with DMCreateMatrix() using a wider stencil than strictly needed for A or with a DMDA_STENCIL_BOX.
2236: See the commment in src/snes/tutorials/ex15.c.
2238: Level: intermediate
2240: .seealso: SNESGetFunction(), SNESSetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESGetPicard(), SNESLineSearchPreCheckPicard(), SNESJacobianFunction
2241: @*/
2242: PetscErrorCode SNESSetPicard(SNES snes,Vec r,PetscErrorCode (*bp)(SNES,Vec,Vec,void*),Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
2243: {
2244: DM dm;
2247: SNESGetDM(snes, &dm);
2248: DMSNESSetPicard(dm,bp,J,ctx);
2249: DMSNESSetMFFunction(dm,SNESPicardComputeMFFunction,ctx);
2250: SNESSetFunction(snes,r,SNESPicardComputeFunction,ctx);
2251: SNESSetJacobian(snes,Amat,Pmat,SNESPicardComputeJacobian,ctx);
2252: return 0;
2253: }
2255: /*@C
2256: SNESGetPicard - Returns the context for the Picard iteration
2258: Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet.
2260: Input Parameter:
2261: . snes - the SNES context
2263: Output Parameters:
2264: + r - the function (or NULL)
2265: . f - the function (or NULL); see SNESFunction for calling sequence details
2266: . Amat - the matrix used to defined the operation A(x) x - b(x) (or NULL)
2267: . Pmat - the matrix from which the preconditioner will be constructed (or NULL)
2268: . J - the function for matrix evaluation (or NULL); see SNESJacobianFunction for calling sequence details
2269: - ctx - the function context (or NULL)
2271: Level: advanced
2273: .seealso: SNESSetPicard(), SNESGetFunction(), SNESGetJacobian(), SNESGetDM(), SNESFunction, SNESJacobianFunction
2274: @*/
2275: PetscErrorCode SNESGetPicard(SNES snes,Vec *r,PetscErrorCode (**f)(SNES,Vec,Vec,void*),Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
2276: {
2277: DM dm;
2280: SNESGetFunction(snes,r,NULL,NULL);
2281: SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);
2282: SNESGetDM(snes,&dm);
2283: DMSNESGetPicard(dm,f,J,ctx);
2284: return 0;
2285: }
2287: /*@C
2288: SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the problem
2290: Logically Collective on SNES
2292: Input Parameters:
2293: + snes - the SNES context
2294: . func - function evaluation routine
2295: - ctx - [optional] user-defined context for private data for the
2296: function evaluation routine (may be NULL)
2298: Calling sequence of func:
2299: $ func (SNES snes,Vec x,void *ctx);
2301: . f - function vector
2302: - ctx - optional user-defined function context
2304: Level: intermediate
2306: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian()
2307: @*/
2308: PetscErrorCode SNESSetComputeInitialGuess(SNES snes,PetscErrorCode (*func)(SNES,Vec,void*),void *ctx)
2309: {
2311: if (func) snes->ops->computeinitialguess = func;
2312: if (ctx) snes->initialguessP = ctx;
2313: return 0;
2314: }
2316: /* --------------------------------------------------------------- */
2317: /*@C
2318: SNESGetRhs - Gets the vector for solving F(x) = rhs. If rhs is not set
2319: it assumes a zero right hand side.
2321: Logically Collective on SNES
2323: Input Parameter:
2324: . snes - the SNES context
2326: Output Parameter:
2327: . rhs - the right hand side vector or NULL if the right hand side vector is null
2329: Level: intermediate
2331: .seealso: SNESGetSolution(), SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
2332: @*/
2333: PetscErrorCode SNESGetRhs(SNES snes,Vec *rhs)
2334: {
2337: *rhs = snes->vec_rhs;
2338: return 0;
2339: }
2341: /*@
2342: SNESComputeFunction - Calls the function that has been set with SNESSetFunction().
2344: Collective on SNES
2346: Input Parameters:
2347: + snes - the SNES context
2348: - x - input vector
2350: Output Parameter:
2351: . y - function vector, as set by SNESSetFunction()
2353: Notes:
2354: SNESComputeFunction() is typically used within nonlinear solvers
2355: implementations, so users would not generally call this routine themselves.
2357: Level: developer
2359: .seealso: SNESSetFunction(), SNESGetFunction(), SNESComputeMFFunction()
2360: @*/
2361: PetscErrorCode SNESComputeFunction(SNES snes,Vec x,Vec y)
2362: {
2363: DM dm;
2364: DMSNES sdm;
2371: VecValidValues(x,2,PETSC_TRUE);
2373: SNESGetDM(snes,&dm);
2374: DMGetDMSNES(dm,&sdm);
2375: if (sdm->ops->computefunction) {
2376: if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) {
2377: PetscLogEventBegin(SNES_FunctionEval,snes,x,y,0);
2378: }
2379: VecLockReadPush(x);
2380: PetscStackPush("SNES user function");
2381: /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2382: snes->domainerror = PETSC_FALSE;
2383: (*sdm->ops->computefunction)(snes,x,y,sdm->functionctx);
2384: PetscStackPop;
2385: VecLockReadPop(x);
2386: if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) {
2387: PetscLogEventEnd(SNES_FunctionEval,snes,x,y,0);
2388: }
2389: } else if (snes->vec_rhs) {
2390: MatMult(snes->jacobian, x, y);
2391: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve().");
2392: if (snes->vec_rhs) {
2393: VecAXPY(y,-1.0,snes->vec_rhs);
2394: }
2395: snes->nfuncs++;
2396: /*
2397: domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2398: propagate the value to all processes
2399: */
2400: if (snes->domainerror) {
2401: VecSetInf(y);
2402: }
2403: return 0;
2404: }
2406: /*@
2407: SNESComputeMFFunction - Calls the function that has been set with SNESSetMFFunction().
2409: Collective on SNES
2411: Input Parameters:
2412: + snes - the SNES context
2413: - x - input vector
2415: Output Parameter:
2416: . y - function vector, as set by SNESSetMFFunction()
2418: Notes:
2419: SNESComputeMFFunction() is used within the matrix vector products called by the matrix created with MatCreateSNESMF()
2420: so users would not generally call this routine themselves.
2422: Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with SNESSolve()
2423: while SNESComputeFunction() does. As such, this routine cannot be used with MatMFFDSetBase() with a provided F function value even if it applies the
2424: same function as SNESComputeFunction() if a SNESSolve() right hand side vector is use because the two functions difference would include this right hand side function.
2426: Level: developer
2428: .seealso: SNESSetFunction(), SNESGetFunction(), SNESComputeFunction(), MatCreateSNESMF
2429: @*/
2430: PetscErrorCode SNESComputeMFFunction(SNES snes,Vec x,Vec y)
2431: {
2432: DM dm;
2433: DMSNES sdm;
2440: VecValidValues(x,2,PETSC_TRUE);
2442: SNESGetDM(snes,&dm);
2443: DMGetDMSNES(dm,&sdm);
2444: PetscLogEventBegin(SNES_FunctionEval,snes,x,y,0);
2445: VecLockReadPush(x);
2446: PetscStackPush("SNES user function");
2447: /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2448: snes->domainerror = PETSC_FALSE;
2449: (*sdm->ops->computemffunction)(snes,x,y,sdm->mffunctionctx);
2450: PetscStackPop;
2451: VecLockReadPop(x);
2452: PetscLogEventEnd(SNES_FunctionEval,snes,x,y,0);
2453: snes->nfuncs++;
2454: /*
2455: domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2456: propagate the value to all processes
2457: */
2458: if (snes->domainerror) {
2459: VecSetInf(y);
2460: }
2461: return 0;
2462: }
2464: /*@
2465: SNESComputeNGS - Calls the Gauss-Seidel function that has been set with SNESSetNGS().
2467: Collective on SNES
2469: Input Parameters:
2470: + snes - the SNES context
2471: . x - input vector
2472: - b - rhs vector
2474: Output Parameter:
2475: . x - new solution vector
2477: Notes:
2478: SNESComputeNGS() is typically used within composed nonlinear solver
2479: implementations, so most users would not generally call this routine
2480: themselves.
2482: Level: developer
2484: .seealso: SNESSetNGS(), SNESComputeFunction()
2485: @*/
2486: PetscErrorCode SNESComputeNGS(SNES snes,Vec b,Vec x)
2487: {
2488: DM dm;
2489: DMSNES sdm;
2496: if (b) VecValidValues(b,2,PETSC_TRUE);
2497: PetscLogEventBegin(SNES_NGSEval,snes,x,b,0);
2498: SNESGetDM(snes,&dm);
2499: DMGetDMSNES(dm,&sdm);
2500: if (sdm->ops->computegs) {
2501: if (b) VecLockReadPush(b);
2502: PetscStackPush("SNES user NGS");
2503: (*sdm->ops->computegs)(snes,x,b,sdm->gsctx);
2504: PetscStackPop;
2505: if (b) VecLockReadPop(b);
2506: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
2507: PetscLogEventEnd(SNES_NGSEval,snes,x,b,0);
2508: return 0;
2509: }
2511: PetscErrorCode SNESTestJacobian(SNES snes)
2512: {
2513: Mat A,B,C,D,jacobian;
2514: Vec x = snes->vec_sol,f = snes->vec_func;
2515: PetscErrorCode ierr;
2516: PetscReal nrm,gnorm;
2517: PetscReal threshold = 1.e-5;
2518: MatType mattype;
2519: PetscInt m,n,M,N;
2520: void *functx;
2521: PetscBool complete_print = PETSC_FALSE,threshold_print = PETSC_FALSE,test = PETSC_FALSE,flg,istranspose;
2522: PetscViewer viewer,mviewer;
2523: MPI_Comm comm;
2524: PetscInt tabs;
2525: static PetscBool directionsprinted = PETSC_FALSE;
2526: PetscViewerFormat format;
2528: PetscObjectOptionsBegin((PetscObject)snes);
2529: PetscOptionsName("-snes_test_jacobian","Compare hand-coded and finite difference Jacobians","None",&test);
2530: PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold,NULL);
2531: PetscOptionsViewer("-snes_test_jacobian_view","View difference between hand-coded and finite difference Jacobians element entries","None",&mviewer,&format,&complete_print);
2532: if (!complete_print) {
2533: PetscOptionsDeprecated("-snes_test_jacobian_display","-snes_test_jacobian_view","3.13",NULL);
2534: PetscOptionsViewer("-snes_test_jacobian_display","Display difference between hand-coded and finite difference Jacobians","None",&mviewer,&format,&complete_print);
2535: }
2536: /* for compatibility with PETSc 3.9 and older. */
2537: PetscOptionsDeprecated("-snes_test_jacobian_display_threshold","-snes_test_jacobian","3.13","-snes_test_jacobian accepts an optional threshold (since v3.10)");
2538: PetscOptionsReal("-snes_test_jacobian_display_threshold", "Display difference between hand-coded and finite difference Jacobians which exceed input threshold", "None", threshold, &threshold, &threshold_print);
2539: PetscOptionsEnd();
2540: if (!test) return 0;
2542: PetscObjectGetComm((PetscObject)snes,&comm);
2543: PetscViewerASCIIGetStdout(comm,&viewer);
2544: PetscViewerASCIIGetTab(viewer, &tabs);
2545: PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel);
2546: PetscViewerASCIIPrintf(viewer," ---------- Testing Jacobian -------------\n");
2547: if (!complete_print && !directionsprinted) {
2548: PetscViewerASCIIPrintf(viewer," Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n");
2549: PetscViewerASCIIPrintf(viewer," of hand-coded and finite difference Jacobian entries greater than <threshold>.\n");
2550: }
2551: if (!directionsprinted) {
2552: PetscViewerASCIIPrintf(viewer," Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n");
2553: PetscViewerASCIIPrintf(viewer," O(1.e-8), the hand-coded Jacobian is probably correct.\n");
2554: directionsprinted = PETSC_TRUE;
2555: }
2556: if (complete_print) {
2557: PetscViewerPushFormat(mviewer,format);
2558: }
2560: PetscObjectTypeCompare((PetscObject)snes->jacobian,MATMFFD,&flg);
2561: if (!flg) jacobian = snes->jacobian;
2562: else jacobian = snes->jacobian_pre;
2564: if (!x) {
2565: MatCreateVecs(jacobian, &x, NULL);
2566: } else {
2567: PetscObjectReference((PetscObject) x);
2568: }
2569: if (!f) {
2570: VecDuplicate(x, &f);
2571: } else {
2572: PetscObjectReference((PetscObject) f);
2573: }
2574: /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
2575: SNESComputeFunction(snes,x,f);
2576: VecDestroy(&f);
2577: PetscObjectTypeCompare((PetscObject)snes,SNESKSPTRANSPOSEONLY,&istranspose);
2578: while (jacobian) {
2579: Mat JT = NULL, Jsave = NULL;
2581: if (istranspose) {
2582: MatCreateTranspose(jacobian,&JT);
2583: Jsave = jacobian;
2584: jacobian = JT;
2585: }
2586: PetscObjectBaseTypeCompareAny((PetscObject)jacobian,&flg,MATSEQAIJ,MATMPIAIJ,MATSEQDENSE,MATMPIDENSE,MATSEQBAIJ,MATMPIBAIJ,MATSEQSBAIJ,MATMPISBAIJ,"");
2587: if (flg) {
2588: A = jacobian;
2589: PetscObjectReference((PetscObject)A);
2590: } else {
2591: MatComputeOperator(jacobian,MATAIJ,&A);
2592: }
2594: MatGetType(A,&mattype);
2595: MatGetSize(A,&M,&N);
2596: MatGetLocalSize(A,&m,&n);
2597: MatCreate(PetscObjectComm((PetscObject)A),&B);
2598: MatSetType(B,mattype);
2599: MatSetSizes(B,m,n,M,N);
2600: MatSetBlockSizesFromMats(B,A,A);
2601: MatSetUp(B);
2602: MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);
2604: SNESGetFunction(snes,NULL,NULL,&functx);
2605: SNESComputeJacobianDefault(snes,x,B,B,functx);
2607: MatDuplicate(B,MAT_COPY_VALUES,&D);
2608: MatAYPX(D,-1.0,A,DIFFERENT_NONZERO_PATTERN);
2609: MatNorm(D,NORM_FROBENIUS,&nrm);
2610: MatNorm(A,NORM_FROBENIUS,&gnorm);
2611: MatDestroy(&D);
2612: if (!gnorm) gnorm = 1; /* just in case */
2613: PetscViewerASCIIPrintf(viewer," ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n",(double)(nrm/gnorm),(double)nrm);
2615: if (complete_print) {
2616: PetscViewerASCIIPrintf(viewer," Hand-coded Jacobian ----------\n");
2617: MatView(A,mviewer);
2618: PetscViewerASCIIPrintf(viewer," Finite difference Jacobian ----------\n");
2619: MatView(B,mviewer);
2620: }
2622: if (threshold_print || complete_print) {
2623: PetscInt Istart, Iend, *ccols, bncols, cncols, j, row;
2624: PetscScalar *cvals;
2625: const PetscInt *bcols;
2626: const PetscScalar *bvals;
2628: MatCreate(PetscObjectComm((PetscObject)A),&C);
2629: MatSetType(C,mattype);
2630: MatSetSizes(C,m,n,M,N);
2631: MatSetBlockSizesFromMats(C,A,A);
2632: MatSetUp(C);
2633: MatSetOption(C,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);
2635: MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);
2636: MatGetOwnershipRange(B,&Istart,&Iend);
2638: for (row = Istart; row < Iend; row++) {
2639: MatGetRow(B,row,&bncols,&bcols,&bvals);
2640: PetscMalloc2(bncols,&ccols,bncols,&cvals);
2641: for (j = 0, cncols = 0; j < bncols; j++) {
2642: if (PetscAbsScalar(bvals[j]) > threshold) {
2643: ccols[cncols] = bcols[j];
2644: cvals[cncols] = bvals[j];
2645: cncols += 1;
2646: }
2647: }
2648: if (cncols) {
2649: MatSetValues(C,1,&row,cncols,ccols,cvals,INSERT_VALUES);
2650: }
2651: MatRestoreRow(B,row,&bncols,&bcols,&bvals);
2652: PetscFree2(ccols,cvals);
2653: }
2654: MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
2655: MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
2656: PetscViewerASCIIPrintf(viewer," Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n",(double)threshold);
2657: MatView(C,complete_print ? mviewer : viewer);
2658: MatDestroy(&C);
2659: }
2660: MatDestroy(&A);
2661: MatDestroy(&B);
2662: MatDestroy(&JT);
2663: if (Jsave) jacobian = Jsave;
2664: if (jacobian != snes->jacobian_pre) {
2665: jacobian = snes->jacobian_pre;
2666: PetscViewerASCIIPrintf(viewer," ---------- Testing Jacobian for preconditioner -------------\n");
2667: }
2668: else jacobian = NULL;
2669: }
2670: VecDestroy(&x);
2671: if (complete_print) {
2672: PetscViewerPopFormat(mviewer);
2673: }
2674: if (mviewer) PetscViewerDestroy(&mviewer);
2675: PetscViewerASCIISetTab(viewer,tabs);
2676: return 0;
2677: }
2679: /*@
2680: SNESComputeJacobian - Computes the Jacobian matrix that has been set with SNESSetJacobian().
2682: Collective on SNES
2684: Input Parameters:
2685: + snes - the SNES context
2686: - x - input vector
2688: Output Parameters:
2689: + A - Jacobian matrix
2690: - B - optional preconditioning matrix
2692: Options Database Keys:
2693: + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner
2694: . -snes_lag_jacobian <lag> - how often to rebuild Jacobian
2695: . -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one compute via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold.
2696: . -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian
2697: . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2698: . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2699: . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
2700: . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix
2701: . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference
2702: . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences
2703: . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold
2704: . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold
2705: . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold
2706: . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences
2707: - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2709: Notes:
2710: Most users should not need to explicitly call this routine, as it
2711: is used internally within the nonlinear solvers.
2713: Developer Notes:
2714: This has duplicative ways of checking the accuracy of the user provided Jacobian (see the options above). This is for historical reasons, the routine SNESTestJacobian() use to used
2715: for with the SNESType of test that has been removed.
2717: Level: developer
2719: .seealso: SNESSetJacobian(), KSPSetOperators(), MatStructure, SNESSetLagPreconditioner(), SNESSetLagJacobian()
2720: @*/
2721: PetscErrorCode SNESComputeJacobian(SNES snes,Vec X,Mat A,Mat B)
2722: {
2723: PetscBool flag;
2724: DM dm;
2725: DMSNES sdm;
2726: KSP ksp;
2731: VecValidValues(X,2,PETSC_TRUE);
2732: SNESGetDM(snes,&dm);
2733: DMGetDMSNES(dm,&sdm);
2737: /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
2739: if (snes->lagjacobian == -2) {
2740: snes->lagjacobian = -1;
2742: PetscInfo(snes,"Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n");
2743: } else if (snes->lagjacobian == -1) {
2744: PetscInfo(snes,"Reusing Jacobian/preconditioner because lag is -1\n");
2745: PetscObjectTypeCompare((PetscObject)A,MATMFFD,&flag);
2746: if (flag) {
2747: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
2748: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
2749: }
2750: return 0;
2751: } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
2752: PetscInfo(snes,"Reusing Jacobian/preconditioner because lag is %D and SNES iteration is %D\n",snes->lagjacobian,snes->iter);
2753: PetscObjectTypeCompare((PetscObject)A,MATMFFD,&flag);
2754: if (flag) {
2755: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
2756: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
2757: }
2758: return 0;
2759: }
2760: if (snes->npc && snes->npcside == PC_LEFT) {
2761: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
2762: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
2763: return 0;
2764: }
2766: PetscLogEventBegin(SNES_JacobianEval,snes,X,A,B);
2767: VecLockReadPush(X);
2768: PetscStackPush("SNES user Jacobian function");
2769: (*sdm->ops->computejacobian)(snes,X,A,B,sdm->jacobianctx);
2770: PetscStackPop;
2771: VecLockReadPop(X);
2772: PetscLogEventEnd(SNES_JacobianEval,snes,X,A,B);
2774: /* attach latest linearization point to the preconditioning matrix */
2775: PetscObjectCompose((PetscObject)B,"__SNES_latest_X",(PetscObject)X);
2777: /* the next line ensures that snes->ksp exists */
2778: SNESGetKSP(snes,&ksp);
2779: if (snes->lagpreconditioner == -2) {
2780: PetscInfo(snes,"Rebuilding preconditioner exactly once since lag is -2\n");
2781: KSPSetReusePreconditioner(snes->ksp,PETSC_FALSE);
2782: snes->lagpreconditioner = -1;
2783: } else if (snes->lagpreconditioner == -1) {
2784: PetscInfo(snes,"Reusing preconditioner because lag is -1\n");
2785: KSPSetReusePreconditioner(snes->ksp,PETSC_TRUE);
2786: } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
2787: PetscInfo(snes,"Reusing preconditioner because lag is %D and SNES iteration is %D\n",snes->lagpreconditioner,snes->iter);
2788: KSPSetReusePreconditioner(snes->ksp,PETSC_TRUE);
2789: } else {
2790: PetscInfo(snes,"Rebuilding preconditioner\n");
2791: KSPSetReusePreconditioner(snes->ksp,PETSC_FALSE);
2792: }
2794: SNESTestJacobian(snes);
2795: /* make sure user returned a correct Jacobian and preconditioner */
2798: {
2799: PetscBool flag = PETSC_FALSE,flag_draw = PETSC_FALSE,flag_contour = PETSC_FALSE,flag_operator = PETSC_FALSE;
2800: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,"-snes_compare_explicit",NULL,NULL,&flag);
2801: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,"-snes_compare_explicit_draw",NULL,NULL,&flag_draw);
2802: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,"-snes_compare_explicit_draw_contour",NULL,NULL,&flag_contour);
2803: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,"-snes_compare_operator",NULL,NULL,&flag_operator);
2804: if (flag || flag_draw || flag_contour) {
2805: Mat Bexp_mine = NULL,Bexp,FDexp;
2806: PetscViewer vdraw,vstdout;
2807: PetscBool flg;
2808: if (flag_operator) {
2809: MatComputeOperator(A,MATAIJ,&Bexp_mine);
2810: Bexp = Bexp_mine;
2811: } else {
2812: /* See if the preconditioning matrix can be viewed and added directly */
2813: PetscObjectBaseTypeCompareAny((PetscObject)B,&flg,MATSEQAIJ,MATMPIAIJ,MATSEQDENSE,MATMPIDENSE,MATSEQBAIJ,MATMPIBAIJ,MATSEQSBAIJ,MATMPIBAIJ,"");
2814: if (flg) Bexp = B;
2815: else {
2816: /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
2817: MatComputeOperator(B,MATAIJ,&Bexp_mine);
2818: Bexp = Bexp_mine;
2819: }
2820: }
2821: MatConvert(Bexp,MATSAME,MAT_INITIAL_MATRIX,&FDexp);
2822: SNESComputeJacobianDefault(snes,X,FDexp,FDexp,NULL);
2823: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&vstdout);
2824: if (flag_draw || flag_contour) {
2825: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),NULL,"Explicit Jacobians",PETSC_DECIDE,PETSC_DECIDE,300,300,&vdraw);
2826: if (flag_contour) PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);
2827: } else vdraw = NULL;
2828: PetscViewerASCIIPrintf(vstdout,"Explicit %s\n",flag_operator ? "Jacobian" : "preconditioning Jacobian");
2829: if (flag) MatView(Bexp,vstdout);
2830: if (vdraw) MatView(Bexp,vdraw);
2831: PetscViewerASCIIPrintf(vstdout,"Finite difference Jacobian\n");
2832: if (flag) MatView(FDexp,vstdout);
2833: if (vdraw) MatView(FDexp,vdraw);
2834: MatAYPX(FDexp,-1.0,Bexp,SAME_NONZERO_PATTERN);
2835: PetscViewerASCIIPrintf(vstdout,"User-provided matrix minus finite difference Jacobian\n");
2836: if (flag) MatView(FDexp,vstdout);
2837: if (vdraw) { /* Always use contour for the difference */
2838: PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);
2839: MatView(FDexp,vdraw);
2840: PetscViewerPopFormat(vdraw);
2841: }
2842: if (flag_contour) PetscViewerPopFormat(vdraw);
2843: PetscViewerDestroy(&vdraw);
2844: MatDestroy(&Bexp_mine);
2845: MatDestroy(&FDexp);
2846: }
2847: }
2848: {
2849: PetscBool flag = PETSC_FALSE,flag_display = PETSC_FALSE,flag_draw = PETSC_FALSE,flag_contour = PETSC_FALSE,flag_threshold = PETSC_FALSE;
2850: PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON,threshold_rtol = 10*PETSC_SQRT_MACHINE_EPSILON;
2851: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring",NULL,NULL,&flag);
2852: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_display",NULL,NULL,&flag_display);
2853: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_draw",NULL,NULL,&flag_draw);
2854: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_draw_contour",NULL,NULL,&flag_contour);
2855: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold",NULL,NULL,&flag_threshold);
2856: if (flag_threshold) {
2857: PetscOptionsGetReal(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold_rtol",&threshold_rtol,NULL);
2858: PetscOptionsGetReal(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold_atol",&threshold_atol,NULL);
2859: }
2860: if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
2861: Mat Bfd;
2862: PetscViewer vdraw,vstdout;
2863: MatColoring coloring;
2864: ISColoring iscoloring;
2865: MatFDColoring matfdcoloring;
2866: PetscErrorCode (*func)(SNES,Vec,Vec,void*);
2867: void *funcctx;
2868: PetscReal norm1,norm2,normmax;
2870: MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&Bfd);
2871: MatColoringCreate(Bfd,&coloring);
2872: MatColoringSetType(coloring,MATCOLORINGSL);
2873: MatColoringSetFromOptions(coloring);
2874: MatColoringApply(coloring,&iscoloring);
2875: MatColoringDestroy(&coloring);
2876: MatFDColoringCreate(Bfd,iscoloring,&matfdcoloring);
2877: MatFDColoringSetFromOptions(matfdcoloring);
2878: MatFDColoringSetUp(Bfd,iscoloring,matfdcoloring);
2879: ISColoringDestroy(&iscoloring);
2881: /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
2882: SNESGetFunction(snes,NULL,&func,&funcctx);
2883: MatFDColoringSetFunction(matfdcoloring,(PetscErrorCode (*)(void))func,funcctx);
2884: PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring,((PetscObject)snes)->prefix);
2885: PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring,"coloring_");
2886: MatFDColoringSetFromOptions(matfdcoloring);
2887: MatFDColoringApply(Bfd,matfdcoloring,X,snes);
2888: MatFDColoringDestroy(&matfdcoloring);
2890: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&vstdout);
2891: if (flag_draw || flag_contour) {
2892: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),NULL,"Colored Jacobians",PETSC_DECIDE,PETSC_DECIDE,300,300,&vdraw);
2893: if (flag_contour) PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);
2894: } else vdraw = NULL;
2895: PetscViewerASCIIPrintf(vstdout,"Explicit preconditioning Jacobian\n");
2896: if (flag_display) MatView(B,vstdout);
2897: if (vdraw) MatView(B,vdraw);
2898: PetscViewerASCIIPrintf(vstdout,"Colored Finite difference Jacobian\n");
2899: if (flag_display) MatView(Bfd,vstdout);
2900: if (vdraw) MatView(Bfd,vdraw);
2901: MatAYPX(Bfd,-1.0,B,SAME_NONZERO_PATTERN);
2902: MatNorm(Bfd,NORM_1,&norm1);
2903: MatNorm(Bfd,NORM_FROBENIUS,&norm2);
2904: MatNorm(Bfd,NORM_MAX,&normmax);
2905: PetscViewerASCIIPrintf(vstdout,"User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n",(double)norm1,(double)norm2,(double)normmax);
2906: if (flag_display) MatView(Bfd,vstdout);
2907: if (vdraw) { /* Always use contour for the difference */
2908: PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);
2909: MatView(Bfd,vdraw);
2910: PetscViewerPopFormat(vdraw);
2911: }
2912: if (flag_contour) PetscViewerPopFormat(vdraw);
2914: if (flag_threshold) {
2915: PetscInt bs,rstart,rend,i;
2916: MatGetBlockSize(B,&bs);
2917: MatGetOwnershipRange(B,&rstart,&rend);
2918: for (i=rstart; i<rend; i++) {
2919: const PetscScalar *ba,*ca;
2920: const PetscInt *bj,*cj;
2921: PetscInt bn,cn,j,maxentrycol = -1,maxdiffcol = -1,maxrdiffcol = -1;
2922: PetscReal maxentry = 0,maxdiff = 0,maxrdiff = 0;
2923: MatGetRow(B,i,&bn,&bj,&ba);
2924: MatGetRow(Bfd,i,&cn,&cj,&ca);
2926: for (j=0; j<bn; j++) {
2927: PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol*PetscAbsScalar(ba[j]));
2928: if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
2929: maxentrycol = bj[j];
2930: maxentry = PetscRealPart(ba[j]);
2931: }
2932: if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
2933: maxdiffcol = bj[j];
2934: maxdiff = PetscRealPart(ca[j]);
2935: }
2936: if (rdiff > maxrdiff) {
2937: maxrdiffcol = bj[j];
2938: maxrdiff = rdiff;
2939: }
2940: }
2941: if (maxrdiff > 1) {
2942: PetscViewerASCIIPrintf(vstdout,"row %D (maxentry=%g at %D, maxdiff=%g at %D, maxrdiff=%g at %D):",i,(double)maxentry,maxentrycol,(double)maxdiff,maxdiffcol,(double)maxrdiff,maxrdiffcol);
2943: for (j=0; j<bn; j++) {
2944: PetscReal rdiff;
2945: rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol*PetscAbsScalar(ba[j]));
2946: if (rdiff > 1) {
2947: PetscViewerASCIIPrintf(vstdout," (%D,%g:%g)",bj[j],(double)PetscRealPart(ba[j]),(double)PetscRealPart(ca[j]));
2948: }
2949: }
2950: PetscViewerASCIIPrintf(vstdout,"\n",i,maxentry,maxdiff,maxrdiff);
2951: }
2952: MatRestoreRow(B,i,&bn,&bj,&ba);
2953: MatRestoreRow(Bfd,i,&cn,&cj,&ca);
2954: }
2955: }
2956: PetscViewerDestroy(&vdraw);
2957: MatDestroy(&Bfd);
2958: }
2959: }
2960: return 0;
2961: }
2963: /*MC
2964: SNESJacobianFunction - Function used to convey the nonlinear Jacobian of the function to be solved by SNES
2966: Synopsis:
2967: #include "petscsnes.h"
2968: PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
2970: Collective on snes
2972: Input Parameters:
2973: + x - input vector, the Jacobian is to be computed at this value
2974: - ctx - [optional] user-defined Jacobian context
2976: Output Parameters:
2977: + Amat - the matrix that defines the (approximate) Jacobian
2978: - Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
2980: Level: intermediate
2982: .seealso: SNESSetFunction(), SNESGetFunction(), SNESSetJacobian(), SNESGetJacobian()
2983: M*/
2985: /*@C
2986: SNESSetJacobian - Sets the function to compute Jacobian as well as the
2987: location to store the matrix.
2989: Logically Collective on SNES
2991: Input Parameters:
2992: + snes - the SNES context
2993: . Amat - the matrix that defines the (approximate) Jacobian
2994: . Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
2995: . J - Jacobian evaluation routine (if NULL then SNES retains any previously set value), see SNESJacobianFunction for details
2996: - ctx - [optional] user-defined context for private data for the
2997: Jacobian evaluation routine (may be NULL) (if NULL then SNES retains any previously set value)
2999: Notes:
3000: If the Amat matrix and Pmat matrix are different you must call MatAssemblyBegin/End() on
3001: each matrix.
3003: If you know the operator Amat has a null space you can use MatSetNullSpace() and MatSetTransposeNullSpace() to supply the null
3004: space to Amat and the KSP solvers will automatically use that null space as needed during the solution process.
3006: If using SNESComputeJacobianDefaultColor() to assemble a Jacobian, the ctx argument
3007: must be a MatFDColoring.
3009: Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common
3010: example is to use the "Picard linearization" which only differentiates through the highest order parts of each term.
3012: Level: beginner
3014: .seealso: KSPSetOperators(), SNESSetFunction(), MatMFFDComputeJacobian(), SNESComputeJacobianDefaultColor(), MatStructure, J,
3015: SNESSetPicard(), SNESJacobianFunction
3016: @*/
3017: PetscErrorCode SNESSetJacobian(SNES snes,Mat Amat,Mat Pmat,PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
3018: {
3019: DM dm;
3026: SNESGetDM(snes,&dm);
3027: DMSNESSetJacobian(dm,J,ctx);
3028: if (Amat) {
3029: PetscObjectReference((PetscObject)Amat);
3030: MatDestroy(&snes->jacobian);
3032: snes->jacobian = Amat;
3033: }
3034: if (Pmat) {
3035: PetscObjectReference((PetscObject)Pmat);
3036: MatDestroy(&snes->jacobian_pre);
3038: snes->jacobian_pre = Pmat;
3039: }
3040: return 0;
3041: }
3043: /*@C
3044: SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3045: provided context for evaluating the Jacobian.
3047: Not Collective, but Mat object will be parallel if SNES object is
3049: Input Parameter:
3050: . snes - the nonlinear solver context
3052: Output Parameters:
3053: + Amat - location to stash (approximate) Jacobian matrix (or NULL)
3054: . Pmat - location to stash matrix used to compute the preconditioner (or NULL)
3055: . J - location to put Jacobian function (or NULL), see SNESJacobianFunction for details on its calling sequence
3056: - ctx - location to stash Jacobian ctx (or NULL)
3058: Level: advanced
3060: .seealso: SNESSetJacobian(), SNESComputeJacobian(), SNESJacobianFunction, SNESGetFunction()
3061: @*/
3062: PetscErrorCode SNESGetJacobian(SNES snes,Mat *Amat,Mat *Pmat,PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
3063: {
3064: DM dm;
3065: DMSNES sdm;
3068: if (Amat) *Amat = snes->jacobian;
3069: if (Pmat) *Pmat = snes->jacobian_pre;
3070: SNESGetDM(snes,&dm);
3071: DMGetDMSNES(dm,&sdm);
3072: if (J) *J = sdm->ops->computejacobian;
3073: if (ctx) *ctx = sdm->jacobianctx;
3074: return 0;
3075: }
3077: static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3078: {
3079: DM dm;
3080: DMSNES sdm;
3082: SNESGetDM(snes,&dm);
3083: DMGetDMSNES(dm,&sdm);
3084: if (!sdm->ops->computejacobian && snes->jacobian_pre) {
3085: DM dm;
3086: PetscBool isdense,ismf;
3088: SNESGetDM(snes,&dm);
3089: PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre,&isdense,MATSEQDENSE,MATMPIDENSE,MATDENSE,NULL);
3090: PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre,&ismf,MATMFFD,MATSHELL,NULL);
3091: if (isdense) {
3092: DMSNESSetJacobian(dm,SNESComputeJacobianDefault,NULL);
3093: } else if (!ismf) {
3094: DMSNESSetJacobian(dm,SNESComputeJacobianDefaultColor,NULL);
3095: }
3096: }
3097: return 0;
3098: }
3100: /*@
3101: SNESSetUp - Sets up the internal data structures for the later use
3102: of a nonlinear solver.
3104: Collective on SNES
3106: Input Parameters:
3107: . snes - the SNES context
3109: Notes:
3110: For basic use of the SNES solvers the user need not explicitly call
3111: SNESSetUp(), since these actions will automatically occur during
3112: the call to SNESSolve(). However, if one wishes to control this
3113: phase separately, SNESSetUp() should be called after SNESCreate()
3114: and optional routines of the form SNESSetXXX(), but before SNESSolve().
3116: Level: advanced
3118: .seealso: SNESCreate(), SNESSolve(), SNESDestroy()
3119: @*/
3120: PetscErrorCode SNESSetUp(SNES snes)
3121: {
3122: DM dm;
3123: DMSNES sdm;
3124: SNESLineSearch linesearch, pclinesearch;
3125: void *lsprectx,*lspostctx;
3126: PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*);
3127: PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*);
3128: PetscErrorCode (*func)(SNES,Vec,Vec,void*);
3129: Vec f,fpc;
3130: void *funcctx;
3131: PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*);
3132: void *jacctx,*appctx;
3133: Mat j,jpre;
3136: if (snes->setupcalled) return 0;
3137: PetscLogEventBegin(SNES_Setup,snes,0,0,0);
3139: if (!((PetscObject)snes)->type_name) {
3140: SNESSetType(snes,SNESNEWTONLS);
3141: }
3143: SNESGetFunction(snes,&snes->vec_func,NULL,NULL);
3145: SNESGetDM(snes,&dm);
3146: DMGetDMSNES(dm,&sdm);
3148: SNESSetDefaultComputeJacobian(snes);
3150: if (!snes->vec_func) {
3151: DMCreateGlobalVector(dm,&snes->vec_func);
3152: }
3154: if (!snes->ksp) {
3155: SNESGetKSP(snes, &snes->ksp);
3156: }
3158: if (snes->linesearch) {
3159: SNESGetLineSearch(snes, &snes->linesearch);
3160: SNESLineSearchSetFunction(snes->linesearch,SNESComputeFunction);
3161: }
3163: if (snes->npc && snes->npcside == PC_LEFT) {
3164: snes->mf = PETSC_TRUE;
3165: snes->mf_operator = PETSC_FALSE;
3166: }
3168: if (snes->npc) {
3169: /* copy the DM over */
3170: SNESGetDM(snes,&dm);
3171: SNESSetDM(snes->npc,dm);
3173: SNESGetFunction(snes,&f,&func,&funcctx);
3174: VecDuplicate(f,&fpc);
3175: SNESSetFunction(snes->npc,fpc,func,funcctx);
3176: SNESGetJacobian(snes,&j,&jpre,&jac,&jacctx);
3177: SNESSetJacobian(snes->npc,j,jpre,jac,jacctx);
3178: SNESGetApplicationContext(snes,&appctx);
3179: SNESSetApplicationContext(snes->npc,appctx);
3180: VecDestroy(&fpc);
3182: /* copy the function pointers over */
3183: PetscObjectCopyFortranFunctionPointers((PetscObject)snes,(PetscObject)snes->npc);
3185: /* default to 1 iteration */
3186: SNESSetTolerances(snes->npc,0.0,0.0,0.0,1,snes->npc->max_funcs);
3187: if (snes->npcside == PC_RIGHT) {
3188: SNESSetNormSchedule(snes->npc,SNES_NORM_FINAL_ONLY);
3189: } else {
3190: SNESSetNormSchedule(snes->npc,SNES_NORM_NONE);
3191: }
3192: SNESSetFromOptions(snes->npc);
3194: /* copy the line search context over */
3195: if (snes->linesearch && snes->npc->linesearch) {
3196: SNESGetLineSearch(snes,&linesearch);
3197: SNESGetLineSearch(snes->npc,&pclinesearch);
3198: SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);
3199: SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);
3200: SNESLineSearchSetPreCheck(pclinesearch,precheck,lsprectx);
3201: SNESLineSearchSetPostCheck(pclinesearch,postcheck,lspostctx);
3202: PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch);
3203: }
3204: }
3205: if (snes->mf) {
3206: SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version);
3207: }
3208: if (snes->ops->usercompute && !snes->user) {
3209: (*snes->ops->usercompute)(snes,(void**)&snes->user);
3210: }
3212: snes->jac_iter = 0;
3213: snes->pre_iter = 0;
3215: if (snes->ops->setup) {
3216: (*snes->ops->setup)(snes);
3217: }
3219: SNESSetDefaultComputeJacobian(snes);
3221: if (snes->npc && snes->npcside == PC_LEFT) {
3222: if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3223: if (snes->linesearch) {
3224: SNESGetLineSearch(snes,&linesearch);
3225: SNESLineSearchSetFunction(linesearch,SNESComputeFunctionDefaultNPC);
3226: }
3227: }
3228: }
3229: PetscLogEventEnd(SNES_Setup,snes,0,0,0);
3230: snes->setupcalled = PETSC_TRUE;
3231: return 0;
3232: }
3234: /*@
3235: SNESReset - Resets a SNES context to the snessetupcalled = 0 state and removes any allocated Vecs and Mats
3237: Collective on SNES
3239: Input Parameter:
3240: . snes - iterative context obtained from SNESCreate()
3242: Level: intermediate
3244: Notes:
3245: Also calls the application context destroy routine set with SNESSetComputeApplicationContext()
3247: .seealso: SNESCreate(), SNESSetUp(), SNESSolve()
3248: @*/
3249: PetscErrorCode SNESReset(SNES snes)
3250: {
3252: if (snes->ops->userdestroy && snes->user) {
3253: (*snes->ops->userdestroy)((void**)&snes->user);
3254: snes->user = NULL;
3255: }
3256: if (snes->npc) {
3257: SNESReset(snes->npc);
3258: }
3260: if (snes->ops->reset) {
3261: (*snes->ops->reset)(snes);
3262: }
3263: if (snes->ksp) {
3264: KSPReset(snes->ksp);
3265: }
3267: if (snes->linesearch) {
3268: SNESLineSearchReset(snes->linesearch);
3269: }
3271: VecDestroy(&snes->vec_rhs);
3272: VecDestroy(&snes->vec_sol);
3273: VecDestroy(&snes->vec_sol_update);
3274: VecDestroy(&snes->vec_func);
3275: MatDestroy(&snes->jacobian);
3276: MatDestroy(&snes->jacobian_pre);
3277: MatDestroy(&snes->picard);
3278: VecDestroyVecs(snes->nwork,&snes->work);
3279: VecDestroyVecs(snes->nvwork,&snes->vwork);
3281: snes->alwayscomputesfinalresidual = PETSC_FALSE;
3283: snes->nwork = snes->nvwork = 0;
3284: snes->setupcalled = PETSC_FALSE;
3285: return 0;
3286: }
3288: /*@
3289: SNESConvergedReasonViewCancel - Clears all the reasonview functions for a SNES object.
3291: Collective on SNES
3293: Input Parameter:
3294: . snes - iterative context obtained from SNESCreate()
3296: Level: intermediate
3298: .seealso: SNESCreate(), SNESDestroy(), SNESReset()
3299: @*/
3300: PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3301: {
3302: PetscInt i;
3305: for (i=0; i<snes->numberreasonviews; i++) {
3306: if (snes->reasonviewdestroy[i]) {
3307: (*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]);
3308: }
3309: }
3310: snes->numberreasonviews = 0;
3311: return 0;
3312: }
3314: /*@C
3315: SNESDestroy - Destroys the nonlinear solver context that was created
3316: with SNESCreate().
3318: Collective on SNES
3320: Input Parameter:
3321: . snes - the SNES context
3323: Level: beginner
3325: .seealso: SNESCreate(), SNESSolve()
3326: @*/
3327: PetscErrorCode SNESDestroy(SNES *snes)
3328: {
3329: if (!*snes) return 0;
3331: if (--((PetscObject)(*snes))->refct > 0) {*snes = NULL; return 0;}
3333: SNESReset((*snes));
3334: SNESDestroy(&(*snes)->npc);
3336: /* if memory was published with SAWs then destroy it */
3337: PetscObjectSAWsViewOff((PetscObject)*snes);
3338: if ((*snes)->ops->destroy) (*((*snes))->ops->destroy)((*snes));
3340: if ((*snes)->dm) DMCoarsenHookRemove((*snes)->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,*snes);
3341: DMDestroy(&(*snes)->dm);
3342: KSPDestroy(&(*snes)->ksp);
3343: SNESLineSearchDestroy(&(*snes)->linesearch);
3345: PetscFree((*snes)->kspconvctx);
3346: if ((*snes)->ops->convergeddestroy) {
3347: (*(*snes)->ops->convergeddestroy)((*snes)->cnvP);
3348: }
3349: if ((*snes)->conv_hist_alloc) {
3350: PetscFree2((*snes)->conv_hist,(*snes)->conv_hist_its);
3351: }
3352: SNESMonitorCancel((*snes));
3353: SNESConvergedReasonViewCancel((*snes));
3354: PetscHeaderDestroy(snes);
3355: return 0;
3356: }
3358: /* ----------- Routines to set solver parameters ---------- */
3360: /*@
3361: SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3363: Logically Collective on SNES
3365: Input Parameters:
3366: + snes - the SNES context
3367: - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3368: the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3370: Options Database Keys:
3371: + -snes_lag_jacobian_persists <true,false> - sets the persistence
3372: . -snes_lag_jacobian <-2,1,2,...> - sets the lag
3373: . -snes_lag_preconditioner_persists <true,false> - sets the persistence
3374: - -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3376: Notes:
3377: The default is 1
3378: The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or SNESSetLagPreconditionerPersists() was called
3380: SNESSetLagPreconditionerPersists() allows using the same uniform lagging (for example every second solve) across multiple solves.
3382: Level: intermediate
3384: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESSetLagPreconditionerPersists(),
3385: SNESSetLagJacobianPersists()
3387: @*/
3388: PetscErrorCode SNESSetLagPreconditioner(SNES snes,PetscInt lag)
3389: {
3394: snes->lagpreconditioner = lag;
3395: return 0;
3396: }
3398: /*@
3399: SNESSetGridSequence - sets the number of steps of grid sequencing that SNES does
3401: Logically Collective on SNES
3403: Input Parameters:
3404: + snes - the SNES context
3405: - steps - the number of refinements to do, defaults to 0
3407: Options Database Keys:
3408: . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3410: Level: intermediate
3412: Notes:
3413: Use SNESGetSolution() to extract the fine grid solution after grid sequencing.
3415: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetGridSequence()
3417: @*/
3418: PetscErrorCode SNESSetGridSequence(SNES snes,PetscInt steps)
3419: {
3422: snes->gridsequence = steps;
3423: return 0;
3424: }
3426: /*@
3427: SNESGetGridSequence - gets the number of steps of grid sequencing that SNES does
3429: Logically Collective on SNES
3431: Input Parameter:
3432: . snes - the SNES context
3434: Output Parameter:
3435: . steps - the number of refinements to do, defaults to 0
3437: Options Database Keys:
3438: . -snes_grid_sequence <steps> - set number of refinements
3440: Level: intermediate
3442: Notes:
3443: Use SNESGetSolution() to extract the fine grid solution after grid sequencing.
3445: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESSetGridSequence()
3447: @*/
3448: PetscErrorCode SNESGetGridSequence(SNES snes,PetscInt *steps)
3449: {
3451: *steps = snes->gridsequence;
3452: return 0;
3453: }
3455: /*@
3456: SNESGetLagPreconditioner - Indicates how often the preconditioner is rebuilt
3458: Not Collective
3460: Input Parameter:
3461: . snes - the SNES context
3463: Output Parameter:
3464: . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3465: the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3467: Options Database Keys:
3468: + -snes_lag_jacobian_persists <true,false> - sets the persistence
3469: . -snes_lag_jacobian <-2,1,2,...> - sets the lag
3470: . -snes_lag_preconditioner_persists <true,false> - sets the persistence
3471: - -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3473: Notes:
3474: The default is 1
3475: The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3477: Level: intermediate
3479: .seealso: SNESSetTrustRegionTolerance(), SNESSetLagPreconditioner(), SNESSetLagJacobianPersists(), SNESSetLagPreconditionerPersists()
3481: @*/
3482: PetscErrorCode SNESGetLagPreconditioner(SNES snes,PetscInt *lag)
3483: {
3485: *lag = snes->lagpreconditioner;
3486: return 0;
3487: }
3489: /*@
3490: SNESSetLagJacobian - Determines when the Jacobian is rebuilt in the nonlinear solve. See SNESSetLagPreconditioner() for determining how
3491: often the preconditioner is rebuilt.
3493: Logically Collective on SNES
3495: Input Parameters:
3496: + snes - the SNES context
3497: - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3498: the Jacobian is built etc. -2 means rebuild at next chance but then never again
3500: Options Database Keys:
3501: + -snes_lag_jacobian_persists <true,false> - sets the persistence
3502: . -snes_lag_jacobian <-2,1,2,...> - sets the lag
3503: . -snes_lag_preconditioner_persists <true,false> - sets the persistence
3504: - -snes_lag_preconditioner <-2,1,2,...> - sets the lag.
3506: Notes:
3507: The default is 1
3508: The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3509: 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
3510: at the next Newton step but never again (unless it is reset to another value)
3512: Level: intermediate
3514: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagPreconditioner(), SNESGetLagJacobianPersists(), SNESSetLagPreconditionerPersists()
3516: @*/
3517: PetscErrorCode SNESSetLagJacobian(SNES snes,PetscInt lag)
3518: {
3523: snes->lagjacobian = lag;
3524: return 0;
3525: }
3527: /*@
3528: SNESGetLagJacobian - Indicates how often the Jacobian is rebuilt. See SNESGetLagPreconditioner() to determine when the preconditioner is rebuilt
3530: Not Collective
3532: Input Parameter:
3533: . snes - the SNES context
3535: Output Parameter:
3536: . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3537: the Jacobian is built etc.
3539: Notes:
3540: The default is 1
3541: The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or SNESSetLagJacobianPersists() was called.
3543: Level: intermediate
3545: .seealso: SNESSetTrustRegionTolerance(), SNESSetLagJacobian(), SNESSetLagPreconditioner(), SNESGetLagPreconditioner(), SNESSetLagJacobianPersists(), SNESSetLagPreconditionerPersists()
3547: @*/
3548: PetscErrorCode SNESGetLagJacobian(SNES snes,PetscInt *lag)
3549: {
3551: *lag = snes->lagjacobian;
3552: return 0;
3553: }
3555: /*@
3556: SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple solves
3558: Logically collective on SNES
3560: Input Parameters:
3561: + snes - the SNES context
3562: - flg - jacobian lagging persists if true
3564: Options Database Keys:
3565: + -snes_lag_jacobian_persists <true,false> - sets the persistence
3566: . -snes_lag_jacobian <-2,1,2,...> - sets the lag
3567: . -snes_lag_preconditioner_persists <true,false> - sets the persistence
3568: - -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3570: Notes:
3571: This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
3572: several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
3573: timesteps may present huge efficiency gains.
3575: Level: developer
3577: .seealso: SNESSetLagPreconditionerPersists(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetNPC(), SNESSetLagJacobianPersists()
3579: @*/
3580: PetscErrorCode SNESSetLagJacobianPersists(SNES snes,PetscBool flg)
3581: {
3584: snes->lagjac_persist = flg;
3585: return 0;
3586: }
3588: /*@
3589: SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
3591: Logically Collective on SNES
3593: Input Parameters:
3594: + snes - the SNES context
3595: - flg - preconditioner lagging persists if true
3597: Options Database Keys:
3598: + -snes_lag_jacobian_persists <true,false> - sets the persistence
3599: . -snes_lag_jacobian <-2,1,2,...> - sets the lag
3600: . -snes_lag_preconditioner_persists <true,false> - sets the persistence
3601: - -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3603: Notes:
3604: This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
3605: by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
3606: several timesteps may present huge efficiency gains.
3608: Level: developer
3610: .seealso: SNESSetLagJacobianPersists(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetNPC(), SNESSetLagPreconditioner()
3612: @*/
3613: PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes,PetscBool flg)
3614: {
3617: snes->lagpre_persist = flg;
3618: return 0;
3619: }
3621: /*@
3622: SNESSetForceIteration - force SNESSolve() to take at least one iteration regardless of the initial residual norm
3624: Logically Collective on SNES
3626: Input Parameters:
3627: + snes - the SNES context
3628: - force - PETSC_TRUE require at least one iteration
3630: Options Database Keys:
3631: . -snes_force_iteration <force> - Sets forcing an iteration
3633: Notes:
3634: This is used sometimes with TS to prevent TS from detecting a false steady state solution
3636: Level: intermediate
3638: .seealso: SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance()
3639: @*/
3640: PetscErrorCode SNESSetForceIteration(SNES snes,PetscBool force)
3641: {
3643: snes->forceiteration = force;
3644: return 0;
3645: }
3647: /*@
3648: SNESGetForceIteration - Whether or not to force SNESSolve() take at least one iteration regardless of the initial residual norm
3650: Logically Collective on SNES
3652: Input Parameters:
3653: . snes - the SNES context
3655: Output Parameter:
3656: . force - PETSC_TRUE requires at least one iteration.
3658: Level: intermediate
3660: .seealso: SNESSetForceIteration(), SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance()
3661: @*/
3662: PetscErrorCode SNESGetForceIteration(SNES snes,PetscBool *force)
3663: {
3665: *force = snes->forceiteration;
3666: return 0;
3667: }
3669: /*@
3670: SNESSetTolerances - Sets various parameters used in convergence tests.
3672: Logically Collective on SNES
3674: Input Parameters:
3675: + snes - the SNES context
3676: . abstol - absolute convergence tolerance
3677: . rtol - relative convergence tolerance
3678: . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x ||
3679: . maxit - maximum number of iterations
3680: - maxf - maximum number of function evaluations (-1 indicates no limit)
3682: Options Database Keys:
3683: + -snes_atol <abstol> - Sets abstol
3684: . -snes_rtol <rtol> - Sets rtol
3685: . -snes_stol <stol> - Sets stol
3686: . -snes_max_it <maxit> - Sets maxit
3687: - -snes_max_funcs <maxf> - Sets maxf
3689: Notes:
3690: The default maximum number of iterations is 50.
3691: The default maximum number of function evaluations is 1000.
3693: Level: intermediate
3695: .seealso: SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance(), SNESSetForceIteration()
3696: @*/
3697: PetscErrorCode SNESSetTolerances(SNES snes,PetscReal abstol,PetscReal rtol,PetscReal stol,PetscInt maxit,PetscInt maxf)
3698: {
3706: if (abstol != PETSC_DEFAULT) {
3708: snes->abstol = abstol;
3709: }
3710: if (rtol != PETSC_DEFAULT) {
3712: snes->rtol = rtol;
3713: }
3714: if (stol != PETSC_DEFAULT) {
3716: snes->stol = stol;
3717: }
3718: if (maxit != PETSC_DEFAULT) {
3720: snes->max_its = maxit;
3721: }
3722: if (maxf != PETSC_DEFAULT) {
3724: snes->max_funcs = maxf;
3725: }
3726: snes->tolerancesset = PETSC_TRUE;
3727: return 0;
3728: }
3730: /*@
3731: SNESSetDivergenceTolerance - Sets the divergence tolerance used for the SNES divergence test.
3733: Logically Collective on SNES
3735: Input Parameters:
3736: + snes - the SNES context
3737: - divtol - the divergence tolerance. Use -1 to deactivate the test.
3739: Options Database Keys:
3740: . -snes_divergence_tolerance <divtol> - Sets divtol
3742: Notes:
3743: The default divergence tolerance is 1e4.
3745: Level: intermediate
3747: .seealso: SNESSetTolerances(), SNESGetDivergenceTolerance
3748: @*/
3749: PetscErrorCode SNESSetDivergenceTolerance(SNES snes,PetscReal divtol)
3750: {
3754: if (divtol != PETSC_DEFAULT) {
3755: snes->divtol = divtol;
3756: }
3757: else {
3758: snes->divtol = 1.0e4;
3759: }
3760: return 0;
3761: }
3763: /*@
3764: SNESGetTolerances - Gets various parameters used in convergence tests.
3766: Not Collective
3768: Input Parameters:
3769: + snes - the SNES context
3770: . atol - absolute convergence tolerance
3771: . rtol - relative convergence tolerance
3772: . stol - convergence tolerance in terms of the norm
3773: of the change in the solution between steps
3774: . maxit - maximum number of iterations
3775: - maxf - maximum number of function evaluations
3777: Notes:
3778: The user can specify NULL for any parameter that is not needed.
3780: Level: intermediate
3782: .seealso: SNESSetTolerances()
3783: @*/
3784: PetscErrorCode SNESGetTolerances(SNES snes,PetscReal *atol,PetscReal *rtol,PetscReal *stol,PetscInt *maxit,PetscInt *maxf)
3785: {
3787: if (atol) *atol = snes->abstol;
3788: if (rtol) *rtol = snes->rtol;
3789: if (stol) *stol = snes->stol;
3790: if (maxit) *maxit = snes->max_its;
3791: if (maxf) *maxf = snes->max_funcs;
3792: return 0;
3793: }
3795: /*@
3796: SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3798: Not Collective
3800: Input Parameters:
3801: + snes - the SNES context
3802: - divtol - divergence tolerance
3804: Level: intermediate
3806: .seealso: SNESSetDivergenceTolerance()
3807: @*/
3808: PetscErrorCode SNESGetDivergenceTolerance(SNES snes,PetscReal *divtol)
3809: {
3811: if (divtol) *divtol = snes->divtol;
3812: return 0;
3813: }
3815: /*@
3816: SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
3818: Logically Collective on SNES
3820: Input Parameters:
3821: + snes - the SNES context
3822: - tol - tolerance
3824: Options Database Key:
3825: . -snes_trtol <tol> - Sets tol
3827: Level: intermediate
3829: .seealso: SNESSetTolerances()
3830: @*/
3831: PetscErrorCode SNESSetTrustRegionTolerance(SNES snes,PetscReal tol)
3832: {
3835: snes->deltatol = tol;
3836: return 0;
3837: }
3839: PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES,PetscInt,PetscReal*);
3841: PetscErrorCode SNESMonitorLGRange(SNES snes,PetscInt n,PetscReal rnorm,void *monctx)
3842: {
3843: PetscDrawLG lg;
3844: PetscReal x,y,per;
3845: PetscViewer v = (PetscViewer)monctx;
3846: static PetscReal prev; /* should be in the context */
3847: PetscDraw draw;
3850: PetscViewerDrawGetDrawLG(v,0,&lg);
3851: if (!n) PetscDrawLGReset(lg);
3852: PetscDrawLGGetDraw(lg,&draw);
3853: PetscDrawSetTitle(draw,"Residual norm");
3854: x = (PetscReal)n;
3855: if (rnorm > 0.0) y = PetscLog10Real(rnorm);
3856: else y = -15.0;
3857: PetscDrawLGAddPoint(lg,&x,&y);
3858: if (n < 20 || !(n % 5) || snes->reason) {
3859: PetscDrawLGDraw(lg);
3860: PetscDrawLGSave(lg);
3861: }
3863: PetscViewerDrawGetDrawLG(v,1,&lg);
3864: if (!n) PetscDrawLGReset(lg);
3865: PetscDrawLGGetDraw(lg,&draw);
3866: PetscDrawSetTitle(draw,"% elemts > .2*max elemt");
3867: SNESMonitorRange_Private(snes,n,&per);
3868: x = (PetscReal)n;
3869: y = 100.0*per;
3870: PetscDrawLGAddPoint(lg,&x,&y);
3871: if (n < 20 || !(n % 5) || snes->reason) {
3872: PetscDrawLGDraw(lg);
3873: PetscDrawLGSave(lg);
3874: }
3876: PetscViewerDrawGetDrawLG(v,2,&lg);
3877: if (!n) {prev = rnorm;PetscDrawLGReset(lg);}
3878: PetscDrawLGGetDraw(lg,&draw);
3879: PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm");
3880: x = (PetscReal)n;
3881: y = (prev - rnorm)/prev;
3882: PetscDrawLGAddPoint(lg,&x,&y);
3883: if (n < 20 || !(n % 5) || snes->reason) {
3884: PetscDrawLGDraw(lg);
3885: PetscDrawLGSave(lg);
3886: }
3888: PetscViewerDrawGetDrawLG(v,3,&lg);
3889: if (!n) PetscDrawLGReset(lg);
3890: PetscDrawLGGetDraw(lg,&draw);
3891: PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm*(% > .2 max)");
3892: x = (PetscReal)n;
3893: y = (prev - rnorm)/(prev*per);
3894: if (n > 2) { /*skip initial crazy value */
3895: PetscDrawLGAddPoint(lg,&x,&y);
3896: }
3897: if (n < 20 || !(n % 5) || snes->reason) {
3898: PetscDrawLGDraw(lg);
3899: PetscDrawLGSave(lg);
3900: }
3901: prev = rnorm;
3902: return 0;
3903: }
3905: /*@
3906: SNESMonitor - runs the user provided monitor routines, if they exist
3908: Collective on SNES
3910: Input Parameters:
3911: + snes - nonlinear solver context obtained from SNESCreate()
3912: . iter - iteration number
3913: - rnorm - relative norm of the residual
3915: Notes:
3916: This routine is called by the SNES implementations.
3917: It does not typically need to be called by the user.
3919: Level: developer
3921: .seealso: SNESMonitorSet()
3922: @*/
3923: PetscErrorCode SNESMonitor(SNES snes,PetscInt iter,PetscReal rnorm)
3924: {
3925: PetscInt i,n = snes->numbermonitors;
3927: VecLockReadPush(snes->vec_sol);
3928: for (i=0; i<n; i++) {
3929: (*snes->monitor[i])(snes,iter,rnorm,snes->monitorcontext[i]);
3930: }
3931: VecLockReadPop(snes->vec_sol);
3932: return 0;
3933: }
3935: /* ------------ Routines to set performance monitoring options ----------- */
3937: /*MC
3938: SNESMonitorFunction - functional form passed to SNESMonitorSet() to monitor convergence of nonlinear solver
3940: Synopsis:
3941: #include <petscsnes.h>
3942: $ PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx)
3944: Collective on snes
3946: Input Parameters:
3947: + snes - the SNES context
3948: . its - iteration number
3949: . norm - 2-norm function value (may be estimated)
3950: - mctx - [optional] monitoring context
3952: Level: advanced
3954: .seealso: SNESMonitorSet(), SNESMonitorGet()
3955: M*/
3957: /*@C
3958: SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
3959: iteration of the nonlinear solver to display the iteration's
3960: progress.
3962: Logically Collective on SNES
3964: Input Parameters:
3965: + snes - the SNES context
3966: . f - the monitor function, see SNESMonitorFunction for the calling sequence
3967: . mctx - [optional] user-defined context for private data for the
3968: monitor routine (use NULL if no context is desired)
3969: - monitordestroy - [optional] routine that frees monitor context
3970: (may be NULL)
3972: Options Database Keys:
3973: + -snes_monitor - sets SNESMonitorDefault()
3974: . -snes_monitor draw::draw_lg - sets line graph monitor,
3975: - -snes_monitor_cancel - cancels all monitors that have
3976: been hardwired into a code by
3977: calls to SNESMonitorSet(), but
3978: does not cancel those set via
3979: the options database.
3981: Notes:
3982: Several different monitoring routines may be set by calling
3983: SNESMonitorSet() multiple times; all will be called in the
3984: order in which they were set.
3986: Fortran Notes:
3987: Only a single monitor function can be set for each SNES object
3989: Level: intermediate
3991: .seealso: SNESMonitorDefault(), SNESMonitorCancel(), SNESMonitorFunction
3992: @*/
3993: PetscErrorCode SNESMonitorSet(SNES snes,PetscErrorCode (*f)(SNES,PetscInt,PetscReal,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
3994: {
3995: PetscInt i;
3996: PetscBool identical;
3999: for (i=0; i<snes->numbermonitors;i++) {
4000: PetscMonitorCompare((PetscErrorCode (*)(void))f,mctx,monitordestroy,(PetscErrorCode (*)(void))snes->monitor[i],snes->monitorcontext[i],snes->monitordestroy[i],&identical);
4001: if (identical) return 0;
4002: }
4004: snes->monitor[snes->numbermonitors] = f;
4005: snes->monitordestroy[snes->numbermonitors] = monitordestroy;
4006: snes->monitorcontext[snes->numbermonitors++] = (void*)mctx;
4007: return 0;
4008: }
4010: /*@
4011: SNESMonitorCancel - Clears all the monitor functions for a SNES object.
4013: Logically Collective on SNES
4015: Input Parameters:
4016: . snes - the SNES context
4018: Options Database Key:
4019: . -snes_monitor_cancel - cancels all monitors that have been hardwired
4020: into a code by calls to SNESMonitorSet(), but does not cancel those
4021: set via the options database
4023: Notes:
4024: There is no way to clear one specific monitor from a SNES object.
4026: Level: intermediate
4028: .seealso: SNESMonitorDefault(), SNESMonitorSet()
4029: @*/
4030: PetscErrorCode SNESMonitorCancel(SNES snes)
4031: {
4032: PetscInt i;
4035: for (i=0; i<snes->numbermonitors; i++) {
4036: if (snes->monitordestroy[i]) {
4037: (*snes->monitordestroy[i])(&snes->monitorcontext[i]);
4038: }
4039: }
4040: snes->numbermonitors = 0;
4041: return 0;
4042: }
4044: /*MC
4045: SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4047: Synopsis:
4048: #include <petscsnes.h>
4049: $ PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx)
4051: Collective on snes
4053: Input Parameters:
4054: + snes - the SNES context
4055: . it - current iteration (0 is the first and is before any Newton step)
4056: . xnorm - 2-norm of current iterate
4057: . gnorm - 2-norm of current step
4058: . f - 2-norm of function
4059: - cctx - [optional] convergence context
4061: Output Parameter:
4062: . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4064: Level: intermediate
4066: .seealso: SNESSetConvergenceTest(), SNESGetConvergenceTest()
4067: M*/
4069: /*@C
4070: SNESSetConvergenceTest - Sets the function that is to be used
4071: to test for convergence of the nonlinear iterative solution.
4073: Logically Collective on SNES
4075: Input Parameters:
4076: + snes - the SNES context
4077: . SNESConvergenceTestFunction - routine to test for convergence
4078: . cctx - [optional] context for private data for the convergence routine (may be NULL)
4079: - destroy - [optional] destructor for the context (may be NULL; PETSC_NULL_FUNCTION in Fortran)
4081: Level: advanced
4083: .seealso: SNESConvergedDefault(), SNESConvergedSkip(), SNESConvergenceTestFunction
4084: @*/
4085: PetscErrorCode SNESSetConvergenceTest(SNES snes,PetscErrorCode (*SNESConvergenceTestFunction)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void *cctx,PetscErrorCode (*destroy)(void*))
4086: {
4088: if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
4089: if (snes->ops->convergeddestroy) {
4090: (*snes->ops->convergeddestroy)(snes->cnvP);
4091: }
4092: snes->ops->converged = SNESConvergenceTestFunction;
4093: snes->ops->convergeddestroy = destroy;
4094: snes->cnvP = cctx;
4095: return 0;
4096: }
4098: /*@
4099: SNESGetConvergedReason - Gets the reason the SNES iteration was stopped.
4101: Not Collective
4103: Input Parameter:
4104: . snes - the SNES context
4106: Output Parameter:
4107: . reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the
4108: manual pages for the individual convergence tests for complete lists
4110: Options Database:
4111: . -snes_converged_reason - prints the reason to standard out
4113: Level: intermediate
4115: Notes:
4116: Should only be called after the call the SNESSolve() is complete, if it is called earlier it returns the value SNES__CONVERGED_ITERATING.
4118: .seealso: SNESSetConvergenceTest(), SNESSetConvergedReason(), SNESConvergedReason
4119: @*/
4120: PetscErrorCode SNESGetConvergedReason(SNES snes,SNESConvergedReason *reason)
4121: {
4124: *reason = snes->reason;
4125: return 0;
4126: }
4128: /*@C
4129: SNESGetConvergedReasonString - Return a human readable string for snes converged reason
4131: Not Collective
4133: Input Parameter:
4134: . snes - the SNES context
4136: Output Parameter:
4137: . strreason - a human readable string that describes SNES converged reason
4139: Level: beginner
4141: .seealso: SNESGetConvergedReason()
4142: @*/
4143: PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char** strreason)
4144: {
4147: *strreason = SNESConvergedReasons[snes->reason];
4148: return 0;
4149: }
4151: /*@
4152: SNESSetConvergedReason - Sets the reason the SNES iteration was stopped.
4154: Not Collective
4156: Input Parameters:
4157: + snes - the SNES context
4158: - reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the
4159: manual pages for the individual convergence tests for complete lists
4161: Level: intermediate
4163: .seealso: SNESGetConvergedReason(), SNESSetConvergenceTest(), SNESConvergedReason
4164: @*/
4165: PetscErrorCode SNESSetConvergedReason(SNES snes,SNESConvergedReason reason)
4166: {
4168: snes->reason = reason;
4169: return 0;
4170: }
4172: /*@
4173: SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
4175: Logically Collective on SNES
4177: Input Parameters:
4178: + snes - iterative context obtained from SNESCreate()
4179: . a - array to hold history, this array will contain the function norms computed at each step
4180: . its - integer array holds the number of linear iterations for each solve.
4181: . na - size of a and its
4182: - reset - PETSC_TRUE indicates each new nonlinear solve resets the history counter to zero,
4183: else it continues storing new values for new nonlinear solves after the old ones
4185: Notes:
4186: If 'a' and 'its' are NULL then space is allocated for the history. If 'na' PETSC_DECIDE or PETSC_DEFAULT then a
4187: default array of length 10000 is allocated.
4189: This routine is useful, e.g., when running a code for purposes
4190: of accurate performance monitoring, when no I/O should be done
4191: during the section of code that is being timed.
4193: Level: intermediate
4195: .seealso: SNESGetConvergenceHistory()
4197: @*/
4198: PetscErrorCode SNESSetConvergenceHistory(SNES snes,PetscReal a[],PetscInt its[],PetscInt na,PetscBool reset)
4199: {
4203: if (!a) {
4204: if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
4205: PetscCalloc2(na,&a,na,&its);
4206: snes->conv_hist_alloc = PETSC_TRUE;
4207: }
4208: snes->conv_hist = a;
4209: snes->conv_hist_its = its;
4210: snes->conv_hist_max = (size_t)na;
4211: snes->conv_hist_len = 0;
4212: snes->conv_hist_reset = reset;
4213: return 0;
4214: }
4216: #if defined(PETSC_HAVE_MATLAB_ENGINE)
4217: #include <engine.h> /* MATLAB include file */
4218: #include <mex.h> /* MATLAB include file */
4220: PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4221: {
4222: mxArray *mat;
4223: PetscInt i;
4224: PetscReal *ar;
4226: mat = mxCreateDoubleMatrix(snes->conv_hist_len,1,mxREAL);
4227: ar = (PetscReal*) mxGetData(mat);
4228: for (i=0; i<snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
4229: return mat;
4230: }
4231: #endif
4233: /*@C
4234: SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
4236: Not Collective
4238: Input Parameter:
4239: . snes - iterative context obtained from SNESCreate()
4241: Output Parameters:
4242: + a - array to hold history
4243: . its - integer array holds the number of linear iterations (or
4244: negative if not converged) for each solve.
4245: - na - size of a and its
4247: Notes:
4248: The calling sequence for this routine in Fortran is
4249: $ call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4251: This routine is useful, e.g., when running a code for purposes
4252: of accurate performance monitoring, when no I/O should be done
4253: during the section of code that is being timed.
4255: Level: intermediate
4257: .seealso: SNESSetConvergenceHistory()
4259: @*/
4260: PetscErrorCode SNESGetConvergenceHistory(SNES snes,PetscReal *a[],PetscInt *its[],PetscInt *na)
4261: {
4263: if (a) *a = snes->conv_hist;
4264: if (its) *its = snes->conv_hist_its;
4265: if (na) *na = (PetscInt) snes->conv_hist_len;
4266: return 0;
4267: }
4269: /*@C
4270: SNESSetUpdate - Sets the general-purpose update function called
4271: at the beginning of every iteration of the nonlinear solve. Specifically
4272: it is called just before the Jacobian is "evaluated".
4274: Logically Collective on SNES
4276: Input Parameters:
4277: + snes - The nonlinear solver context
4278: - func - The function
4280: Calling sequence of func:
4281: $ func (SNES snes, PetscInt step);
4283: . step - The current step of the iteration
4285: Level: advanced
4287: Note:
4288: 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()
4289: This is not used by most users.
4291: There are a varity of function hooks one many set that are called at different stages of the nonlinear solution process, see the functions listed below.
4293: .seealso SNESSetJacobian(), SNESSolve(), SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck(), SNESNewtonTRSetPreCheck(), SNESNewtonTRSetPostCheck(),
4294: SNESMonitorSet(), SNESSetDivergenceTest()
4295: @*/
4296: PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
4297: {
4299: snes->ops->update = func;
4300: return 0;
4301: }
4303: /*
4304: SNESScaleStep_Private - Scales a step so that its length is less than the
4305: positive parameter delta.
4307: Input Parameters:
4308: + snes - the SNES context
4309: . y - approximate solution of linear system
4310: . fnorm - 2-norm of current function
4311: - delta - trust region size
4313: Output Parameters:
4314: + gpnorm - predicted function norm at the new point, assuming local
4315: linearization. The value is zero if the step lies within the trust
4316: region, and exceeds zero otherwise.
4317: - ynorm - 2-norm of the step
4319: Note:
4320: For non-trust region methods such as SNESNEWTONLS, the parameter delta
4321: is set to be the maximum allowable step size.
4323: */
4324: PetscErrorCode SNESScaleStep_Private(SNES snes,Vec y,PetscReal *fnorm,PetscReal *delta,PetscReal *gpnorm,PetscReal *ynorm)
4325: {
4326: PetscReal nrm;
4327: PetscScalar cnorm;
4333: VecNorm(y,NORM_2,&nrm);
4334: if (nrm > *delta) {
4335: nrm = *delta/nrm;
4336: *gpnorm = (1.0 - nrm)*(*fnorm);
4337: cnorm = nrm;
4338: VecScale(y,cnorm);
4339: *ynorm = *delta;
4340: } else {
4341: *gpnorm = 0.0;
4342: *ynorm = nrm;
4343: }
4344: return 0;
4345: }
4347: /*@C
4348: SNESConvergedReasonView - Displays the reason a SNES solve converged or diverged to a viewer
4350: Collective on SNES
4352: Parameter:
4353: + snes - iterative context obtained from SNESCreate()
4354: - viewer - the viewer to display the reason
4356: Options Database Keys:
4357: + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations
4358: - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4360: Notes:
4361: To change the format of the output call PetscViewerPushFormat(viewer,format) before this call. Use PETSC_VIEWER_DEFAULT for the default,
4362: use PETSC_VIEWER_FAILED to only display a reason if it fails.
4364: Level: beginner
4366: .seealso: SNESCreate(), SNESSetUp(), SNESDestroy(), SNESSetTolerances(), SNESConvergedDefault(), SNESGetConvergedReason(), SNESConvergedReasonViewFromOptions(),
4367: PetscViewerPushFormat(), PetscViewerPopFormat()
4369: @*/
4370: PetscErrorCode SNESConvergedReasonView(SNES snes,PetscViewer viewer)
4371: {
4372: PetscViewerFormat format;
4373: PetscBool isAscii;
4375: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
4376: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii);
4377: if (isAscii) {
4378: PetscViewerGetFormat(viewer, &format);
4379: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
4380: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
4381: DM dm;
4382: Vec u;
4383: PetscDS prob;
4384: PetscInt Nf, f;
4385: PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
4386: void **exactCtx;
4387: PetscReal error;
4389: SNESGetDM(snes, &dm);
4390: SNESGetSolution(snes, &u);
4391: DMGetDS(dm, &prob);
4392: PetscDSGetNumFields(prob, &Nf);
4393: PetscMalloc2(Nf, &exactSol, Nf, &exactCtx);
4394: for (f = 0; f < Nf; ++f) PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]);
4395: DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error);
4396: PetscFree2(exactSol, exactCtx);
4397: if (error < 1.0e-11) PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n");
4398: else PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", error);
4399: }
4400: if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
4401: if (((PetscObject) snes)->prefix) {
4402: PetscViewerASCIIPrintf(viewer,"Nonlinear %s solve converged due to %s iterations %D\n",((PetscObject) snes)->prefix,SNESConvergedReasons[snes->reason],snes->iter);
4403: } else {
4404: PetscViewerASCIIPrintf(viewer,"Nonlinear solve converged due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);
4405: }
4406: } else if (snes->reason <= 0) {
4407: if (((PetscObject) snes)->prefix) {
4408: PetscViewerASCIIPrintf(viewer,"Nonlinear %s solve did not converge due to %s iterations %D\n",((PetscObject) snes)->prefix,SNESConvergedReasons[snes->reason],snes->iter);
4409: } else {
4410: PetscViewerASCIIPrintf(viewer,"Nonlinear solve did not converge due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);
4411: }
4412: }
4413: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
4414: }
4415: return 0;
4416: }
4418: /*@C
4419: SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4420: end of the nonlinear solver to display the conver reason of the nonlinear solver.
4422: Logically Collective on SNES
4424: Input Parameters:
4425: + snes - the SNES context
4426: . f - the snes converged reason view function
4427: . vctx - [optional] user-defined context for private data for the
4428: snes converged reason view routine (use NULL if no context is desired)
4429: - reasonviewdestroy - [optional] routine that frees reasonview context
4430: (may be NULL)
4432: Options Database Keys:
4433: + -snes_converged_reason - sets a default SNESConvergedReasonView()
4434: - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have
4435: been hardwired into a code by
4436: calls to SNESConvergedReasonViewSet(), but
4437: does not cancel those set via
4438: the options database.
4440: Notes:
4441: Several different converged reason view routines may be set by calling
4442: SNESConvergedReasonViewSet() multiple times; all will be called in the
4443: order in which they were set.
4445: Level: intermediate
4447: .seealso: SNESConvergedReasonView(), SNESConvergedReasonViewCancel()
4448: @*/
4449: PetscErrorCode SNESConvergedReasonViewSet(SNES snes,PetscErrorCode (*f)(SNES,void*),void *vctx,PetscErrorCode (*reasonviewdestroy)(void**))
4450: {
4451: PetscInt i;
4452: PetscBool identical;
4455: for (i=0; i<snes->numberreasonviews;i++) {
4456: PetscMonitorCompare((PetscErrorCode (*)(void))f,vctx,reasonviewdestroy,(PetscErrorCode (*)(void))snes->reasonview[i],snes->reasonviewcontext[i],snes->reasonviewdestroy[i],&identical);
4457: if (identical) return 0;
4458: }
4460: snes->reasonview[snes->numberreasonviews] = f;
4461: snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy;
4462: snes->reasonviewcontext[snes->numberreasonviews++] = (void*)vctx;
4463: return 0;
4464: }
4466: /*@
4467: SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a SNESReason is to be viewed.
4468: All the user-provided convergedReasonView routines will be involved as well, if they exist.
4470: Collective on SNES
4472: Input Parameters:
4473: . snes - the SNES object
4475: Level: intermediate
4477: .seealso: SNESCreate(), SNESSetUp(), SNESDestroy(), SNESSetTolerances(), SNESConvergedDefault(), SNESGetConvergedReason(), SNESConvergedReasonView()
4479: @*/
4480: PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4481: {
4482: PetscViewer viewer;
4483: PetscBool flg;
4484: static PetscBool incall = PETSC_FALSE;
4485: PetscViewerFormat format;
4486: PetscInt i;
4488: if (incall) return 0;
4489: incall = PETSC_TRUE;
4491: /* All user-provided viewers are called first, if they exist. */
4492: for (i=0; i<snes->numberreasonviews; i++) {
4493: (*snes->reasonview[i])(snes,snes->reasonviewcontext[i]);
4494: }
4496: /* Call PETSc default routine if users ask for it */
4497: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_converged_reason",&viewer,&format,&flg);
4498: if (flg) {
4499: PetscViewerPushFormat(viewer,format);
4500: SNESConvergedReasonView(snes,viewer);
4501: PetscViewerPopFormat(viewer);
4502: PetscViewerDestroy(&viewer);
4503: }
4504: incall = PETSC_FALSE;
4505: return 0;
4506: }
4508: /*@
4509: SNESSolve - Solves a nonlinear system F(x) = b.
4510: Call SNESSolve() after calling SNESCreate() and optional routines of the form SNESSetXXX().
4512: Collective on SNES
4514: Input Parameters:
4515: + snes - the SNES context
4516: . b - the constant part of the equation F(x) = b, or NULL to use zero.
4517: - x - the solution vector.
4519: Notes:
4520: The user should initialize the vector,x, with the initial guess
4521: for the nonlinear solve prior to calling SNESSolve(). In particular,
4522: to employ an initial guess of zero, the user should explicitly set
4523: this vector to zero by calling VecSet().
4525: Level: beginner
4527: .seealso: SNESCreate(), SNESDestroy(), SNESSetFunction(), SNESSetJacobian(), SNESSetGridSequence(), SNESGetSolution(),
4528: SNESNewtonTRSetPreCheck(), SNESNewtonTRGetPreCheck(), SNESNewtonTRSetPostCheck(), SNESNewtonTRGetPostCheck(),
4529: SNESLineSearchSetPostCheck(), SNESLineSearchGetPostCheck(), SNESLineSearchSetPreCheck(), SNESLineSearchGetPreCheck()
4530: @*/
4531: PetscErrorCode SNESSolve(SNES snes,Vec b,Vec x)
4532: {
4533: PetscBool flg;
4534: PetscInt grid;
4535: Vec xcreated = NULL;
4536: DM dm;
4544: /* High level operations using the nonlinear solver */
4545: {
4546: PetscViewer viewer;
4547: PetscViewerFormat format;
4548: PetscInt num;
4549: PetscBool flg;
4550: static PetscBool incall = PETSC_FALSE;
4552: if (!incall) {
4553: /* Estimate the convergence rate of the discretization */
4554: PetscOptionsGetViewer(PetscObjectComm((PetscObject) snes),((PetscObject)snes)->options, ((PetscObject) snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg);
4555: if (flg) {
4556: PetscConvEst conv;
4557: DM dm;
4558: PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
4559: PetscInt Nf;
4561: incall = PETSC_TRUE;
4562: SNESGetDM(snes, &dm);
4563: DMGetNumFields(dm, &Nf);
4564: PetscCalloc1(Nf, &alpha);
4565: PetscConvEstCreate(PetscObjectComm((PetscObject) snes), &conv);
4566: PetscConvEstSetSolver(conv, (PetscObject) snes);
4567: PetscConvEstSetFromOptions(conv);
4568: PetscConvEstSetUp(conv);
4569: PetscConvEstGetConvRate(conv, alpha);
4570: PetscViewerPushFormat(viewer, format);
4571: PetscConvEstRateView(conv, alpha, viewer);
4572: PetscViewerPopFormat(viewer);
4573: PetscViewerDestroy(&viewer);
4574: PetscConvEstDestroy(&conv);
4575: PetscFree(alpha);
4576: incall = PETSC_FALSE;
4577: }
4578: /* Adaptively refine the initial grid */
4579: num = 1;
4580: PetscOptionsGetInt(NULL, ((PetscObject) snes)->prefix, "-snes_adapt_initial", &num, &flg);
4581: if (flg) {
4582: DMAdaptor adaptor;
4584: incall = PETSC_TRUE;
4585: DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor);
4586: DMAdaptorSetSolver(adaptor, snes);
4587: DMAdaptorSetSequenceLength(adaptor, num);
4588: DMAdaptorSetFromOptions(adaptor);
4589: DMAdaptorSetUp(adaptor);
4590: DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x);
4591: DMAdaptorDestroy(&adaptor);
4592: incall = PETSC_FALSE;
4593: }
4594: /* Use grid sequencing to adapt */
4595: num = 0;
4596: PetscOptionsGetInt(NULL, ((PetscObject) snes)->prefix, "-snes_adapt_sequence", &num, NULL);
4597: if (num) {
4598: DMAdaptor adaptor;
4600: incall = PETSC_TRUE;
4601: DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor);
4602: DMAdaptorSetSolver(adaptor, snes);
4603: DMAdaptorSetSequenceLength(adaptor, num);
4604: DMAdaptorSetFromOptions(adaptor);
4605: DMAdaptorSetUp(adaptor);
4606: DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x);
4607: DMAdaptorDestroy(&adaptor);
4608: incall = PETSC_FALSE;
4609: }
4610: }
4611: }
4612: if (!x) { x = snes->vec_sol; }
4613: if (!x) {
4614: SNESGetDM(snes,&dm);
4615: DMCreateGlobalVector(dm,&xcreated);
4616: x = xcreated;
4617: }
4618: SNESViewFromOptions(snes,NULL,"-snes_view_pre");
4620: for (grid=0; grid<snes->gridsequence; grid++) PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));
4621: for (grid=0; grid<snes->gridsequence+1; grid++) {
4623: /* set solution vector */
4624: if (!grid) PetscObjectReference((PetscObject)x);
4625: VecDestroy(&snes->vec_sol);
4626: snes->vec_sol = x;
4627: SNESGetDM(snes,&dm);
4629: /* set affine vector if provided */
4630: if (b) PetscObjectReference((PetscObject)b);
4631: VecDestroy(&snes->vec_rhs);
4632: snes->vec_rhs = b;
4637: if (!snes->vec_sol_update /* && snes->vec_sol */) {
4638: VecDuplicate(snes->vec_sol,&snes->vec_sol_update);
4639: PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->vec_sol_update);
4640: }
4641: DMShellSetGlobalVector(dm,snes->vec_sol);
4642: SNESSetUp(snes);
4644: if (!grid) {
4645: if (snes->ops->computeinitialguess) {
4646: (*snes->ops->computeinitialguess)(snes,snes->vec_sol,snes->initialguessP);
4647: }
4648: }
4650: if (snes->conv_hist_reset) snes->conv_hist_len = 0;
4651: if (snes->counters_reset) {snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;}
4653: PetscLogEventBegin(SNES_Solve,snes,0,0,0);
4654: (*snes->ops->solve)(snes);
4655: PetscLogEventEnd(SNES_Solve,snes,0,0,0);
4657: snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
4659: if (snes->lagjac_persist) snes->jac_iter += snes->iter;
4660: if (snes->lagpre_persist) snes->pre_iter += snes->iter;
4662: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_test_local_min",NULL,NULL,&flg);
4663: if (flg && !PetscPreLoadingOn) SNESTestLocalMin(snes);
4664: /* Call converged reason views. This may involve user-provided viewers as well */
4665: SNESConvergedReasonViewFromOptions(snes);
4668: if (snes->reason < 0) break;
4669: if (grid < snes->gridsequence) {
4670: DM fine;
4671: Vec xnew;
4672: Mat interp;
4674: DMRefine(snes->dm,PetscObjectComm((PetscObject)snes),&fine);
4676: DMCreateInterpolation(snes->dm,fine,&interp,NULL);
4677: DMCreateGlobalVector(fine,&xnew);
4678: MatInterpolate(interp,x,xnew);
4679: DMInterpolate(snes->dm,interp,fine);
4680: MatDestroy(&interp);
4681: x = xnew;
4683: SNESReset(snes);
4684: SNESSetDM(snes,fine);
4685: SNESResetFromOptions(snes);
4686: DMDestroy(&fine);
4687: PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));
4688: }
4689: }
4690: SNESViewFromOptions(snes,NULL,"-snes_view");
4691: VecViewFromOptions(snes->vec_sol,(PetscObject)snes,"-snes_view_solution");
4692: DMMonitor(snes->dm);
4693: SNESMonitorPauseFinal_Internal(snes);
4695: VecDestroy(&xcreated);
4696: PetscObjectSAWsBlock((PetscObject)snes);
4697: return 0;
4698: }
4700: /* --------- Internal routines for SNES Package --------- */
4702: /*@C
4703: SNESSetType - Sets the method for the nonlinear solver.
4705: Collective on SNES
4707: Input Parameters:
4708: + snes - the SNES context
4709: - type - a known method
4711: Options Database Key:
4712: . -snes_type <type> - Sets the method; use -help for a list
4713: of available methods (for instance, newtonls or newtontr)
4715: Notes:
4716: See "petsc/include/petscsnes.h" for available methods (for instance)
4717: + SNESNEWTONLS - Newton's method with line search
4718: (systems of nonlinear equations)
4719: - SNESNEWTONTR - Newton's method with trust region
4720: (systems of nonlinear equations)
4722: Normally, it is best to use the SNESSetFromOptions() command and then
4723: set the SNES solver type from the options database rather than by using
4724: this routine. Using the options database provides the user with
4725: maximum flexibility in evaluating the many nonlinear solvers.
4726: The SNESSetType() routine is provided for those situations where it
4727: is necessary to set the nonlinear solver independently of the command
4728: line or options database. This might be the case, for example, when
4729: the choice of solver changes during the execution of the program,
4730: and the user's application is taking responsibility for choosing the
4731: appropriate method.
4733: Developer Notes:
4734: SNESRegister() adds a constructor for a new SNESType to SNESList, SNESSetType() locates
4735: the constructor in that list and calls it to create the spexific object.
4737: Level: intermediate
4739: .seealso: SNESType, SNESCreate(), SNESDestroy(), SNESGetType(), SNESSetFromOptions()
4741: @*/
4742: PetscErrorCode SNESSetType(SNES snes,SNESType type)
4743: {
4744: PetscBool match;
4745: PetscErrorCode (*r)(SNES);
4750: PetscObjectTypeCompare((PetscObject)snes,type,&match);
4751: if (match) return 0;
4753: PetscFunctionListFind(SNESList,type,&r);
4755: /* Destroy the previous private SNES context */
4756: if (snes->ops->destroy) {
4757: (*(snes)->ops->destroy)(snes);
4758: snes->ops->destroy = NULL;
4759: }
4760: /* Reinitialize function pointers in SNESOps structure */
4761: snes->ops->setup = NULL;
4762: snes->ops->solve = NULL;
4763: snes->ops->view = NULL;
4764: snes->ops->setfromoptions = NULL;
4765: snes->ops->destroy = NULL;
4767: /* It may happen the user has customized the line search before calling SNESSetType */
4768: if (((PetscObject)snes)->type_name) SNESLineSearchDestroy(&snes->linesearch);
4770: /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
4771: snes->setupcalled = PETSC_FALSE;
4773: PetscObjectChangeTypeName((PetscObject)snes,type);
4774: (*r)(snes);
4775: return 0;
4776: }
4778: /*@C
4779: SNESGetType - Gets the SNES method type and name (as a string).
4781: Not Collective
4783: Input Parameter:
4784: . snes - nonlinear solver context
4786: Output Parameter:
4787: . type - SNES method (a character string)
4789: Level: intermediate
4791: @*/
4792: PetscErrorCode SNESGetType(SNES snes,SNESType *type)
4793: {
4796: *type = ((PetscObject)snes)->type_name;
4797: return 0;
4798: }
4800: /*@
4801: SNESSetSolution - Sets the solution vector for use by the SNES routines.
4803: Logically Collective on SNES
4805: Input Parameters:
4806: + snes - the SNES context obtained from SNESCreate()
4807: - u - the solution vector
4809: Level: beginner
4811: @*/
4812: PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4813: {
4814: DM dm;
4818: PetscObjectReference((PetscObject) u);
4819: VecDestroy(&snes->vec_sol);
4821: snes->vec_sol = u;
4823: SNESGetDM(snes, &dm);
4824: DMShellSetGlobalVector(dm, u);
4825: return 0;
4826: }
4828: /*@
4829: SNESGetSolution - Returns the vector where the approximate solution is
4830: stored. This is the fine grid solution when using SNESSetGridSequence().
4832: Not Collective, but Vec is parallel if SNES is parallel
4834: Input Parameter:
4835: . snes - the SNES context
4837: Output Parameter:
4838: . x - the solution
4840: Level: intermediate
4842: .seealso: SNESGetSolutionUpdate(), SNESGetFunction()
4843: @*/
4844: PetscErrorCode SNESGetSolution(SNES snes,Vec *x)
4845: {
4848: *x = snes->vec_sol;
4849: return 0;
4850: }
4852: /*@
4853: SNESGetSolutionUpdate - Returns the vector where the solution update is
4854: stored.
4856: Not Collective, but Vec is parallel if SNES is parallel
4858: Input Parameter:
4859: . snes - the SNES context
4861: Output Parameter:
4862: . x - the solution update
4864: Level: advanced
4866: .seealso: SNESGetSolution(), SNESGetFunction()
4867: @*/
4868: PetscErrorCode SNESGetSolutionUpdate(SNES snes,Vec *x)
4869: {
4872: *x = snes->vec_sol_update;
4873: return 0;
4874: }
4876: /*@C
4877: SNESGetFunction - Returns the vector where the function is stored.
4879: Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet.
4881: Input Parameter:
4882: . snes - the SNES context
4884: Output Parameters:
4885: + r - the vector that is used to store residuals (or NULL if you don't want it)
4886: . f - the function (or NULL if you don't want it); see SNESFunction for calling sequence details
4887: - ctx - the function context (or NULL if you don't want it)
4889: Level: advanced
4891: Notes: The vector r DOES NOT, in general contain the current value of the SNES nonlinear function
4893: .seealso: SNESSetFunction(), SNESGetSolution(), SNESFunction
4894: @*/
4895: PetscErrorCode SNESGetFunction(SNES snes,Vec *r,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx)
4896: {
4897: DM dm;
4900: if (r) {
4901: if (!snes->vec_func) {
4902: if (snes->vec_rhs) {
4903: VecDuplicate(snes->vec_rhs,&snes->vec_func);
4904: } else if (snes->vec_sol) {
4905: VecDuplicate(snes->vec_sol,&snes->vec_func);
4906: } else if (snes->dm) {
4907: DMCreateGlobalVector(snes->dm,&snes->vec_func);
4908: }
4909: }
4910: *r = snes->vec_func;
4911: }
4912: SNESGetDM(snes,&dm);
4913: DMSNESGetFunction(dm,f,ctx);
4914: return 0;
4915: }
4917: /*@C
4918: SNESGetNGS - Returns the NGS function and context.
4920: Input Parameter:
4921: . snes - the SNES context
4923: Output Parameters:
4924: + f - the function (or NULL) see SNESNGSFunction for details
4925: - ctx - the function context (or NULL)
4927: Level: advanced
4929: .seealso: SNESSetNGS(), SNESGetFunction()
4930: @*/
4932: PetscErrorCode SNESGetNGS (SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void*), void ** ctx)
4933: {
4934: DM dm;
4937: SNESGetDM(snes,&dm);
4938: DMSNESGetNGS(dm,f,ctx);
4939: return 0;
4940: }
4942: /*@C
4943: SNESSetOptionsPrefix - Sets the prefix used for searching for all
4944: SNES options in the database.
4946: Logically Collective on SNES
4948: Input Parameters:
4949: + snes - the SNES context
4950: - prefix - the prefix to prepend to all option names
4952: Notes:
4953: A hyphen (-) must NOT be given at the beginning of the prefix name.
4954: The first character of all runtime options is AUTOMATICALLY the hyphen.
4956: Level: advanced
4958: .seealso: SNESSetFromOptions()
4959: @*/
4960: PetscErrorCode SNESSetOptionsPrefix(SNES snes,const char prefix[])
4961: {
4963: PetscObjectSetOptionsPrefix((PetscObject)snes,prefix);
4964: if (!snes->ksp) SNESGetKSP(snes,&snes->ksp);
4965: if (snes->linesearch) {
4966: SNESGetLineSearch(snes,&snes->linesearch);
4967: PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch,prefix);
4968: }
4969: KSPSetOptionsPrefix(snes->ksp,prefix);
4970: return 0;
4971: }
4973: /*@C
4974: SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
4975: SNES options in the database.
4977: Logically Collective on SNES
4979: Input Parameters:
4980: + snes - the SNES context
4981: - prefix - the prefix to prepend to all option names
4983: Notes:
4984: A hyphen (-) must NOT be given at the beginning of the prefix name.
4985: The first character of all runtime options is AUTOMATICALLY the hyphen.
4987: Level: advanced
4989: .seealso: SNESGetOptionsPrefix()
4990: @*/
4991: PetscErrorCode SNESAppendOptionsPrefix(SNES snes,const char prefix[])
4992: {
4994: PetscObjectAppendOptionsPrefix((PetscObject)snes,prefix);
4995: if (!snes->ksp) SNESGetKSP(snes,&snes->ksp);
4996: if (snes->linesearch) {
4997: SNESGetLineSearch(snes,&snes->linesearch);
4998: PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch,prefix);
4999: }
5000: KSPAppendOptionsPrefix(snes->ksp,prefix);
5001: return 0;
5002: }
5004: /*@C
5005: SNESGetOptionsPrefix - Sets the prefix used for searching for all
5006: SNES options in the database.
5008: Not Collective
5010: Input Parameter:
5011: . snes - the SNES context
5013: Output Parameter:
5014: . prefix - pointer to the prefix string used
5016: Notes:
5017: On the fortran side, the user should pass in a string 'prefix' of
5018: sufficient length to hold the prefix.
5020: Level: advanced
5022: .seealso: SNESAppendOptionsPrefix()
5023: @*/
5024: PetscErrorCode SNESGetOptionsPrefix(SNES snes,const char *prefix[])
5025: {
5027: PetscObjectGetOptionsPrefix((PetscObject)snes,prefix);
5028: return 0;
5029: }
5031: /*@C
5032: SNESRegister - Adds a method to the nonlinear solver package.
5034: Not collective
5036: Input Parameters:
5037: + name_solver - name of a new user-defined solver
5038: - routine_create - routine to create method context
5040: Notes:
5041: SNESRegister() may be called multiple times to add several user-defined solvers.
5043: Sample usage:
5044: .vb
5045: SNESRegister("my_solver",MySolverCreate);
5046: .ve
5048: Then, your solver can be chosen with the procedural interface via
5049: $ SNESSetType(snes,"my_solver")
5050: or at runtime via the option
5051: $ -snes_type my_solver
5053: Level: advanced
5055: Note: If your function is not being put into a shared library then use SNESRegister() instead
5057: .seealso: SNESRegisterAll(), SNESRegisterDestroy()
5059: Level: advanced
5060: @*/
5061: PetscErrorCode SNESRegister(const char sname[],PetscErrorCode (*function)(SNES))
5062: {
5063: SNESInitializePackage();
5064: PetscFunctionListAdd(&SNESList,sname,function);
5065: return 0;
5066: }
5068: PetscErrorCode SNESTestLocalMin(SNES snes)
5069: {
5070: PetscInt N,i,j;
5071: Vec u,uh,fh;
5072: PetscScalar value;
5073: PetscReal norm;
5075: SNESGetSolution(snes,&u);
5076: VecDuplicate(u,&uh);
5077: VecDuplicate(u,&fh);
5079: /* currently only works for sequential */
5080: PetscPrintf(PetscObjectComm((PetscObject)snes),"Testing FormFunction() for local min\n");
5081: VecGetSize(u,&N);
5082: for (i=0; i<N; i++) {
5083: VecCopy(u,uh);
5084: PetscPrintf(PetscObjectComm((PetscObject)snes),"i = %D\n",i);
5085: for (j=-10; j<11; j++) {
5086: value = PetscSign(j)*PetscExpReal(PetscAbs(j)-10.0);
5087: VecSetValue(uh,i,value,ADD_VALUES);
5088: SNESComputeFunction(snes,uh,fh);
5089: VecNorm(fh,NORM_2,&norm);
5090: PetscPrintf(PetscObjectComm((PetscObject)snes)," j norm %D %18.16e\n",j,norm);
5091: value = -value;
5092: VecSetValue(uh,i,value,ADD_VALUES);
5093: }
5094: }
5095: VecDestroy(&uh);
5096: VecDestroy(&fh);
5097: return 0;
5098: }
5100: /*@
5101: SNESKSPSetUseEW - Sets SNES use Eisenstat-Walker method for
5102: computing relative tolerance for linear solvers within an inexact
5103: Newton method.
5105: Logically Collective on SNES
5107: Input Parameters:
5108: + snes - SNES context
5109: - flag - PETSC_TRUE or PETSC_FALSE
5111: Options Database:
5112: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
5113: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
5114: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
5115: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
5116: . -snes_ksp_ew_gamma <gamma> - Sets gamma
5117: . -snes_ksp_ew_alpha <alpha> - Sets alpha
5118: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
5119: - -snes_ksp_ew_threshold <threshold> - Sets threshold
5121: Notes:
5122: Currently, the default is to use a constant relative tolerance for
5123: the inner linear solvers. Alternatively, one can use the
5124: Eisenstat-Walker method, where the relative convergence tolerance
5125: is reset at each Newton iteration according progress of the nonlinear
5126: solver.
5128: Level: advanced
5130: Reference:
5131: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
5132: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
5134: .seealso: SNESKSPGetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
5135: @*/
5136: PetscErrorCode SNESKSPSetUseEW(SNES snes,PetscBool flag)
5137: {
5140: snes->ksp_ewconv = flag;
5141: return 0;
5142: }
5144: /*@
5145: SNESKSPGetUseEW - Gets if SNES is using Eisenstat-Walker method
5146: for computing relative tolerance for linear solvers within an
5147: inexact Newton method.
5149: Not Collective
5151: Input Parameter:
5152: . snes - SNES context
5154: Output Parameter:
5155: . flag - PETSC_TRUE or PETSC_FALSE
5157: Notes:
5158: Currently, the default is to use a constant relative tolerance for
5159: the inner linear solvers. Alternatively, one can use the
5160: Eisenstat-Walker method, where the relative convergence tolerance
5161: is reset at each Newton iteration according progress of the nonlinear
5162: solver.
5164: Level: advanced
5166: Reference:
5167: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
5168: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
5170: .seealso: SNESKSPSetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
5171: @*/
5172: PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5173: {
5176: *flag = snes->ksp_ewconv;
5177: return 0;
5178: }
5180: /*@
5181: SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
5182: convergence criteria for the linear solvers within an inexact
5183: Newton method.
5185: Logically Collective on SNES
5187: Input Parameters:
5188: + snes - SNES context
5189: . version - version 1, 2 (default is 2) or 3
5190: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
5191: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
5192: . gamma - multiplicative factor for version 2 rtol computation
5193: (0 <= gamma2 <= 1)
5194: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
5195: . alpha2 - power for safeguard
5196: - threshold - threshold for imposing safeguard (0 < threshold < 1)
5198: Note:
5199: Version 3 was contributed by Luis Chacon, June 2006.
5201: Use PETSC_DEFAULT to retain the default for any of the parameters.
5203: Level: advanced
5205: Reference:
5206: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
5207: inexact Newton method", Utah State University Math. Stat. Dept. Res.
5208: Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
5210: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPGetParametersEW()
5211: @*/
5212: PetscErrorCode SNESKSPSetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,PetscReal gamma,PetscReal alpha,PetscReal alpha2,PetscReal threshold)
5213: {
5214: SNESKSPEW *kctx;
5217: kctx = (SNESKSPEW*)snes->kspconvctx;
5227: if (version != PETSC_DEFAULT) kctx->version = version;
5228: if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
5229: if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max;
5230: if (gamma != PETSC_DEFAULT) kctx->gamma = gamma;
5231: if (alpha != PETSC_DEFAULT) kctx->alpha = alpha;
5232: if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2;
5233: if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
5241: return 0;
5242: }
5244: /*@
5245: SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
5246: convergence criteria for the linear solvers within an inexact
5247: Newton method.
5249: Not Collective
5251: Input Parameter:
5252: . snes - SNES context
5254: Output Parameters:
5255: + version - version 1, 2 (default is 2) or 3
5256: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
5257: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
5258: . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
5259: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
5260: . alpha2 - power for safeguard
5261: - threshold - threshold for imposing safeguard (0 < threshold < 1)
5263: Level: advanced
5265: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPSetParametersEW()
5266: @*/
5267: PetscErrorCode SNESKSPGetParametersEW(SNES snes,PetscInt *version,PetscReal *rtol_0,PetscReal *rtol_max,PetscReal *gamma,PetscReal *alpha,PetscReal *alpha2,PetscReal *threshold)
5268: {
5269: SNESKSPEW *kctx;
5272: kctx = (SNESKSPEW*)snes->kspconvctx;
5274: if (version) *version = kctx->version;
5275: if (rtol_0) *rtol_0 = kctx->rtol_0;
5276: if (rtol_max) *rtol_max = kctx->rtol_max;
5277: if (gamma) *gamma = kctx->gamma;
5278: if (alpha) *alpha = kctx->alpha;
5279: if (alpha2) *alpha2 = kctx->alpha2;
5280: if (threshold) *threshold = kctx->threshold;
5281: return 0;
5282: }
5284: PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5285: {
5286: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
5287: PetscReal rtol = PETSC_DEFAULT,stol;
5289: if (!snes->ksp_ewconv) return 0;
5290: if (!snes->iter) {
5291: rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
5292: VecNorm(snes->vec_func,NORM_2,&kctx->norm_first);
5293: }
5294: else {
5295: if (kctx->version == 1) {
5296: rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
5297: if (rtol < 0.0) rtol = -rtol;
5298: stol = PetscPowReal(kctx->rtol_last,kctx->alpha2);
5299: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
5300: } else if (kctx->version == 2) {
5301: rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha);
5302: stol = kctx->gamma * PetscPowReal(kctx->rtol_last,kctx->alpha);
5303: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
5304: } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
5305: rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha);
5306: /* safeguard: avoid sharp decrease of rtol */
5307: stol = kctx->gamma*PetscPowReal(kctx->rtol_last,kctx->alpha);
5308: stol = PetscMax(rtol,stol);
5309: rtol = PetscMin(kctx->rtol_0,stol);
5310: /* safeguard: avoid oversolving */
5311: stol = kctx->gamma*(kctx->norm_first*snes->rtol)/snes->norm;
5312: stol = PetscMax(rtol,stol);
5313: rtol = PetscMin(kctx->rtol_0,stol);
5314: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 or 3 are supported: %D",kctx->version);
5315: }
5316: /* safeguard: avoid rtol greater than one */
5317: rtol = PetscMin(rtol,kctx->rtol_max);
5318: KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
5319: PetscInfo(snes,"iter %D, Eisenstat-Walker (version %D) KSP rtol=%g\n",snes->iter,kctx->version,(double)rtol);
5320: return 0;
5321: }
5323: PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5324: {
5325: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
5326: PCSide pcside;
5327: Vec lres;
5329: if (!snes->ksp_ewconv) return 0;
5330: KSPGetTolerances(ksp,&kctx->rtol_last,NULL,NULL,NULL);
5331: kctx->norm_last = snes->norm;
5332: if (kctx->version == 1) {
5333: PC pc;
5334: PetscBool isNone;
5336: KSPGetPC(ksp, &pc);
5337: PetscObjectTypeCompare((PetscObject) pc, PCNONE, &isNone);
5338: KSPGetPCSide(ksp,&pcside);
5339: if (pcside == PC_RIGHT || isNone) { /* XXX Should we also test KSP_UNPRECONDITIONED_NORM ? */
5340: /* KSP residual is true linear residual */
5341: KSPGetResidualNorm(ksp,&kctx->lresid_last);
5342: } else {
5343: /* KSP residual is preconditioned residual */
5344: /* compute true linear residual norm */
5345: VecDuplicate(b,&lres);
5346: MatMult(snes->jacobian,x,lres);
5347: VecAYPX(lres,-1.0,b);
5348: VecNorm(lres,NORM_2,&kctx->lresid_last);
5349: VecDestroy(&lres);
5350: }
5351: }
5352: return 0;
5353: }
5355: /*@
5356: SNESGetKSP - Returns the KSP context for a SNES solver.
5358: Not Collective, but if SNES object is parallel, then KSP object is parallel
5360: Input Parameter:
5361: . snes - the SNES context
5363: Output Parameter:
5364: . ksp - the KSP context
5366: Notes:
5367: The user can then directly manipulate the KSP context to set various
5368: options, etc. Likewise, the user can then extract and manipulate the
5369: PC contexts as well.
5371: Level: beginner
5373: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
5374: @*/
5375: PetscErrorCode SNESGetKSP(SNES snes,KSP *ksp)
5376: {
5380: if (!snes->ksp) {
5381: KSPCreate(PetscObjectComm((PetscObject)snes),&snes->ksp);
5382: PetscObjectIncrementTabLevel((PetscObject)snes->ksp,(PetscObject)snes,1);
5383: PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->ksp);
5385: KSPSetPreSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))KSPPreSolve_SNESEW,snes);
5386: KSPSetPostSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))KSPPostSolve_SNESEW,snes);
5388: KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes);
5389: PetscObjectSetOptions((PetscObject)snes->ksp,((PetscObject)snes)->options);
5390: }
5391: *ksp = snes->ksp;
5392: return 0;
5393: }
5395: #include <petsc/private/dmimpl.h>
5396: /*@
5397: SNESSetDM - Sets the DM that may be used by some nonlinear solvers or their underlying preconditioners
5399: Logically Collective on SNES
5401: Input Parameters:
5402: + snes - the nonlinear solver context
5403: - dm - the dm, cannot be NULL
5405: Notes:
5406: A DM can only be used for solving one problem at a time because information about the problem is stored on the DM,
5407: even when not using interfaces like DMSNESSetFunction(). Use DMClone() to get a distinct DM when solving different
5408: problems using the same function space.
5410: Level: intermediate
5412: .seealso: SNESGetDM(), KSPSetDM(), KSPGetDM()
5413: @*/
5414: PetscErrorCode SNESSetDM(SNES snes,DM dm)
5415: {
5416: KSP ksp;
5417: DMSNES sdm;
5421: PetscObjectReference((PetscObject)dm);
5422: if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
5423: if (snes->dm->dmsnes && !dm->dmsnes) {
5424: DMCopyDMSNES(snes->dm,dm);
5425: DMGetDMSNES(snes->dm,&sdm);
5426: if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
5427: }
5428: DMCoarsenHookRemove(snes->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,snes);
5429: DMDestroy(&snes->dm);
5430: }
5431: snes->dm = dm;
5432: snes->dmAuto = PETSC_FALSE;
5434: SNESGetKSP(snes,&ksp);
5435: KSPSetDM(ksp,dm);
5436: KSPSetDMActive(ksp,PETSC_FALSE);
5437: if (snes->npc) {
5438: SNESSetDM(snes->npc,snes->dm);
5439: SNESSetNPCSide(snes,snes->npcside);
5440: }
5441: return 0;
5442: }
5444: /*@
5445: SNESGetDM - Gets the DM that may be used by some preconditioners
5447: Not Collective but DM obtained is parallel on SNES
5449: Input Parameter:
5450: . snes - the preconditioner context
5452: Output Parameter:
5453: . dm - the dm
5455: Level: intermediate
5457: .seealso: SNESSetDM(), KSPSetDM(), KSPGetDM()
5458: @*/
5459: PetscErrorCode SNESGetDM(SNES snes,DM *dm)
5460: {
5462: if (!snes->dm) {
5463: DMShellCreate(PetscObjectComm((PetscObject)snes),&snes->dm);
5464: snes->dmAuto = PETSC_TRUE;
5465: }
5466: *dm = snes->dm;
5467: return 0;
5468: }
5470: /*@
5471: SNESSetNPC - Sets the nonlinear preconditioner to be used.
5473: Collective on SNES
5475: Input Parameters:
5476: + snes - iterative context obtained from SNESCreate()
5477: - pc - the preconditioner object
5479: Notes:
5480: Use SNESGetNPC() to retrieve the preconditioner context (for example,
5481: to configure it using the API).
5483: Level: developer
5485: .seealso: SNESGetNPC(), SNESHasNPC()
5486: @*/
5487: PetscErrorCode SNESSetNPC(SNES snes, SNES pc)
5488: {
5492: PetscObjectReference((PetscObject) pc);
5493: SNESDestroy(&snes->npc);
5494: snes->npc = pc;
5495: PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->npc);
5496: return 0;
5497: }
5499: /*@
5500: SNESGetNPC - Creates a nonlinear preconditioning solver (SNES) to be used to precondition the nonlinear solver.
5502: Not Collective; but any changes to the obtained SNES object must be applied collectively
5504: Input Parameter:
5505: . snes - iterative context obtained from SNESCreate()
5507: Output Parameter:
5508: . pc - preconditioner context
5510: Options Database:
5511: . -npc_snes_type <type> - set the type of the SNES to use as the nonlinear preconditioner
5513: Notes:
5514: If a SNES was previously set with SNESSetNPC() then that SNES is returned, otherwise a new SNES object is created.
5516: The (preconditioner) SNES returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5517: SNES during SNESSetUp()
5519: Level: developer
5521: .seealso: SNESSetNPC(), SNESHasNPC(), SNES, SNESCreate()
5522: @*/
5523: PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5524: {
5525: const char *optionsprefix;
5529: if (!snes->npc) {
5530: SNESCreate(PetscObjectComm((PetscObject)snes),&snes->npc);
5531: PetscObjectIncrementTabLevel((PetscObject)snes->npc,(PetscObject)snes,1);
5532: PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->npc);
5533: SNESGetOptionsPrefix(snes,&optionsprefix);
5534: SNESSetOptionsPrefix(snes->npc,optionsprefix);
5535: SNESAppendOptionsPrefix(snes->npc,"npc_");
5536: SNESSetCountersReset(snes->npc,PETSC_FALSE);
5537: }
5538: *pc = snes->npc;
5539: return 0;
5540: }
5542: /*@
5543: SNESHasNPC - Returns whether a nonlinear preconditioner exists
5545: Not Collective
5547: Input Parameter:
5548: . snes - iterative context obtained from SNESCreate()
5550: Output Parameter:
5551: . has_npc - whether the SNES has an NPC or not
5553: Level: developer
5555: .seealso: SNESSetNPC(), SNESGetNPC()
5556: @*/
5557: PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5558: {
5560: *has_npc = (PetscBool) (snes->npc ? PETSC_TRUE : PETSC_FALSE);
5561: return 0;
5562: }
5564: /*@
5565: SNESSetNPCSide - Sets the preconditioning side.
5567: Logically Collective on SNES
5569: Input Parameter:
5570: . snes - iterative context obtained from SNESCreate()
5572: Output Parameter:
5573: . side - the preconditioning side, where side is one of
5574: .vb
5575: PC_LEFT - left preconditioning
5576: PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5577: .ve
5579: Options Database Keys:
5580: . -snes_npc_side <right,left> - nonlinear preconditioner side
5582: Notes:
5583: SNESNRICHARDSON and SNESNCG only support left preconditioning.
5585: Level: intermediate
5587: .seealso: SNESGetNPCSide(), KSPSetPCSide()
5588: @*/
5589: PetscErrorCode SNESSetNPCSide(SNES snes,PCSide side)
5590: {
5593: if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
5595: snes->npcside = side;
5596: return 0;
5597: }
5599: /*@
5600: SNESGetNPCSide - Gets the preconditioning side.
5602: Not Collective
5604: Input Parameter:
5605: . snes - iterative context obtained from SNESCreate()
5607: Output Parameter:
5608: . side - the preconditioning side, where side is one of
5609: .vb
5610: PC_LEFT - left preconditioning
5611: PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5612: .ve
5614: Level: intermediate
5616: .seealso: SNESSetNPCSide(), KSPGetPCSide()
5617: @*/
5618: PetscErrorCode SNESGetNPCSide(SNES snes,PCSide *side)
5619: {
5622: *side = snes->npcside;
5623: return 0;
5624: }
5626: /*@
5627: SNESSetLineSearch - Sets the linesearch on the SNES instance.
5629: Collective on SNES
5631: Input Parameters:
5632: + snes - iterative context obtained from SNESCreate()
5633: - linesearch - the linesearch object
5635: Notes:
5636: Use SNESGetLineSearch() to retrieve the preconditioner context (for example,
5637: to configure it using the API).
5639: Level: developer
5641: .seealso: SNESGetLineSearch()
5642: @*/
5643: PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5644: {
5648: PetscObjectReference((PetscObject) linesearch);
5649: SNESLineSearchDestroy(&snes->linesearch);
5651: snes->linesearch = linesearch;
5653: PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->linesearch);
5654: return 0;
5655: }
5657: /*@
5658: SNESGetLineSearch - Returns a pointer to the line search context set with SNESSetLineSearch()
5659: or creates a default line search instance associated with the SNES and returns it.
5661: Not Collective
5663: Input Parameter:
5664: . snes - iterative context obtained from SNESCreate()
5666: Output Parameter:
5667: . linesearch - linesearch context
5669: Level: beginner
5671: .seealso: SNESSetLineSearch(), SNESLineSearchCreate()
5672: @*/
5673: PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5674: {
5675: const char *optionsprefix;
5679: if (!snes->linesearch) {
5680: SNESGetOptionsPrefix(snes, &optionsprefix);
5681: SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch);
5682: SNESLineSearchSetSNES(snes->linesearch, snes);
5683: SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix);
5684: PetscObjectIncrementTabLevel((PetscObject) snes->linesearch, (PetscObject) snes, 1);
5685: PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->linesearch);
5686: }
5687: *linesearch = snes->linesearch;
5688: return 0;
5689: }