Actual source code: snes.c
petsc-3.4.0 2013-05-13
2: #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/
3: #include <petscdmshell.h>
5: PetscBool SNESRegisterAllCalled = PETSC_FALSE;
6: PetscFunctionList SNESList = NULL;
8: /* Logging support */
9: PetscClassId SNES_CLASSID, DMSNES_CLASSID;
10: PetscLogEvent SNES_Solve, SNES_FunctionEval, SNES_JacobianEval, SNES_GSEval, SNES_NPCSolve;
14: /*@
15: SNESSetErrorIfNotConverged - Causes SNESSolve() to generate an error if the solver has not converged.
17: Logically Collective on SNES
19: Input Parameters:
20: + snes - iterative context obtained from SNESCreate()
21: - flg - PETSC_TRUE indicates you want the error generated
23: Options database keys:
24: . -snes_error_if_not_converged : this takes an optional truth value (0/1/no/yes/true/false)
26: Level: intermediate
28: Notes:
29: Normally PETSc continues if a linear solver fails to converge, you can call SNESGetConvergedReason() after a SNESSolve()
30: to determine if it has converged.
32: .keywords: SNES, set, initial guess, nonzero
34: .seealso: SNESGetErrorIfNotConverged(), KSPGetErrorIfNotConverged(), KSPSetErrorIFNotConverged()
35: @*/
36: PetscErrorCode SNESSetErrorIfNotConverged(SNES snes,PetscBool flg)
37: {
41: snes->errorifnotconverged = flg;
42: return(0);
43: }
47: /*@
48: SNESGetErrorIfNotConverged - Will SNESSolve() generate an error if the solver does not converge?
50: Not Collective
52: Input Parameter:
53: . snes - iterative context obtained from SNESCreate()
55: Output Parameter:
56: . flag - PETSC_TRUE if it will generate an error, else PETSC_FALSE
58: Level: intermediate
60: .keywords: SNES, set, initial guess, nonzero
62: .seealso: SNESSetErrorIfNotConverged(), KSPGetErrorIfNotConverged(), KSPSetErrorIFNotConverged()
63: @*/
64: PetscErrorCode SNESGetErrorIfNotConverged(SNES snes,PetscBool *flag)
65: {
69: *flag = snes->errorifnotconverged;
70: return(0);
71: }
75: /*@
76: SNESSetFunctionDomainError - tells SNES that the input vector to your SNESFunction is not
77: in the functions domain. For example, negative pressure.
79: Logically Collective on SNES
81: Input Parameters:
82: . snes - the SNES context
84: Level: advanced
86: .keywords: SNES, view
88: .seealso: SNESCreate(), SNESSetFunction(), SNESFunction
89: @*/
90: PetscErrorCode SNESSetFunctionDomainError(SNES snes)
91: {
94: snes->domainerror = PETSC_TRUE;
95: return(0);
96: }
100: /*@
101: SNESGetFunctionDomainError - Gets the status of the domain error after a call to SNESComputeFunction;
103: Logically Collective on SNES
105: Input Parameters:
106: . snes - the SNES context
108: Output Parameters:
109: . domainerror - Set to PETSC_TRUE if there's a domain error; PETSC_FALSE otherwise.
111: Level: advanced
113: .keywords: SNES, view
115: .seealso: SNESSetFunctionDomainError(), SNESComputeFunction()
116: @*/
117: PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
118: {
122: *domainerror = snes->domainerror;
123: return(0);
124: }
128: /*@C
129: SNESLoad - Loads a SNES that has been stored in binary with SNESView().
131: Collective on PetscViewer
133: Input Parameters:
134: + newdm - the newly loaded SNES, this needs to have been created with SNESCreate() or
135: some related function before a call to SNESLoad().
136: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
138: Level: intermediate
140: Notes:
141: The type is determined by the data in the file, any type set into the SNES before this call is ignored.
143: Notes for advanced users:
144: Most users should not need to know the details of the binary storage
145: format, since SNESLoad() and TSView() completely hide these details.
146: But for anyone who's interested, the standard binary matrix storage
147: format is
148: .vb
149: has not yet been determined
150: .ve
152: .seealso: PetscViewerBinaryOpen(), SNESView(), MatLoad(), VecLoad()
153: @*/
154: PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
155: {
157: PetscBool isbinary;
158: PetscInt classid;
159: char type[256];
160: KSP ksp;
161: DM dm;
162: DMSNES dmsnes;
167: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
168: if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
170: PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);
171: if (classid != SNES_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONG,"Not SNES next in file");
172: PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);
173: SNESSetType(snes, type);
174: if (snes->ops->load) {
175: (*snes->ops->load)(snes,viewer);
176: }
177: SNESGetDM(snes,&dm);
178: DMGetDMSNES(dm,&dmsnes);
179: DMSNESLoad(dmsnes,viewer);
180: SNESGetKSP(snes,&ksp);
181: KSPLoad(ksp,viewer);
182: return(0);
183: }
185: #include <petscdraw.h>
186: #if defined(PETSC_HAVE_AMS)
187: #include <petscviewerams.h>
188: #endif
191: /*@C
192: SNESView - Prints the SNES data structure.
194: Collective on SNES
196: Input Parameters:
197: + SNES - the SNES context
198: - viewer - visualization context
200: Options Database Key:
201: . -snes_view - Calls SNESView() at end of SNESSolve()
203: Notes:
204: The available visualization contexts include
205: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
206: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
207: output where only the first processor opens
208: the file. All other processors send their
209: data to the first processor to print.
211: The user can open an alternative visualization context with
212: PetscViewerASCIIOpen() - output to a specified file.
214: Level: beginner
216: .keywords: SNES, view
218: .seealso: PetscViewerASCIIOpen()
219: @*/
220: PetscErrorCode SNESView(SNES snes,PetscViewer viewer)
221: {
222: SNESKSPEW *kctx;
224: KSP ksp;
225: SNESLineSearch linesearch;
226: PetscBool iascii,isstring,isbinary,isdraw;
227: DMSNES dmsnes;
228: #if defined(PETSC_HAVE_AMS)
229: PetscBool isams;
230: #endif
234: if (!viewer) {
235: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);
236: }
240: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
241: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
242: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
243: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
244: #if defined(PETSC_HAVE_AMS)
245: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERAMS,&isams);
246: #endif
247: if (iascii) {
248: PetscObjectPrintClassNamePrefixType((PetscObject)snes,viewer,"SNES Object");
249: if (snes->ops->view) {
250: PetscViewerASCIIPushTab(viewer);
251: (*snes->ops->view)(snes,viewer);
252: PetscViewerASCIIPopTab(viewer);
253: }
254: PetscViewerASCIIPrintf(viewer," maximum iterations=%D, maximum function evaluations=%D\n",snes->max_its,snes->max_funcs);
255: PetscViewerASCIIPrintf(viewer," tolerances: relative=%G, absolute=%G, solution=%G\n",snes->rtol,snes->abstol,snes->stol);
256: PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",snes->linear_its);
257: PetscViewerASCIIPrintf(viewer," total number of function evaluations=%D\n",snes->nfuncs);
258: if (snes->gridsequence) {
259: PetscViewerASCIIPrintf(viewer," total number of grid sequence refinements=%D\n",snes->gridsequence);
260: }
261: if (snes->ksp_ewconv) {
262: kctx = (SNESKSPEW*)snes->kspconvctx;
263: if (kctx) {
264: PetscViewerASCIIPrintf(viewer," Eisenstat-Walker computation of KSP relative tolerance (version %D)\n",kctx->version);
265: PetscViewerASCIIPrintf(viewer," rtol_0=%G, rtol_max=%G, threshold=%G\n",kctx->rtol_0,kctx->rtol_max,kctx->threshold);
266: PetscViewerASCIIPrintf(viewer," gamma=%G, alpha=%G, alpha2=%G\n",kctx->gamma,kctx->alpha,kctx->alpha2);
267: }
268: }
269: if (snes->lagpreconditioner == -1) {
270: PetscViewerASCIIPrintf(viewer," Preconditioned is never rebuilt\n");
271: } else if (snes->lagpreconditioner > 1) {
272: PetscViewerASCIIPrintf(viewer," Preconditioned is rebuilt every %D new Jacobians\n",snes->lagpreconditioner);
273: }
274: if (snes->lagjacobian == -1) {
275: PetscViewerASCIIPrintf(viewer," Jacobian is never rebuilt\n");
276: } else if (snes->lagjacobian > 1) {
277: PetscViewerASCIIPrintf(viewer," Jacobian is rebuilt every %D SNES iterations\n",snes->lagjacobian);
278: }
279: } else if (isstring) {
280: const char *type;
281: SNESGetType(snes,&type);
282: PetscViewerStringSPrintf(viewer," %-3.3s",type);
283: } else if (isbinary) {
284: PetscInt classid = SNES_FILE_CLASSID;
285: MPI_Comm comm;
286: PetscMPIInt rank;
287: char type[256];
289: PetscObjectGetComm((PetscObject)snes,&comm);
290: MPI_Comm_rank(comm,&rank);
291: if (!rank) {
292: PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);
293: PetscStrncpy(type,((PetscObject)snes)->type_name,256);
294: PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);
295: }
296: if (snes->ops->view) {
297: (*snes->ops->view)(snes,viewer);
298: }
299: } else if (isdraw) {
300: PetscDraw draw;
301: char str[36];
302: PetscReal x,y,bottom,h;
304: PetscViewerDrawGetDraw(viewer,0,&draw);
305: PetscDrawGetCurrentPoint(draw,&x,&y);
306: PetscStrcpy(str,"SNES: ");
307: PetscStrcat(str,((PetscObject)snes)->type_name);
308: PetscDrawBoxedString(draw,x,y,PETSC_DRAW_BLUE,PETSC_DRAW_BLACK,str,NULL,&h);
309: bottom = y - h;
310: PetscDrawPushCurrentPoint(draw,x,bottom);
311: if (snes->ops->view) {
312: (*snes->ops->view)(snes,viewer);
313: }
314: #if defined(PETSC_HAVE_AMS)
315: } else if (isams) {
316: if (((PetscObject)snes)->amsmem == -1) {
317: PetscObjectViewAMS((PetscObject)snes,viewer);
318: PetscStackCallAMS(AMS_Memory_take_access,(((PetscObject)snes)->amsmem));
319: PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)snes)->amsmem,"its",&snes->iter,1,AMS_INT,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF));
320: if (!snes->conv_hist) {
321: SNESSetConvergenceHistory(snes,NULL,NULL,PETSC_DECIDE,PETSC_FALSE);
322: }
323: PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)snes)->amsmem,"conv_hist",snes->conv_hist,10,AMS_DOUBLE,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF));
324: PetscStackCallAMS(AMS_Memory_grant_access,(((PetscObject)snes)->amsmem));
325: }
326: #endif
327: }
328: if (snes->linesearch) {
329: PetscViewerASCIIPushTab(viewer);
330: SNESGetLineSearch(snes, &linesearch);
331: SNESLineSearchView(linesearch, viewer);
332: PetscViewerASCIIPopTab(viewer);
333: }
334: if (snes->pc && snes->usespc) {
335: PetscViewerASCIIPushTab(viewer);
336: SNESView(snes->pc, viewer);
337: PetscViewerASCIIPopTab(viewer);
338: }
339: PetscViewerASCIIPushTab(viewer);
340: DMGetDMSNES(snes->dm,&dmsnes);
341: DMSNESView(dmsnes, viewer);
342: PetscViewerASCIIPopTab(viewer);
343: if (snes->usesksp) {
344: SNESGetKSP(snes,&ksp);
345: PetscViewerASCIIPushTab(viewer);
346: KSPView(ksp,viewer);
347: PetscViewerASCIIPopTab(viewer);
348: }
349: if (isdraw) {
350: PetscDraw draw;
351: PetscViewerDrawGetDraw(viewer,0,&draw);
352: PetscDrawPopCurrentPoint(draw);
353: }
354: return(0);
355: }
357: /*
358: We retain a list of functions that also take SNES command
359: line options. These are called at the end SNESSetFromOptions()
360: */
361: #define MAXSETFROMOPTIONS 5
362: static PetscInt numberofsetfromoptions;
363: static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
367: /*@C
368: SNESAddOptionsChecker - Adds an additional function to check for SNES options.
370: Not Collective
372: Input Parameter:
373: . snescheck - function that checks for options
375: Level: developer
377: .seealso: SNESSetFromOptions()
378: @*/
379: PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES))
380: {
382: if (numberofsetfromoptions >= MAXSETFROMOPTIONS) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %D allowed", MAXSETFROMOPTIONS);
383: othersetfromoptions[numberofsetfromoptions++] = snescheck;
384: return(0);
385: }
387: extern PetscErrorCode SNESDefaultMatrixFreeCreate2(SNES,Vec,Mat*);
391: static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
392: {
393: Mat J;
394: KSP ksp;
395: PC pc;
396: PetscBool match;
402: if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
403: Mat A = snes->jacobian, B = snes->jacobian_pre;
404: MatGetVecs(A ? A : B, NULL,&snes->vec_func);
405: }
407: if (version == 1) {
408: MatCreateSNESMF(snes,&J);
409: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
410: MatSetFromOptions(J);
411: } else if (version == 2) {
412: if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"SNESSetFunction() must be called first");
413: #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
414: SNESDefaultMatrixFreeCreate2(snes,snes->vec_func,&J);
415: #else
416: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "matrix-free operator rutines (version 2)");
417: #endif
418: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator rutines, only version 1 and 2");
420: PetscInfo1(snes,"Setting default matrix-free operator routines (version %D)\n", version);
421: if (hasOperator) {
423: /* This version replaces the user provided Jacobian matrix with a
424: matrix-free version but still employs the user-provided preconditioner matrix. */
425: SNESSetJacobian(snes,J,0,0,0);
426: } else {
427: /* This version replaces both the user-provided Jacobian and the user-
428: provided preconditioner Jacobian with the default matrix free version. */
429: if ((snes->pcside == PC_LEFT) && snes->pc) {
430: if (!snes->jacobian){SNESSetJacobian(snes,J,0,0,0);}
431: } else {
432: SNESSetJacobian(snes,J,J,MatMFFDComputeJacobian,0);
433: }
434: /* Force no preconditioner */
435: SNESGetKSP(snes,&ksp);
436: KSPGetPC(ksp,&pc);
437: PetscObjectTypeCompare((PetscObject)pc,PCSHELL,&match);
438: if (!match) {
439: PetscInfo(snes,"Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n");
440: PCSetType(pc,PCNONE);
441: }
442: }
443: MatDestroy(&J);
444: return(0);
445: }
449: static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine,Mat Restrict,Vec Rscale,Mat Inject,DM dmcoarse,void *ctx)
450: {
451: SNES snes = (SNES)ctx;
453: Vec Xfine,Xfine_named = NULL,Xcoarse;
456: if (PetscLogPrintInfo) {
457: PetscInt finelevel,coarselevel,fineclevel,coarseclevel;
458: DMGetRefineLevel(dmfine,&finelevel);
459: DMGetCoarsenLevel(dmfine,&fineclevel);
460: DMGetRefineLevel(dmcoarse,&coarselevel);
461: DMGetCoarsenLevel(dmcoarse,&coarseclevel);
462: PetscInfo4(dmfine,"Restricting SNES solution vector from level %D-%D to level %D-%D\n",finelevel,fineclevel,coarselevel,coarseclevel);
463: }
464: if (dmfine == snes->dm) Xfine = snes->vec_sol;
465: else {
466: DMGetNamedGlobalVector(dmfine,"SNESVecSol",&Xfine_named);
467: Xfine = Xfine_named;
468: }
469: DMGetNamedGlobalVector(dmcoarse,"SNESVecSol",&Xcoarse);
470: MatRestrict(Restrict,Xfine,Xcoarse);
471: VecPointwiseMult(Xcoarse,Xcoarse,Rscale);
472: DMRestoreNamedGlobalVector(dmcoarse,"SNESVecSol",&Xcoarse);
473: if (Xfine_named) {DMRestoreNamedGlobalVector(dmfine,"SNESVecSol",&Xfine_named);}
474: return(0);
475: }
479: static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm,DM dmc,void *ctx)
480: {
484: DMCoarsenHookAdd(dmc,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,ctx);
485: return(0);
486: }
490: /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
491: * safely call SNESGetDM() in their residual evaluation routine. */
492: static PetscErrorCode KSPComputeOperators_SNES(KSP ksp,Mat A,Mat B,MatStructure *mstruct,void *ctx)
493: {
494: SNES snes = (SNES)ctx;
496: Mat Asave = A,Bsave = B;
497: Vec X,Xnamed = NULL;
498: DM dmsave;
499: void *ctxsave;
500: PetscErrorCode (*jac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
503: dmsave = snes->dm;
504: KSPGetDM(ksp,&snes->dm);
505: if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
506: else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */
507: DMGetNamedGlobalVector(snes->dm,"SNESVecSol",&Xnamed);
508: X = Xnamed;
509: SNESGetJacobian(snes,NULL,NULL,&jac,&ctxsave);
510: /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
511: if (jac == SNESComputeJacobianDefaultColor) {
512: SNESSetJacobian(snes,NULL,NULL,SNESComputeJacobianDefaultColor,0);
513: }
514: }
515: /* put the previous context back */
517: SNESComputeJacobian(snes,X,&A,&B,mstruct);
518: if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) {
519: SNESSetJacobian(snes,NULL,NULL,jac,ctxsave);
520: }
522: if (A != Asave || B != Bsave) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"No support for changing matrices at this time");
523: if (Xnamed) {
524: DMRestoreNamedGlobalVector(snes->dm,"SNESVecSol",&Xnamed);
525: }
526: snes->dm = dmsave;
527: return(0);
528: }
532: /*@
533: SNESSetUpMatrices - ensures that matrices are available for SNES, to be called by SNESSetUp_XXX()
535: Collective
537: Input Arguments:
538: . snes - snes to configure
540: Level: developer
542: .seealso: SNESSetUp()
543: @*/
544: PetscErrorCode SNESSetUpMatrices(SNES snes)
545: {
547: DM dm;
548: DMSNES sdm;
551: SNESGetDM(snes,&dm);
552: DMGetDMSNES(dm,&sdm);
553: if (!sdm->ops->computejacobian) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"DMSNES not properly configured");
554: else if (!snes->jacobian && snes->mf) {
555: Mat J;
556: void *functx;
557: MatCreateSNESMF(snes,&J);
558: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
559: MatSetFromOptions(J);
560: SNESGetFunction(snes,NULL,NULL,&functx);
561: SNESSetJacobian(snes,J,J,0,0);
562: MatDestroy(&J);
563: } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
564: Mat J,B;
565: MatCreateSNESMF(snes,&J);
566: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
567: MatSetFromOptions(J);
568: DMCreateMatrix(snes->dm,MATAIJ,&B);
569: /* sdm->computejacobian was already set to reach here */
570: SNESSetJacobian(snes,J,B,NULL,NULL);
571: MatDestroy(&J);
572: MatDestroy(&B);
573: } else if (!snes->jacobian_pre) {
574: Mat J,B;
575: J = snes->jacobian;
576: DMCreateMatrix(snes->dm,MATAIJ,&B);
577: SNESSetJacobian(snes,J ? J : B,B,NULL,NULL);
578: MatDestroy(&B);
579: }
580: {
581: KSP ksp;
582: SNESGetKSP(snes,&ksp);
583: KSPSetComputeOperators(ksp,KSPComputeOperators_SNES,snes);
584: DMCoarsenHookAdd(snes->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,snes);
585: }
586: return(0);
587: }
591: /*@
592: SNESSetFromOptions - Sets various SNES and KSP parameters from user options.
594: Collective on SNES
596: Input Parameter:
597: . snes - the SNES context
599: Options Database Keys:
600: + -snes_type <type> - ls, tr, ngmres, ncg, richardson, qn, vi, fas
601: . -snes_stol - convergence tolerance in terms of the norm
602: of the change in the solution between steps
603: . -snes_atol <abstol> - absolute tolerance of residual norm
604: . -snes_rtol <rtol> - relative decrease in tolerance norm from initial
605: . -snes_max_it <max_it> - maximum number of iterations
606: . -snes_max_funcs <max_funcs> - maximum number of function evaluations
607: . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
608: . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
609: . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild)
610: . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild)
611: . -snes_trtol <trtol> - trust region tolerance
612: . -snes_no_convergence_test - skip convergence test in nonlinear
613: solver; hence iterations will continue until max_it
614: or some other criterion is reached. Saves expense
615: of convergence test
616: . -snes_monitor <optional filename> - prints residual norm at each iteration. if no
617: filename given prints to stdout
618: . -snes_monitor_solution - plots solution at each iteration
619: . -snes_monitor_residual - plots residual (not its norm) at each iteration
620: . -snes_monitor_solution_update - plots update to solution at each iteration
621: . -snes_monitor_lg_residualnorm - plots residual norm at each iteration
622: . -snes_monitor_lg_range - plots residual norm at each iteration
623: . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
624: . -snes_fd_color - use finite differences with coloring to compute Jacobian
625: . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration
626: - -snes_converged_reason - print the reason for convergence/divergence after each solve
628: Options Database for Eisenstat-Walker method:
629: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
630: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
631: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
632: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
633: . -snes_ksp_ew_gamma <gamma> - Sets gamma
634: . -snes_ksp_ew_alpha <alpha> - Sets alpha
635: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
636: - -snes_ksp_ew_threshold <threshold> - Sets threshold
638: Notes:
639: To see all options, run your program with the -help option or consult
640: the <A href="../../docs/manual.pdf#nameddest=ch_snes">SNES chapter of the users manual</A>.
642: Level: beginner
644: .keywords: SNES, nonlinear, set, options, database
646: .seealso: SNESSetOptionsPrefix()
647: @*/
648: PetscErrorCode SNESSetFromOptions(SNES snes)
649: {
650: PetscBool flg,pcset;
651: PetscInt i,indx,lag,grids;
652: MatStructure matflag;
653: const char *deft = SNESNEWTONLS;
654: const char *convtests[] = {"default","skip"};
655: SNESKSPEW *kctx = NULL;
656: char type[256], monfilename[PETSC_MAX_PATH_LEN];
657: PetscViewer monviewer;
659: PCSide pcside;
660: const char *optionsprefix;
665: if (!SNESRegisterAllCalled) {SNESRegisterAll();}
666: PetscObjectOptionsBegin((PetscObject)snes);
667: if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
668: PetscOptionsList("-snes_type","Nonlinear solver method","SNESSetType",SNESList,deft,type,256,&flg);
669: if (flg) {
670: SNESSetType(snes,type);
671: } else if (!((PetscObject)snes)->type_name) {
672: SNESSetType(snes,deft);
673: }
674: /* not used here, but called so will go into help messaage */
675: PetscOptionsName("-snes_view","Print detailed information on solver used","SNESView",0);
677: PetscOptionsReal("-snes_stol","Stop if step length less than","SNESSetTolerances",snes->stol,&snes->stol,0);
678: PetscOptionsReal("-snes_atol","Stop if function norm less than","SNESSetTolerances",snes->abstol,&snes->abstol,0);
680: PetscOptionsReal("-snes_rtol","Stop if decrease in function norm less than","SNESSetTolerances",snes->rtol,&snes->rtol,0);
681: PetscOptionsInt("-snes_max_it","Maximum iterations","SNESSetTolerances",snes->max_its,&snes->max_its,NULL);
682: PetscOptionsInt("-snes_max_funcs","Maximum function evaluations","SNESSetTolerances",snes->max_funcs,&snes->max_funcs,NULL);
683: PetscOptionsInt("-snes_max_fail","Maximum nonlinear step failures","SNESSetMaxNonlinearStepFailures",snes->maxFailures,&snes->maxFailures,NULL);
684: PetscOptionsInt("-snes_max_linear_solve_fail","Maximum failures in linear solves allowed","SNESSetMaxLinearSolveFailures",snes->maxLinearSolveFailures,&snes->maxLinearSolveFailures,NULL);
685: PetscOptionsBool("-snes_error_if_not_converged","Generate error if solver does not converge","SNESSetErrorIfNotConverged",snes->errorifnotconverged,&snes->errorifnotconverged,NULL);
687: PetscOptionsInt("-snes_lag_preconditioner","How often to rebuild preconditioner","SNESSetLagPreconditioner",snes->lagpreconditioner,&lag,&flg);
688: if (flg) {
689: SNESSetLagPreconditioner(snes,lag);
690: }
691: PetscOptionsInt("-snes_lag_jacobian","How often to rebuild Jacobian","SNESSetLagJacobian",snes->lagjacobian,&lag,&flg);
692: if (flg) {
693: SNESSetLagJacobian(snes,lag);
694: }
695: PetscOptionsInt("-snes_grid_sequence","Use grid sequencing to generate initial guess","SNESSetGridSequence",snes->gridsequence,&grids,&flg);
696: if (flg) {
697: SNESSetGridSequence(snes,grids);
698: }
700: PetscOptionsEList("-snes_convergence_test","Convergence test","SNESSetConvergenceTest",convtests,2,"default",&indx,&flg);
701: if (flg) {
702: switch (indx) {
703: case 0: SNESSetConvergenceTest(snes,SNESConvergedDefault,NULL,NULL); break;
704: case 1: SNESSetConvergenceTest(snes,SNESSkipConverged,NULL,NULL); break;
705: }
706: }
708: PetscOptionsBool("-snes_converged_reason","Print reason for converged or diverged","SNESSolve",snes->printreason,&snes->printreason,NULL);
710: PetscOptionsEList("-snes_norm_type","SNES Norm type","SNESSetNormType",SNESNormTypes,5,"function",&indx,&flg);
711: if (flg) { SNESSetNormType(snes,(SNESNormType)indx); }
713: kctx = (SNESKSPEW*)snes->kspconvctx;
715: PetscOptionsBool("-snes_ksp_ew","Use Eisentat-Walker linear system convergence test","SNESKSPSetUseEW",snes->ksp_ewconv,&snes->ksp_ewconv,NULL);
717: PetscOptionsInt("-snes_ksp_ew_version","Version 1, 2 or 3","SNESKSPSetParametersEW",kctx->version,&kctx->version,0);
718: PetscOptionsReal("-snes_ksp_ew_rtol0","0 <= rtol0 < 1","SNESKSPSetParametersEW",kctx->rtol_0,&kctx->rtol_0,0);
719: PetscOptionsReal("-snes_ksp_ew_rtolmax","0 <= rtolmax < 1","SNESKSPSetParametersEW",kctx->rtol_max,&kctx->rtol_max,0);
720: PetscOptionsReal("-snes_ksp_ew_gamma","0 <= gamma <= 1","SNESKSPSetParametersEW",kctx->gamma,&kctx->gamma,0);
721: PetscOptionsReal("-snes_ksp_ew_alpha","1 < alpha <= 2","SNESKSPSetParametersEW",kctx->alpha,&kctx->alpha,0);
722: PetscOptionsReal("-snes_ksp_ew_alpha2","alpha2","SNESKSPSetParametersEW",kctx->alpha2,&kctx->alpha2,0);
723: PetscOptionsReal("-snes_ksp_ew_threshold","0 < threshold < 1","SNESKSPSetParametersEW",kctx->threshold,&kctx->threshold,0);
725: flg = PETSC_FALSE;
726: PetscOptionsBool("-snes_check_jacobian","Check each Jacobian with a differenced one","SNESUpdateCheckJacobian",flg,&flg,NULL);
727: if (flg) {
728: SNESSetUpdate(snes,SNESUpdateCheckJacobian);
729: }
731: flg = PETSC_FALSE;
732: PetscOptionsBool("-snes_monitor_cancel","Remove all monitors","SNESMonitorCancel",flg,&flg,NULL);
733: if (flg) {SNESMonitorCancel(snes);}
735: PetscOptionsString("-snes_monitor","Monitor norm of function","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
736: if (flg) {
737: PetscViewerASCIIOpen(PetscObjectComm((PetscObject)snes),monfilename,&monviewer);
738: SNESMonitorSet(snes,SNESMonitorDefault,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);
739: }
741: PetscOptionsString("-snes_monitor_range","Monitor range of elements of function","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
742: if (flg) {
743: SNESMonitorSet(snes,SNESMonitorRange,0,0);
744: }
746: PetscOptionsString("-snes_ratiomonitor","Monitor ratios of norms of function","SNESMonitorSetRatio","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
747: if (flg) {
748: PetscViewerASCIIOpen(PetscObjectComm((PetscObject)snes),monfilename,&monviewer);
749: SNESMonitorSetRatio(snes,monviewer);
750: }
752: PetscOptionsString("-snes_monitor_short","Monitor norm of function (fewer digits)","SNESMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
753: if (flg) {
754: PetscViewerASCIIOpen(PetscObjectComm((PetscObject)snes),monfilename,&monviewer);
755: SNESMonitorSet(snes,SNESMonitorDefaultShort,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);
756: }
758: PetscOptionsString("-snes_monitor_python","Use Python function","SNESMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);
759: if (flg) {PetscPythonMonitorSet((PetscObject)snes,monfilename);}
761: flg = PETSC_FALSE;
762: PetscOptionsBool("-snes_monitor_solution","Plot solution at each iteration","SNESMonitorSolution",flg,&flg,NULL);
763: if (flg) {SNESMonitorSet(snes,SNESMonitorSolution,0,0);}
764: flg = PETSC_FALSE;
765: PetscOptionsBool("-snes_monitor_solution_update","Plot correction at each iteration","SNESMonitorSolutionUpdate",flg,&flg,NULL);
766: if (flg) {SNESMonitorSet(snes,SNESMonitorSolutionUpdate,0,0);}
767: flg = PETSC_FALSE;
768: PetscOptionsBool("-snes_monitor_residual","Plot residual at each iteration","SNESMonitorResidual",flg,&flg,NULL);
769: if (flg) {SNESMonitorSet(snes,SNESMonitorResidual,0,0);}
770: flg = PETSC_FALSE;
771: PetscOptionsBool("-snes_monitor_lg_residualnorm","Plot function norm at each iteration","SNESMonitorLGResidualNorm",flg,&flg,NULL);
772: if (flg) {
773: PetscDrawLG ctx;
775: SNESMonitorLGCreate(0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&ctx);
776: SNESMonitorSet(snes,SNESMonitorLGResidualNorm,ctx,(PetscErrorCode (*)(void**))SNESMonitorLGDestroy);
777: }
778: flg = PETSC_FALSE;
779: PetscOptionsBool("-snes_monitor_lg_range","Plot function range at each iteration","SNESMonitorLGRange",flg,&flg,NULL);
780: if (flg) {
781: PetscViewer ctx;
783: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&ctx);
784: SNESMonitorSet(snes,SNESMonitorLGRange,ctx,(PetscErrorCode (*)(void**))PetscViewerDestroy);
785: }
787: flg = PETSC_FALSE;
788: PetscOptionsBool("-snes_monitor_jacupdate_spectrum","Print the change in the spectrum of the Jacobian","SNESMonitorJacUpdateSpectrum",flg,&flg,NULL);
789: if (flg) {SNESMonitorSet(snes,SNESMonitorJacUpdateSpectrum,0,0);}
791: flg = PETSC_FALSE;
792: PetscOptionsBool("-snes_fd","Use finite differences (slow) to compute Jacobian","SNESComputeJacobianDefault",flg,&flg,NULL);
793: if (flg) {
794: void *functx;
795: SNESGetFunction(snes,NULL,NULL,&functx);
796: SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESComputeJacobianDefault,functx);
797: PetscInfo(snes,"Setting default finite difference Jacobian matrix\n");
798: }
800: flg = PETSC_FALSE;
801: PetscOptionsBool("-snes_fd_function","Use finite differences (slow) to compute function from user objective","SNESObjectiveComputeFunctionDefaultFD",flg,&flg,NULL);
802: if (flg) {
803: SNESSetFunction(snes,NULL,SNESObjectiveComputeFunctionDefaultFD,NULL);
804: }
806: flg = PETSC_FALSE;
807: PetscOptionsBool("-snes_fd_color","Use finite differences with coloring to compute Jacobian","SNESComputeJacobianDefaultColor",flg,&flg,NULL);
808: if (flg) {
809: void *functx;
810: SNESGetFunction(snes,NULL,NULL,&functx);
811: SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESComputeJacobianDefaultColor,0);
812: PetscInfo(snes,"Setting default finite difference coloring Jacobian matrix\n");
813: }
815: flg = PETSC_FALSE;
816: PetscOptionsBool("-snes_mf_operator","Use a Matrix-Free Jacobian with user-provided preconditioner matrix","MatCreateSNESMF",PETSC_FALSE,&snes->mf_operator,&flg);
817: if (flg && snes->mf_operator) {
818: snes->mf_operator = PETSC_TRUE;
819: snes->mf = PETSC_TRUE;
820: }
821: flg = PETSC_FALSE;
822: PetscOptionsBool("-snes_mf","Use a Matrix-Free Jacobian with no preconditioner matrix","MatCreateSNESMF",PETSC_FALSE,&snes->mf,&flg);
823: if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
824: PetscOptionsInt("-snes_mf_version","Matrix-Free routines version 1 or 2","None",snes->mf_version,&snes->mf_version,0);
826: flg = PETSC_FALSE;
827: SNESGetPCSide(snes,&pcside);
828: PetscOptionsEnum("-snes_npc_side","SNES nonlinear preconditioner side","SNESSetPCSide",PCSides,(PetscEnum)pcside,(PetscEnum*)&pcside,&flg);
829: if (flg) {SNESSetPCSide(snes,pcside);}
831: #if defined(PETSC_HAVE_AMS)
832: {
833: PetscBool set;
834: flg = PETSC_FALSE;
835: PetscOptionsBool("-snes_ams_block","Block for AMS memory snooper at end of SNESSolve","PetscObjectAMSBlock",((PetscObject)snes)->amspublishblock,&flg,&set);
836: if (set) {
837: PetscObjectAMSSetBlock((PetscObject)snes,flg);
838: }
839: }
840: #endif
842: for (i = 0; i < numberofsetfromoptions; i++) {
843: (*othersetfromoptions[i])(snes);
844: }
846: if (snes->ops->setfromoptions) {
847: (*snes->ops->setfromoptions)(snes);
848: }
850: /* process any options handlers added with PetscObjectAddOptionsHandler() */
851: PetscObjectProcessOptionsHandlers((PetscObject)snes);
852: PetscOptionsEnd();
854: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
855: KSPGetOperators(snes->ksp,NULL,NULL,&matflag);
856: KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,matflag);
857: KSPSetFromOptions(snes->ksp);
859: if (!snes->linesearch) {
860: SNESGetLineSearch(snes, &snes->linesearch);
861: }
862: SNESLineSearchSetFromOptions(snes->linesearch);
864: /* if someone has set the SNES PC type, create it. */
865: SNESGetOptionsPrefix(snes, &optionsprefix);
866: PetscOptionsHasName(optionsprefix, "-npc_snes_type", &pcset);
867: if (pcset && (!snes->pc)) {
868: SNESGetPC(snes, &snes->pc);
869: }
870: return(0);
871: }
875: /*@C
876: SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
877: the nonlinear solvers.
879: Logically Collective on SNES
881: Input Parameters:
882: + snes - the SNES context
883: . compute - function to compute the context
884: - destroy - function to destroy the context
886: Level: intermediate
888: Notes:
889: This function is currently not available from Fortran.
891: .keywords: SNES, nonlinear, set, application, context
893: .seealso: SNESGetApplicationContext(), SNESSetComputeApplicationContext(), SNESGetApplicationContext()
894: @*/
895: PetscErrorCode SNESSetComputeApplicationContext(SNES snes,PetscErrorCode (*compute)(SNES,void**),PetscErrorCode (*destroy)(void**))
896: {
899: snes->ops->usercompute = compute;
900: snes->ops->userdestroy = destroy;
901: return(0);
902: }
906: /*@
907: SNESSetApplicationContext - Sets the optional user-defined context for
908: the nonlinear solvers.
910: Logically Collective on SNES
912: Input Parameters:
913: + snes - the SNES context
914: - usrP - optional user context
916: Level: intermediate
918: .keywords: SNES, nonlinear, set, application, context
920: .seealso: SNESGetApplicationContext()
921: @*/
922: PetscErrorCode SNESSetApplicationContext(SNES snes,void *usrP)
923: {
925: KSP ksp;
929: SNESGetKSP(snes,&ksp);
930: KSPSetApplicationContext(ksp,usrP);
931: snes->user = usrP;
932: return(0);
933: }
937: /*@
938: SNESGetApplicationContext - Gets the user-defined context for the
939: nonlinear solvers.
941: Not Collective
943: Input Parameter:
944: . snes - SNES context
946: Output Parameter:
947: . usrP - user context
949: Level: intermediate
951: .keywords: SNES, nonlinear, get, application, context
953: .seealso: SNESSetApplicationContext()
954: @*/
955: PetscErrorCode SNESGetApplicationContext(SNES snes,void *usrP)
956: {
959: *(void**)usrP = snes->user;
960: return(0);
961: }
965: /*@
966: SNESGetIterationNumber - Gets the number of nonlinear iterations completed
967: at this time.
969: Not Collective
971: Input Parameter:
972: . snes - SNES context
974: Output Parameter:
975: . iter - iteration number
977: Notes:
978: For example, during the computation of iteration 2 this would return 1.
980: This is useful for using lagged Jacobians (where one does not recompute the
981: Jacobian at each SNES iteration). For example, the code
982: .vb
983: SNESGetIterationNumber(snes,&it);
984: if (!(it % 2)) {
985: [compute Jacobian here]
986: }
987: .ve
988: can be used in your ComputeJacobian() function to cause the Jacobian to be
989: recomputed every second SNES iteration.
991: Level: intermediate
993: .keywords: SNES, nonlinear, get, iteration, number,
995: .seealso: SNESGetFunctionNorm(), SNESGetLinearSolveIterations()
996: @*/
997: PetscErrorCode SNESGetIterationNumber(SNES snes,PetscInt *iter)
998: {
1002: *iter = snes->iter;
1003: return(0);
1004: }
1008: /*@
1009: SNESSetIterationNumber - Sets the current iteration number.
1011: Not Collective
1013: Input Parameter:
1014: . snes - SNES context
1015: . iter - iteration number
1017: Level: developer
1019: .keywords: SNES, nonlinear, set, iteration, number,
1021: .seealso: SNESGetFunctionNorm(), SNESGetLinearSolveIterations()
1022: @*/
1023: PetscErrorCode SNESSetIterationNumber(SNES snes,PetscInt iter)
1024: {
1029: PetscObjectAMSTakeAccess((PetscObject)snes);
1030: snes->iter = iter;
1031: PetscObjectAMSGrantAccess((PetscObject)snes);
1032: return(0);
1033: }
1037: /*@
1038: SNESGetFunctionNorm - Gets the norm of the current function that was set
1039: with SNESSSetFunction().
1041: Collective on SNES
1043: Input Parameter:
1044: . snes - SNES context
1046: Output Parameter:
1047: . fnorm - 2-norm of function
1049: Level: intermediate
1051: .keywords: SNES, nonlinear, get, function, norm
1053: .seealso: SNESGetFunction(), SNESGetIterationNumber(), SNESGetLinearSolveIterations()
1054: @*/
1055: PetscErrorCode SNESGetFunctionNorm(SNES snes,PetscReal *fnorm)
1056: {
1060: *fnorm = snes->norm;
1061: return(0);
1062: }
1067: /*@
1068: SNESSetFunctionNorm - Sets the 2-norm of the current function computed using VecNorm().
1070: Collective on SNES
1072: Input Parameter:
1073: . snes - SNES context
1074: . fnorm - 2-norm of function
1076: Level: developer
1078: .keywords: SNES, nonlinear, set, function, norm
1080: .seealso: SNESSetFunction(), SNESSetIterationNumber(), VecNorm().
1081: @*/
1082: PetscErrorCode SNESSetFunctionNorm(SNES snes,PetscReal fnorm)
1083: {
1089: PetscObjectAMSTakeAccess((PetscObject)snes);
1090: snes->norm = fnorm;
1091: PetscObjectAMSGrantAccess((PetscObject)snes);
1092: return(0);
1093: }
1097: /*@
1098: SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1099: attempted by the nonlinear solver.
1101: Not Collective
1103: Input Parameter:
1104: . snes - SNES context
1106: Output Parameter:
1107: . nfails - number of unsuccessful steps attempted
1109: Notes:
1110: This counter is reset to zero for each successive call to SNESSolve().
1112: Level: intermediate
1114: .keywords: SNES, nonlinear, get, number, unsuccessful, steps
1116: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1117: SNESSetMaxNonlinearStepFailures(), SNESGetMaxNonlinearStepFailures()
1118: @*/
1119: PetscErrorCode SNESGetNonlinearStepFailures(SNES snes,PetscInt *nfails)
1120: {
1124: *nfails = snes->numFailures;
1125: return(0);
1126: }
1130: /*@
1131: SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1132: attempted by the nonlinear solver before it gives up.
1134: Not Collective
1136: Input Parameters:
1137: + snes - SNES context
1138: - maxFails - maximum of unsuccessful steps
1140: Level: intermediate
1142: .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps
1144: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1145: SNESGetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
1146: @*/
1147: PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1148: {
1151: snes->maxFailures = maxFails;
1152: return(0);
1153: }
1157: /*@
1158: SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1159: attempted by the nonlinear solver before it gives up.
1161: Not Collective
1163: Input Parameter:
1164: . snes - SNES context
1166: Output Parameter:
1167: . maxFails - maximum of unsuccessful steps
1169: Level: intermediate
1171: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
1173: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1174: SNESSetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
1176: @*/
1177: PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1178: {
1182: *maxFails = snes->maxFailures;
1183: return(0);
1184: }
1188: /*@
1189: SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1190: done by SNES.
1192: Not Collective
1194: Input Parameter:
1195: . snes - SNES context
1197: Output Parameter:
1198: . nfuncs - number of evaluations
1200: Level: intermediate
1202: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
1204: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures()
1205: @*/
1206: PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1207: {
1211: *nfuncs = snes->nfuncs;
1212: return(0);
1213: }
1217: /*@
1218: SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1219: linear solvers.
1221: Not Collective
1223: Input Parameter:
1224: . snes - SNES context
1226: Output Parameter:
1227: . nfails - number of failed solves
1229: Notes:
1230: This counter is reset to zero for each successive call to SNESSolve().
1232: Level: intermediate
1234: .keywords: SNES, nonlinear, get, number, unsuccessful, steps
1236: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures()
1237: @*/
1238: PetscErrorCode SNESGetLinearSolveFailures(SNES snes,PetscInt *nfails)
1239: {
1243: *nfails = snes->numLinearSolveFailures;
1244: return(0);
1245: }
1249: /*@
1250: SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1251: allowed before SNES returns with a diverged reason of SNES_DIVERGED_LINEAR_SOLVE
1253: Logically Collective on SNES
1255: Input Parameters:
1256: + snes - SNES context
1257: - maxFails - maximum allowed linear solve failures
1259: Level: intermediate
1261: Notes: By default this is 0; that is SNES returns on the first failed linear solve
1263: .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps
1265: .seealso: SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations()
1266: @*/
1267: PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1268: {
1272: snes->maxLinearSolveFailures = maxFails;
1273: return(0);
1274: }
1278: /*@
1279: SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1280: are allowed before SNES terminates
1282: Not Collective
1284: Input Parameter:
1285: . snes - SNES context
1287: Output Parameter:
1288: . maxFails - maximum of unsuccessful solves allowed
1290: Level: intermediate
1292: Notes: By default this is 1; that is SNES returns on the first failed linear solve
1294: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
1296: .seealso: SNESGetLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(),
1297: @*/
1298: PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1299: {
1303: *maxFails = snes->maxLinearSolveFailures;
1304: return(0);
1305: }
1309: /*@
1310: SNESGetLinearSolveIterations - Gets the total number of linear iterations
1311: used by the nonlinear solver.
1313: Not Collective
1315: Input Parameter:
1316: . snes - SNES context
1318: Output Parameter:
1319: . lits - number of linear iterations
1321: Notes:
1322: This counter is reset to zero for each successive call to SNESSolve().
1324: Level: intermediate
1326: .keywords: SNES, nonlinear, get, number, linear, iterations
1328: .seealso: SNESGetIterationNumber(), SNESGetFunctionNorm(), SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures()
1329: @*/
1330: PetscErrorCode SNESGetLinearSolveIterations(SNES snes,PetscInt *lits)
1331: {
1335: *lits = snes->linear_its;
1336: return(0);
1337: }
1342: /*@
1343: SNESSetKSP - Sets a KSP context for the SNES object to use
1345: Not Collective, but the SNES and KSP objects must live on the same MPI_Comm
1347: Input Parameters:
1348: + snes - the SNES context
1349: - ksp - the KSP context
1351: Notes:
1352: The SNES object already has its KSP object, you can obtain with SNESGetKSP()
1353: so this routine is rarely needed.
1355: The KSP object that is already in the SNES object has its reference count
1356: decreased by one.
1358: Level: developer
1360: .keywords: SNES, nonlinear, get, KSP, context
1362: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
1363: @*/
1364: PetscErrorCode SNESSetKSP(SNES snes,KSP ksp)
1365: {
1372: PetscObjectReference((PetscObject)ksp);
1373: if (snes->ksp) {PetscObjectDereference((PetscObject)snes->ksp);}
1374: snes->ksp = ksp;
1375: return(0);
1376: }
1378: /* -----------------------------------------------------------*/
1381: /*@
1382: SNESCreate - Creates a nonlinear solver context.
1384: Collective on MPI_Comm
1386: Input Parameters:
1387: . comm - MPI communicator
1389: Output Parameter:
1390: . outsnes - the new SNES context
1392: Options Database Keys:
1393: + -snes_mf - Activates default matrix-free Jacobian-vector products,
1394: and no preconditioning matrix
1395: . -snes_mf_operator - Activates default matrix-free Jacobian-vector
1396: products, and a user-provided preconditioning matrix
1397: as set by SNESSetJacobian()
1398: - -snes_fd - Uses (slow!) finite differences to compute Jacobian
1400: Level: beginner
1402: .keywords: SNES, nonlinear, create, context
1404: .seealso: SNESSolve(), SNESDestroy(), SNES, SNESSetLagPreconditioner()
1406: @*/
1407: PetscErrorCode SNESCreate(MPI_Comm comm,SNES *outsnes)
1408: {
1410: SNES snes;
1411: SNESKSPEW *kctx;
1415: *outsnes = NULL;
1416: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
1417: SNESInitializePackage();
1418: #endif
1420: PetscHeaderCreate(snes,_p_SNES,struct _SNESOps,SNES_CLASSID,"SNES","Nonlinear solver","SNES",comm,SNESDestroy,SNESView);
1422: snes->ops->converged = SNESConvergedDefault;
1423: snes->usesksp = PETSC_TRUE;
1424: snes->tolerancesset = PETSC_FALSE;
1425: snes->max_its = 50;
1426: snes->max_funcs = 10000;
1427: snes->norm = 0.0;
1428: snes->normtype = SNES_NORM_FUNCTION;
1429: snes->rtol = 1.e-8;
1430: snes->ttol = 0.0;
1431: snes->abstol = 1.e-50;
1432: snes->stol = 1.e-8;
1433: snes->deltatol = 1.e-12;
1434: snes->nfuncs = 0;
1435: snes->numFailures = 0;
1436: snes->maxFailures = 1;
1437: snes->linear_its = 0;
1438: snes->lagjacobian = 1;
1439: snes->lagpreconditioner = 1;
1440: snes->numbermonitors = 0;
1441: snes->data = 0;
1442: snes->setupcalled = PETSC_FALSE;
1443: snes->ksp_ewconv = PETSC_FALSE;
1444: snes->nwork = 0;
1445: snes->work = 0;
1446: snes->nvwork = 0;
1447: snes->vwork = 0;
1448: snes->conv_hist_len = 0;
1449: snes->conv_hist_max = 0;
1450: snes->conv_hist = NULL;
1451: snes->conv_hist_its = NULL;
1452: snes->conv_hist_reset = PETSC_TRUE;
1453: snes->vec_func_init_set = PETSC_FALSE;
1454: snes->norm_init = 0.;
1455: snes->norm_init_set = PETSC_FALSE;
1456: snes->reason = SNES_CONVERGED_ITERATING;
1457: snes->pcside = PC_RIGHT;
1459: snes->mf = PETSC_FALSE;
1460: snes->mf_operator = PETSC_FALSE;
1461: snes->mf_version = 1;
1463: snes->numLinearSolveFailures = 0;
1464: snes->maxLinearSolveFailures = 1;
1466: /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
1467: PetscNewLog(snes,SNESKSPEW,&kctx);
1469: snes->kspconvctx = (void*)kctx;
1470: kctx->version = 2;
1471: kctx->rtol_0 = .3; /* Eisenstat and Walker suggest rtol_0=.5, but
1472: this was too large for some test cases */
1473: kctx->rtol_last = 0.0;
1474: kctx->rtol_max = .9;
1475: kctx->gamma = 1.0;
1476: kctx->alpha = .5*(1.0 + PetscSqrtReal(5.0));
1477: kctx->alpha2 = kctx->alpha;
1478: kctx->threshold = .1;
1479: kctx->lresid_last = 0.0;
1480: kctx->norm_last = 0.0;
1482: *outsnes = snes;
1483: return(0);
1484: }
1486: /*MC
1487: SNESFunction - functional form used to convey the nonlinear function to be solved by SNES
1489: Synopsis:
1490: #include "petscsnes.h"
1491: SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
1493: Input Parameters:
1494: + snes - the SNES context
1495: . x - state at which to evaluate residual
1496: - ctx - optional user-defined function context, passed in with SNESSetFunction()
1498: Output Parameter:
1499: . f - vector to put residual (function value)
1501: Level: intermediate
1503: .seealso: SNESSetFunction(), SNESGetFunction()
1504: M*/
1508: /*@C
1509: SNESSetFunction - Sets the function evaluation routine and function
1510: vector for use by the SNES routines in solving systems of nonlinear
1511: equations.
1513: Logically Collective on SNES
1515: Input Parameters:
1516: + snes - the SNES context
1517: . r - vector to store function value
1518: . SNESFunction - function evaluation routine
1519: - ctx - [optional] user-defined context for private data for the
1520: function evaluation routine (may be NULL)
1522: Notes:
1523: The Newton-like methods typically solve linear systems of the form
1524: $ f'(x) x = -f(x),
1525: where f'(x) denotes the Jacobian matrix and f(x) is the function.
1527: Level: beginner
1529: .keywords: SNES, nonlinear, set, function
1531: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetPicard(), SNESFunction
1532: @*/
1533: PetscErrorCode SNESSetFunction(SNES snes,Vec r,PetscErrorCode (*SNESFunction)(SNES,Vec,Vec,void*),void *ctx)
1534: {
1536: DM dm;
1540: if (r) {
1543: PetscObjectReference((PetscObject)r);
1544: VecDestroy(&snes->vec_func);
1546: snes->vec_func = r;
1547: }
1548: SNESGetDM(snes,&dm);
1549: DMSNESSetFunction(dm,SNESFunction,ctx);
1550: return(0);
1551: }
1556: /*@C
1557: SNESSetInitialFunction - Sets the function vector to be used as the
1558: function norm at the initialization of the method. In some
1559: instances, the user has precomputed the function before calling
1560: SNESSolve. This function allows one to avoid a redundant call
1561: to SNESComputeFunction in that case.
1563: Logically Collective on SNES
1565: Input Parameters:
1566: + snes - the SNES context
1567: - f - vector to store function value
1569: Notes:
1570: This should not be modified during the solution procedure.
1572: This is used extensively in the SNESFAS hierarchy and in nonlinear preconditioning.
1574: Level: developer
1576: .keywords: SNES, nonlinear, set, function
1578: .seealso: SNESSetFunction(), SNESComputeFunction(), SNESSetInitialFunctionNorm()
1579: @*/
1580: PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1581: {
1583: Vec vec_func;
1589: SNESGetFunction(snes,&vec_func,NULL,NULL);
1590: VecCopy(f, vec_func);
1592: snes->vec_func_init_set = PETSC_TRUE;
1593: return(0);
1594: }
1599: /*@C
1600: SNESSetInitialFunctionNorm - Sets the function norm to be used as the function norm
1601: at the initialization of the method. In some instances, the user has precomputed
1602: the function and its norm before calling SNESSolve. This function allows one to
1603: avoid a redundant call to SNESComputeFunction() and VecNorm() in that case.
1605: Logically Collective on SNES
1607: Input Parameters:
1608: + snes - the SNES context
1609: - fnorm - the norm of F as set by SNESSetInitialFunction()
1611: This is used extensively in the SNESFAS hierarchy and in nonlinear preconditioning.
1613: Level: developer
1615: .keywords: SNES, nonlinear, set, function, norm
1617: .seealso: SNESSetFunction(), SNESComputeFunction(), SNESSetInitialFunction()
1618: @*/
1619: PetscErrorCode SNESSetInitialFunctionNorm(SNES snes, PetscReal fnorm)
1620: {
1623: snes->norm_init = fnorm;
1624: snes->norm_init_set = PETSC_TRUE;
1625: return(0);
1626: }
1630: /*@
1631: SNESSetNormType - Sets the SNESNormType used in covergence and monitoring
1632: of the SNES method.
1634: Logically Collective on SNES
1636: Input Parameters:
1637: + snes - the SNES context
1638: - normtype - the type of the norm used
1640: Notes:
1641: Only certain SNES methods support certain SNESNormTypes. Most require evaluation
1642: of the nonlinear function and the taking of its norm at every iteration to
1643: even ensure convergence at all. However, methods such as custom Gauss-Seidel methods
1644: (SNESGS) and the like do not require the norm of the function to be computed, and therfore
1645: may either be monitored for convergence or not. As these are often used as nonlinear
1646: preconditioners, monitoring the norm of their error is not a useful enterprise within
1647: their solution.
1649: Level: developer
1651: .keywords: SNES, nonlinear, set, function, norm, type
1653: .seealso: SNESGetNormType(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormType
1654: @*/
1655: PetscErrorCode SNESSetNormType(SNES snes, SNESNormType normtype)
1656: {
1659: snes->normtype = normtype;
1660: return(0);
1661: }
1666: /*@
1667: SNESGetNormType - Gets the SNESNormType used in covergence and monitoring
1668: of the SNES method.
1670: Logically Collective on SNES
1672: Input Parameters:
1673: + snes - the SNES context
1674: - normtype - the type of the norm used
1676: Level: advanced
1678: .keywords: SNES, nonlinear, set, function, norm, type
1680: .seealso: SNESSetNormType(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormType
1681: @*/
1682: PetscErrorCode SNESGetNormType(SNES snes, SNESNormType *normtype)
1683: {
1686: *normtype = snes->normtype;
1687: return(0);
1688: }
1690: /*MC
1691: SNESGSFunction - function used to convey a Gauss-Seidel sweep on the nonlinear function
1693: Synopsis:
1694: #include "petscsnes.h"
1695: $ SNESGSFunction(SNES snes,Vec x,Vec b,void *ctx);
1697: + X - solution vector
1698: . B - RHS vector
1699: - ctx - optional user-defined Gauss-Seidel context
1701: Level: intermediate
1703: .seealso: SNESSetGS(), SNESGetGS()
1704: M*/
1708: /*@C
1709: SNESSetGS - Sets the user nonlinear Gauss-Seidel routine for
1710: use with composed nonlinear solvers.
1712: Input Parameters:
1713: + snes - the SNES context
1714: . SNESGSFunction - function evaluation routine
1715: - ctx - [optional] user-defined context for private data for the
1716: smoother evaluation routine (may be NULL)
1718: Notes:
1719: The GS routines are used by the composed nonlinear solver to generate
1720: a problem appropriate update to the solution, particularly FAS.
1722: Level: intermediate
1724: .keywords: SNES, nonlinear, set, Gauss-Seidel
1726: .seealso: SNESGetFunction(), SNESComputeGS()
1727: @*/
1728: PetscErrorCode SNESSetGS(SNES snes,PetscErrorCode (*SNESGSFunction)(SNES,Vec,Vec,void*),void *ctx)
1729: {
1731: DM dm;
1735: SNESGetDM(snes,&dm);
1736: DMSNESSetGS(dm,SNESGSFunction,ctx);
1737: return(0);
1738: }
1742: PETSC_EXTERN PetscErrorCode SNESPicardComputeFunction(SNES snes,Vec x,Vec f,void *ctx)
1743: {
1745: DM dm;
1746: DMSNES sdm;
1749: SNESGetDM(snes,&dm);
1750: DMGetDMSNES(dm,&sdm);
1751: /* A(x)*x - b(x) */
1752: if (sdm->ops->computepfunction) {
1753: (*sdm->ops->computepfunction)(snes,x,f,sdm->pctx);
1754: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetPicard() to provide Picard function.");
1756: if (sdm->ops->computepjacobian) {
1757: (*sdm->ops->computepjacobian)(snes,x,&snes->jacobian,&snes->jacobian_pre,&snes->matstruct,sdm->pctx);
1758: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetPicard() to provide Picard matrix.");
1759: VecScale(f,-1.0);
1760: MatMultAdd(snes->jacobian,x,f,f);
1761: return(0);
1762: }
1766: PETSC_EXTERN PetscErrorCode SNESPicardComputeJacobian(SNES snes,Vec x1,Mat *J,Mat *B,MatStructure *flag,void *ctx)
1767: {
1769: /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
1770: *flag = snes->matstruct;
1771: return(0);
1772: }
1776: /*@C
1777: SNESSetPicard - Use SNES to solve the semilinear-system A(x) x = b(x) via a Picard type iteration (Picard linearization)
1779: Logically Collective on SNES
1781: Input Parameters:
1782: + snes - the SNES context
1783: . r - vector to store function value
1784: . SNESFunction - function evaluation routine
1785: . Amat - matrix with which A(x) x - b(x) is to be computed
1786: . Pmat - matrix from which preconditioner is computed (usually the same as Amat)
1787: . SNESJacobianFunction - function to compute matrix value
1788: - ctx - [optional] user-defined context for private data for the
1789: function evaluation routine (may be NULL)
1791: Notes:
1792: We do not recomemend using this routine. It is far better to provide the nonlinear function F() and some approximation to the Jacobian and use
1793: 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.
1795: One can call SNESSetPicard() or SNESSetFunction() (and possibly SNESSetJacobian()) but cannot call both
1797: $ Solves the equation A(x) x = b(x) via the defect correction algorithm A(x^{n}) (x^{n+1} - x^{n}) = b(x^{n}) - A(x^{n})x^{n}
1798: $ Note that when an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = b(x^{n}) iteration.
1800: Run with -snes_mf_operator to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
1802: We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
1803: the direct Picard iteration A(x^n) x^{n+1} = b(x^n)
1805: 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
1806: 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
1807: different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
1809: Level: intermediate
1811: .keywords: SNES, nonlinear, set, function
1813: .seealso: SNESGetFunction(), SNESSetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESGetPicard(), SNESLineSearchPreCheckPicard()
1814: @*/
1815: PetscErrorCode SNESSetPicard(SNES snes,Vec r,PetscErrorCode (*SNESFunction)(SNES,Vec,Vec,void*),Mat Amat, Mat Pmat, PetscErrorCode (*SNESJacobianFunction)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
1816: {
1818: DM dm;
1822: SNESGetDM(snes, &dm);
1823: DMSNESSetPicard(dm,SNESFunction,SNESJacobianFunction,ctx);
1824: SNESSetFunction(snes,r,SNESPicardComputeFunction,ctx);
1825: SNESSetJacobian(snes,Amat,Pmat,SNESPicardComputeJacobian,ctx);
1826: return(0);
1827: }
1831: /*@C
1832: SNESGetPicard - Returns the context for the Picard iteration
1834: Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet.
1836: Input Parameter:
1837: . snes - the SNES context
1839: Output Parameter:
1840: + r - the function (or NULL)
1841: . SNESFunction - the function (or NULL)
1842: . Amat - the matrix used to defined the operation A(x) x - b(x) (or NULL)
1843: . Pmat - the matrix from which the preconditioner will be constructed (or NULL)
1844: . SNESJacobianFunction - the function for matrix evaluation (or NULL)
1845: - ctx - the function context (or NULL)
1847: Level: advanced
1849: .keywords: SNES, nonlinear, get, function
1851: .seealso: SNESSetPicard(), SNESGetFunction(), SNESGetJacobian(), SNESGetDM(), SNESFunction, SNESJacobianFunction
1852: @*/
1853: PetscErrorCode SNESGetPicard(SNES snes,Vec *r,PetscErrorCode (**SNESFunction)(SNES,Vec,Vec,void*),Mat *Amat, Mat *Pmat, PetscErrorCode (**SNESJacobianFunction)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
1854: {
1856: DM dm;
1860: SNESGetFunction(snes,r,NULL,NULL);
1861: SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);
1862: SNESGetDM(snes,&dm);
1863: DMSNESGetPicard(dm,SNESFunction,SNESJacobianFunction,ctx);
1864: return(0);
1865: }
1869: /*@C
1870: SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the problem
1872: Logically Collective on SNES
1874: Input Parameters:
1875: + snes - the SNES context
1876: . func - function evaluation routine
1877: - ctx - [optional] user-defined context for private data for the
1878: function evaluation routine (may be NULL)
1880: Calling sequence of func:
1881: $ func (SNES snes,Vec x,void *ctx);
1883: . f - function vector
1884: - ctx - optional user-defined function context
1886: Level: intermediate
1888: .keywords: SNES, nonlinear, set, function
1890: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian()
1891: @*/
1892: PetscErrorCode SNESSetComputeInitialGuess(SNES snes,PetscErrorCode (*func)(SNES,Vec,void*),void *ctx)
1893: {
1896: if (func) snes->ops->computeinitialguess = func;
1897: if (ctx) snes->initialguessP = ctx;
1898: return(0);
1899: }
1901: /* --------------------------------------------------------------- */
1904: /*@C
1905: SNESGetRhs - Gets the vector for solving F(x) = rhs. If rhs is not set
1906: it assumes a zero right hand side.
1908: Logically Collective on SNES
1910: Input Parameter:
1911: . snes - the SNES context
1913: Output Parameter:
1914: . rhs - the right hand side vector or NULL if the right hand side vector is null
1916: Level: intermediate
1918: .keywords: SNES, nonlinear, get, function, right hand side
1920: .seealso: SNESGetSolution(), SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
1921: @*/
1922: PetscErrorCode SNESGetRhs(SNES snes,Vec *rhs)
1923: {
1927: *rhs = snes->vec_rhs;
1928: return(0);
1929: }
1933: /*@
1934: SNESComputeFunction - Calls the function that has been set with SNESSetFunction().
1936: Collective on SNES
1938: Input Parameters:
1939: + snes - the SNES context
1940: - x - input vector
1942: Output Parameter:
1943: . y - function vector, as set by SNESSetFunction()
1945: Notes:
1946: SNESComputeFunction() is typically used within nonlinear solvers
1947: implementations, so most users would not generally call this routine
1948: themselves.
1950: Level: developer
1952: .keywords: SNES, nonlinear, compute, function
1954: .seealso: SNESSetFunction(), SNESGetFunction()
1955: @*/
1956: PetscErrorCode SNESComputeFunction(SNES snes,Vec x,Vec y)
1957: {
1959: DM dm;
1960: DMSNES sdm;
1968: VecValidValues(x,2,PETSC_TRUE);
1970: SNESGetDM(snes,&dm);
1971: DMGetDMSNES(dm,&sdm);
1972: if (snes->pc && snes->pcside == PC_LEFT) {
1973: VecCopy(x,y);
1974: PetscLogEventBegin(SNES_NPCSolve,snes->pc,x,y,0);
1975: SNESSolve(snes->pc,snes->vec_rhs,y);
1976: PetscLogEventEnd(SNES_NPCSolve,snes->pc,x,y,0);
1977: VecAYPX(y,-1.0,x);
1978: VecValidValues(y,3,PETSC_FALSE);
1979: return(0);
1980: } else if (sdm->ops->computefunction) {
1981: PetscLogEventBegin(SNES_FunctionEval,snes,x,y,0);
1982: PetscStackPush("SNES user function");
1983: (*sdm->ops->computefunction)(snes,x,y,sdm->functionctx);
1984: PetscStackPop;
1985: PetscLogEventEnd(SNES_FunctionEval,snes,x,y,0);
1986: } else if (snes->vec_rhs) {
1987: MatMult(snes->jacobian, x, y);
1988: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve().");
1989: if (snes->vec_rhs) {
1990: VecAXPY(y,-1.0,snes->vec_rhs);
1991: }
1992: snes->nfuncs++;
1993: VecValidValues(y,3,PETSC_FALSE);
1994: return(0);
1995: }
1999: /*@
2000: SNESComputeGS - Calls the Gauss-Seidel function that has been set with SNESSetGS().
2002: Collective on SNES
2004: Input Parameters:
2005: + snes - the SNES context
2006: . x - input vector
2007: - b - rhs vector
2009: Output Parameter:
2010: . x - new solution vector
2012: Notes:
2013: SNESComputeGS() is typically used within composed nonlinear solver
2014: implementations, so most users would not generally call this routine
2015: themselves.
2017: Level: developer
2019: .keywords: SNES, nonlinear, compute, function
2021: .seealso: SNESSetGS(), SNESComputeFunction()
2022: @*/
2023: PetscErrorCode SNESComputeGS(SNES snes,Vec b,Vec x)
2024: {
2026: DM dm;
2027: DMSNES sdm;
2035: if (b) {VecValidValues(b,2,PETSC_TRUE);}
2036: PetscLogEventBegin(SNES_GSEval,snes,x,b,0);
2037: SNESGetDM(snes,&dm);
2038: DMGetDMSNES(dm,&sdm);
2039: if (sdm->ops->computegs) {
2040: PetscStackPush("SNES user GS");
2041: (*sdm->ops->computegs)(snes,x,b,sdm->gsctx);
2042: PetscStackPop;
2043: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetGS() before SNESComputeGS(), likely called from SNESSolve().");
2044: PetscLogEventEnd(SNES_GSEval,snes,x,b,0);
2045: VecValidValues(x,3,PETSC_FALSE);
2046: return(0);
2047: }
2051: /*@
2052: SNESComputeJacobian - Computes the Jacobian matrix that has been set with SNESSetJacobian().
2054: Collective on SNES and Mat
2056: Input Parameters:
2057: + snes - the SNES context
2058: - x - input vector
2060: Output Parameters:
2061: + A - Jacobian matrix
2062: . B - optional preconditioning matrix
2063: - flag - flag indicating matrix structure (one of, SAME_NONZERO_PATTERN,DIFFERENT_NONZERO_PATTERN,SAME_PRECONDITIONER)
2065: Options Database Keys:
2066: + -snes_lag_preconditioner <lag>
2067: . -snes_lag_jacobian <lag>
2068: . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2069: . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2070: . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
2071: . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix
2072: . -snes_compare_coloring - Compute the finite differece Jacobian using coloring and display norms of difference
2073: . -snes_compare_coloring_display - Compute the finite differece Jacobian using coloring and display verbose differences
2074: . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold
2075: . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold
2076: . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold
2077: . -snes_compare_coloring_draw - Compute the finite differece Jacobian using coloring and draw differences
2078: - -snes_compare_coloring_draw_contour - Compute the finite differece Jacobian using coloring and show contours of matrices and differences
2081: Notes:
2082: Most users should not need to explicitly call this routine, as it
2083: is used internally within the nonlinear solvers.
2085: See KSPSetOperators() for important information about setting the
2086: flag parameter.
2088: Level: developer
2090: .keywords: SNES, compute, Jacobian, matrix
2092: .seealso: SNESSetJacobian(), KSPSetOperators(), MatStructure, SNESSetLagPreconditioner(), SNESSetLagJacobian()
2093: @*/
2094: PetscErrorCode SNESComputeJacobian(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *flg)
2095: {
2097: PetscBool flag;
2098: DM dm;
2099: DMSNES sdm;
2106: VecValidValues(X,2,PETSC_TRUE);
2107: SNESGetDM(snes,&dm);
2108: DMGetDMSNES(dm,&sdm);
2110: if (!sdm->ops->computejacobian) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_USER,"Must call SNESSetJacobian(), DMSNESSetJacobian(), DMDASNESSetJacobianLocal(), etc");
2112: /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
2114: if (snes->lagjacobian == -2) {
2115: snes->lagjacobian = -1;
2117: PetscInfo(snes,"Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n");
2118: } else if (snes->lagjacobian == -1) {
2119: *flg = SAME_PRECONDITIONER;
2120: PetscInfo(snes,"Reusing Jacobian/preconditioner because lag is -1\n");
2121: PetscObjectTypeCompare((PetscObject)*A,MATMFFD,&flag);
2122: if (flag) {
2123: MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
2124: MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
2125: }
2126: return(0);
2127: } else if (snes->lagjacobian > 1 && snes->iter % snes->lagjacobian) {
2128: *flg = SAME_PRECONDITIONER;
2129: PetscInfo2(snes,"Reusing Jacobian/preconditioner because lag is %D and SNES iteration is %D\n",snes->lagjacobian,snes->iter);
2130: PetscObjectTypeCompare((PetscObject)*A,MATMFFD,&flag);
2131: if (flag) {
2132: MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
2133: MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
2134: }
2135: return(0);
2136: }
2137: if (snes->pc && snes->pcside == PC_LEFT) {
2138: MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
2139: MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
2140: return(0);
2141: }
2143: *flg = DIFFERENT_NONZERO_PATTERN;
2144: PetscLogEventBegin(SNES_JacobianEval,snes,X,*A,*B);
2146: PetscStackPush("SNES user Jacobian function");
2147: (*sdm->ops->computejacobian)(snes,X,A,B,flg,sdm->jacobianctx);
2148: PetscStackPop;
2150: PetscLogEventEnd(SNES_JacobianEval,snes,X,*A,*B);
2152: if (snes->lagpreconditioner == -2) {
2153: PetscInfo(snes,"Rebuilding preconditioner exactly once since lag is -2\n");
2155: snes->lagpreconditioner = -1;
2156: } else if (snes->lagpreconditioner == -1) {
2157: *flg = SAME_PRECONDITIONER;
2158: PetscInfo(snes,"Reusing preconditioner because lag is -1\n");
2159: } else if (snes->lagpreconditioner > 1 && snes->iter % snes->lagpreconditioner) {
2160: *flg = SAME_PRECONDITIONER;
2161: PetscInfo2(snes,"Reusing preconditioner because lag is %D and SNES iteration is %D\n",snes->lagpreconditioner,snes->iter);
2162: }
2164: /* make sure user returned a correct Jacobian and preconditioner */
2167: {
2168: PetscBool flag = PETSC_FALSE,flag_draw = PETSC_FALSE,flag_contour = PETSC_FALSE,flag_operator = PETSC_FALSE;
2169: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_explicit",&flag,NULL);
2170: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_explicit_draw",&flag_draw,NULL);
2171: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_explicit_draw_contour",&flag_contour,NULL);
2172: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_operator",&flag_operator,NULL);
2173: if (flag || flag_draw || flag_contour) {
2174: Mat Bexp_mine = NULL,Bexp,FDexp;
2175: MatStructure mstruct;
2176: PetscViewer vdraw,vstdout;
2177: PetscBool flg;
2178: if (flag_operator) {
2179: MatComputeExplicitOperator(*A,&Bexp_mine);
2180: Bexp = Bexp_mine;
2181: } else {
2182: /* See if the preconditioning matrix can be viewed and added directly */
2183: PetscObjectTypeCompareAny((PetscObject)*B,&flg,MATSEQAIJ,MATMPIAIJ,MATSEQDENSE,MATMPIDENSE,MATSEQBAIJ,MATMPIBAIJ,MATSEQSBAIJ,MATMPIBAIJ,"");
2184: if (flg) Bexp = *B;
2185: else {
2186: /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
2187: MatComputeExplicitOperator(*B,&Bexp_mine);
2188: Bexp = Bexp_mine;
2189: }
2190: }
2191: MatConvert(Bexp,MATSAME,MAT_INITIAL_MATRIX,&FDexp);
2192: SNESComputeJacobianDefault(snes,X,&FDexp,&FDexp,&mstruct,NULL);
2193: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&vstdout);
2194: if (flag_draw || flag_contour) {
2195: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),0,"Explicit Jacobians",PETSC_DECIDE,PETSC_DECIDE,300,300,&vdraw);
2196: if (flag_contour) {PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);}
2197: } else vdraw = NULL;
2198: PetscViewerASCIIPrintf(vstdout,"Explicit %s\n",flag_operator ? "Jacobian" : "preconditioning Jacobian");
2199: if (flag) {MatView(Bexp,vstdout);}
2200: if (vdraw) {MatView(Bexp,vdraw);}
2201: PetscViewerASCIIPrintf(vstdout,"Finite difference Jacobian\n");
2202: if (flag) {MatView(FDexp,vstdout);}
2203: if (vdraw) {MatView(FDexp,vdraw);}
2204: MatAYPX(FDexp,-1.0,Bexp,SAME_NONZERO_PATTERN);
2205: PetscViewerASCIIPrintf(vstdout,"User-provided matrix minus finite difference Jacobian\n");
2206: if (flag) {MatView(FDexp,vstdout);}
2207: if (vdraw) { /* Always use contour for the difference */
2208: PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);
2209: MatView(FDexp,vdraw);
2210: PetscViewerPopFormat(vdraw);
2211: }
2212: if (flag_contour) {PetscViewerPopFormat(vdraw);}
2213: PetscViewerDestroy(&vdraw);
2214: MatDestroy(&Bexp_mine);
2215: MatDestroy(&FDexp);
2216: }
2217: }
2218: {
2219: PetscBool flag = PETSC_FALSE,flag_display = PETSC_FALSE,flag_draw = PETSC_FALSE,flag_contour = PETSC_FALSE,flag_threshold = PETSC_FALSE;
2220: PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON,threshold_rtol = 10*PETSC_SQRT_MACHINE_EPSILON;
2221: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_coloring",&flag,NULL);
2222: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_coloring_display",&flag_display,NULL);
2223: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_coloring_draw",&flag_draw,NULL);
2224: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_coloring_draw_contour",&flag_contour,NULL);
2225: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold",&flag_threshold,NULL);
2226: PetscOptionsGetReal(((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold_rtol",&threshold_rtol,NULL);
2227: PetscOptionsGetReal(((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold_atol",&threshold_atol,NULL);
2228: if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
2229: Mat Bfd;
2230: MatStructure mstruct;
2231: PetscViewer vdraw,vstdout;
2232: ISColoring iscoloring;
2233: MatFDColoring matfdcoloring;
2234: PetscErrorCode (*func)(SNES,Vec,Vec,void*);
2235: void *funcctx;
2236: PetscReal norm1,norm2,normmax;
2238: MatDuplicate(*B,MAT_DO_NOT_COPY_VALUES,&Bfd);
2239: MatGetColoring(Bfd,MATCOLORINGSL,&iscoloring);
2240: MatFDColoringCreate(Bfd,iscoloring,&matfdcoloring);
2241: ISColoringDestroy(&iscoloring);
2243: /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
2244: SNESGetFunction(snes,NULL,&func,&funcctx);
2245: MatFDColoringSetFunction(matfdcoloring,(PetscErrorCode (*)(void))func,funcctx);
2246: PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring,((PetscObject)snes)->prefix);
2247: PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring,"coloring_");
2248: MatFDColoringSetFromOptions(matfdcoloring);
2249: MatFDColoringApply(Bfd,matfdcoloring,X,&mstruct,snes);
2250: MatFDColoringDestroy(&matfdcoloring);
2252: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&vstdout);
2253: if (flag_draw || flag_contour) {
2254: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),0,"Colored Jacobians",PETSC_DECIDE,PETSC_DECIDE,300,300,&vdraw);
2255: if (flag_contour) {PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);}
2256: } else vdraw = NULL;
2257: PetscViewerASCIIPrintf(vstdout,"Explicit preconditioning Jacobian\n");
2258: if (flag_display) {MatView(*B,vstdout);}
2259: if (vdraw) {MatView(*B,vdraw);}
2260: PetscViewerASCIIPrintf(vstdout,"Colored Finite difference Jacobian\n");
2261: if (flag_display) {MatView(Bfd,vstdout);}
2262: if (vdraw) {MatView(Bfd,vdraw);}
2263: MatAYPX(Bfd,-1.0,*B,SAME_NONZERO_PATTERN);
2264: MatNorm(Bfd,NORM_1,&norm1);
2265: MatNorm(Bfd,NORM_FROBENIUS,&norm2);
2266: MatNorm(Bfd,NORM_MAX,&normmax);
2267: PetscViewerASCIIPrintf(vstdout,"User-provided matrix minus finite difference Jacobian, norm1=%G normFrob=%G normmax=%G\n",norm1,norm2,normmax);
2268: if (flag_display) {MatView(Bfd,vstdout);}
2269: if (vdraw) { /* Always use contour for the difference */
2270: PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);
2271: MatView(Bfd,vdraw);
2272: PetscViewerPopFormat(vdraw);
2273: }
2274: if (flag_contour) {PetscViewerPopFormat(vdraw);}
2276: if (flag_threshold) {
2277: PetscInt bs,rstart,rend,i;
2278: MatGetBlockSize(*B,&bs);
2279: MatGetOwnershipRange(*B,&rstart,&rend);
2280: for (i=rstart; i<rend; i++) {
2281: const PetscScalar *ba,*ca;
2282: const PetscInt *bj,*cj;
2283: PetscInt bn,cn,j,maxentrycol = -1,maxdiffcol = -1,maxrdiffcol = -1;
2284: PetscReal maxentry = 0,maxdiff = 0,maxrdiff = 0;
2285: MatGetRow(*B,i,&bn,&bj,&ba);
2286: MatGetRow(Bfd,i,&cn,&cj,&ca);
2287: if (bn != cn) SETERRQ(((PetscObject)*A)->comm,PETSC_ERR_PLIB,"Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
2288: for (j=0; j<bn; j++) {
2289: PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol*PetscAbsScalar(ba[j]));
2290: if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
2291: maxentrycol = bj[j];
2292: maxentry = PetscRealPart(ba[j]);
2293: }
2294: if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
2295: maxdiffcol = bj[j];
2296: maxdiff = PetscRealPart(ca[j]);
2297: }
2298: if (rdiff > maxrdiff) {
2299: maxrdiffcol = bj[j];
2300: maxrdiff = rdiff;
2301: }
2302: }
2303: if (maxrdiff > 1) {
2304: PetscViewerASCIIPrintf(vstdout,"row %D (maxentry=%G at %D, maxdiff=%G at %D, maxrdiff=%G at %D):",i,maxentry,maxentrycol,maxdiff,maxdiffcol,maxrdiff,maxrdiffcol);
2305: for (j=0; j<bn; j++) {
2306: PetscReal rdiff;
2307: rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol*PetscAbsScalar(ba[j]));
2308: if (rdiff > 1) {
2309: PetscViewerASCIIPrintf(vstdout," (%D,%G:%G)",bj[j],PetscRealPart(ba[j]),PetscRealPart(ca[j]));
2310: }
2311: }
2312: PetscViewerASCIIPrintf(vstdout,"\n",i,maxentry,maxdiff,maxrdiff);
2313: }
2314: MatRestoreRow(*B,i,&bn,&bj,&ba);
2315: MatRestoreRow(Bfd,i,&cn,&cj,&ca);
2316: }
2317: }
2318: PetscViewerDestroy(&vdraw);
2319: MatDestroy(&Bfd);
2320: }
2321: }
2322: return(0);
2323: }
2325: /*MC
2326: SNESJacobianFunction - function used to convey the nonlinear Jacobian of the function to be solved by SNES
2328: Synopsis:
2329: #include "petscsnes.h"
2330: $ SNESJacobianFunction(SNES snes,Vec x,Mat *Amat,Mat *Pmat,int *flag,void *ctx);
2332: + x - input vector
2333: . Amat - the matrix that defines the (approximate) Jacobian
2334: . Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
2335: . flag - flag indicating information about the preconditioner matrix
2336: structure (same as flag in KSPSetOperators()), one of SAME_NONZERO_PATTERN,DIFFERENT_NONZERO_PATTERN,SAME_PRECONDITIONER
2337: - ctx - [optional] user-defined Jacobian context
2339: Level: intermediate
2341: .seealso: SNESSetFunction(), SNESGetFunction(), SNESSetJacobian(), SNESGetJacobian()
2342: M*/
2346: /*@C
2347: SNESSetJacobian - Sets the function to compute Jacobian as well as the
2348: location to store the matrix.
2350: Logically Collective on SNES and Mat
2352: Input Parameters:
2353: + snes - the SNES context
2354: . Amat - the matrix that defines the (approximate) Jacobian
2355: . Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
2356: . SNESJacobianFunction - Jacobian evaluation routine (if NULL then SNES retains any previously set value)
2357: - ctx - [optional] user-defined context for private data for the
2358: Jacobian evaluation routine (may be NULL) (if NULL then SNES retains any previously set value)
2360: Notes:
2361: See KSPSetOperators() for important information about setting the flag
2362: output parameter in the routine func(). Be sure to read this information!
2364: The routine func() takes Mat * as the matrix arguments rather than Mat.
2365: This allows the Jacobian evaluation routine to replace A and/or B with a
2366: completely new new matrix structure (not just different matrix elements)
2367: when appropriate, for instance, if the nonzero structure is changing
2368: throughout the global iterations.
2370: If the Amat matrix and Pmat matrix are different you must call MatAssemblyBegin/End() on
2371: each matrix.
2373: If using SNESComputeJacobianDefaultColor() to assemble a Jacobian, the ctx argument
2374: must be a MatFDColoring.
2376: Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common
2377: example is to use the "Picard linearization" which only differentiates through the highest order parts of each term.
2379: Level: beginner
2381: .keywords: SNES, nonlinear, set, Jacobian, matrix
2383: .seealso: KSPSetOperators(), SNESSetFunction(), MatMFFDComputeJacobian(), SNESComputeJacobianDefaultColor(), MatStructure, SNESJacobianFunction, SNESSetPicard()
2384: @*/
2385: PetscErrorCode SNESSetJacobian(SNES snes,Mat Amat,Mat Pmat,PetscErrorCode (*SNESJacobianFunction)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
2386: {
2388: DM dm;
2396: SNESGetDM(snes,&dm);
2397: DMSNESSetJacobian(dm,SNESJacobianFunction,ctx);
2398: if (Amat) {
2399: PetscObjectReference((PetscObject)Amat);
2400: MatDestroy(&snes->jacobian);
2402: snes->jacobian = Amat;
2403: }
2404: if (Pmat) {
2405: PetscObjectReference((PetscObject)Pmat);
2406: MatDestroy(&snes->jacobian_pre);
2408: snes->jacobian_pre = Pmat;
2409: }
2410: return(0);
2411: }
2415: /*@C
2416: SNESGetJacobian - Returns the Jacobian matrix and optionally the user
2417: provided context for evaluating the Jacobian.
2419: Not Collective, but Mat object will be parallel if SNES object is
2421: Input Parameter:
2422: . snes - the nonlinear solver context
2424: Output Parameters:
2425: + Amat - location to stash (approximate) Jacobian matrix (or NULL)
2426: . Pmat - location to stash matrix used to compute the preconditioner (or NULL)
2427: . SNESJacobianFunction - location to put Jacobian function (or NULL)
2428: - ctx - location to stash Jacobian ctx (or NULL)
2430: Level: advanced
2432: .seealso: SNESSetJacobian(), SNESComputeJacobian()
2433: @*/
2434: PetscErrorCode SNESGetJacobian(SNES snes,Mat *Amat,Mat *Pmat,PetscErrorCode (**SNESJacobianFunction)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
2435: {
2437: DM dm;
2438: DMSNES sdm;
2442: if (Amat) *Amat = snes->jacobian;
2443: if (Pmat) *Pmat = snes->jacobian_pre;
2444: SNESGetDM(snes,&dm);
2445: DMGetDMSNES(dm,&sdm);
2446: if (SNESJacobianFunction) *SNESJacobianFunction = sdm->ops->computejacobian;
2447: if (ctx) *ctx = sdm->jacobianctx;
2448: return(0);
2449: }
2453: /*@
2454: SNESSetUp - Sets up the internal data structures for the later use
2455: of a nonlinear solver.
2457: Collective on SNES
2459: Input Parameters:
2460: . snes - the SNES context
2462: Notes:
2463: For basic use of the SNES solvers the user need not explicitly call
2464: SNESSetUp(), since these actions will automatically occur during
2465: the call to SNESSolve(). However, if one wishes to control this
2466: phase separately, SNESSetUp() should be called after SNESCreate()
2467: and optional routines of the form SNESSetXXX(), but before SNESSolve().
2469: Level: advanced
2471: .keywords: SNES, nonlinear, setup
2473: .seealso: SNESCreate(), SNESSolve(), SNESDestroy()
2474: @*/
2475: PetscErrorCode SNESSetUp(SNES snes)
2476: {
2478: DM dm;
2479: DMSNES sdm;
2480: SNESLineSearch linesearch, pclinesearch;
2481: void *lsprectx,*lspostctx;
2482: PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*);
2483: PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*);
2484: PetscErrorCode (*func)(SNES,Vec,Vec,void*);
2485: Vec f,fpc;
2486: void *funcctx;
2487: PetscErrorCode (*jac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
2488: void *jacctx,*appctx;
2489: Mat A,B;
2493: if (snes->setupcalled) return(0);
2495: if (!((PetscObject)snes)->type_name) {
2496: SNESSetType(snes,SNESNEWTONLS);
2497: }
2499: SNESGetFunction(snes,&snes->vec_func,NULL,NULL);
2500: if (snes->vec_func == snes->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"Solution vector cannot be function vector");
2501: if (snes->vec_rhs == snes->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"Solution vector cannot be right hand side vector");
2503: if (!snes->vec_sol_update /* && snes->vec_sol */) {
2504: VecDuplicate(snes->vec_sol,&snes->vec_sol_update);
2505: PetscLogObjectParent(snes,snes->vec_sol_update);
2506: }
2508: SNESGetDM(snes,&dm);
2509: DMShellSetGlobalVector(snes->dm,snes->vec_sol);
2510: DMGetDMSNES(dm,&sdm);
2511: if (!sdm->ops->computefunction) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Function never provided to SNES object");
2512: if (!sdm->ops->computejacobian) {
2513: DMSNESSetJacobian(dm,SNESComputeJacobianDefaultColor,NULL);
2514: }
2515: if (!snes->vec_func) {
2516: DMCreateGlobalVector(dm,&snes->vec_func);
2517: }
2519: if (!snes->ksp) {
2520: SNESGetKSP(snes, &snes->ksp);
2521: }
2523: if (!snes->linesearch) {
2524: SNESGetLineSearch(snes, &snes->linesearch);
2525: }
2527: if (snes->pc && (snes->pcside == PC_LEFT)) {
2528: snes->mf = PETSC_TRUE;
2529: snes->mf_operator = PETSC_FALSE;
2530: }
2532: if (snes->mf) {
2533: SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version);
2534: }
2536: if (snes->ops->usercompute && !snes->user) {
2537: (*snes->ops->usercompute)(snes,(void**)&snes->user);
2538: }
2540: if (snes->pc) {
2541: /* copy the DM over */
2542: SNESGetDM(snes,&dm);
2543: SNESSetDM(snes->pc,dm);
2545: SNESGetFunction(snes,&f,&func,&funcctx);
2546: VecDuplicate(f,&fpc);
2547: SNESSetFunction(snes->pc,fpc,func,funcctx);
2548: SNESGetJacobian(snes,&A,&B,&jac,&jacctx);
2549: SNESSetJacobian(snes->pc,A,B,jac,jacctx);
2550: SNESGetApplicationContext(snes,&appctx);
2551: SNESSetApplicationContext(snes->pc,appctx);
2552: VecDestroy(&fpc);
2554: /* copy the function pointers over */
2555: PetscObjectCopyFortranFunctionPointers((PetscObject)snes,(PetscObject)snes->pc);
2557: /* default to 1 iteration */
2558: SNESSetTolerances(snes->pc,0.0,0.0,0.0,1,snes->pc->max_funcs);
2559: if (snes->pcside==PC_RIGHT) {
2560: SNESSetNormType(snes->pc,SNES_NORM_FINAL_ONLY);
2561: } else {
2562: SNESSetNormType(snes->pc,SNES_NORM_NONE);
2563: }
2564: SNESSetFromOptions(snes->pc);
2566: /* copy the line search context over */
2567: SNESGetLineSearch(snes,&linesearch);
2568: SNESGetLineSearch(snes->pc,&pclinesearch);
2569: SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);
2570: SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);
2571: SNESLineSearchSetPreCheck(pclinesearch,precheck,lsprectx);
2572: SNESLineSearchSetPostCheck(pclinesearch,postcheck,lspostctx);
2573: PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch);
2574: }
2576: if (snes->ops->setup) {
2577: (*snes->ops->setup)(snes);
2578: }
2580: snes->setupcalled = PETSC_TRUE;
2581: return(0);
2582: }
2586: /*@
2587: SNESReset - Resets a SNES context to the snessetupcalled = 0 state and removes any allocated Vecs and Mats
2589: Collective on SNES
2591: Input Parameter:
2592: . snes - iterative context obtained from SNESCreate()
2594: Level: intermediate
2596: Notes: Also calls the application context destroy routine set with SNESSetComputeApplicationContext()
2598: .keywords: SNES, destroy
2600: .seealso: SNESCreate(), SNESSetUp(), SNESSolve()
2601: @*/
2602: PetscErrorCode SNESReset(SNES snes)
2603: {
2608: if (snes->ops->userdestroy && snes->user) {
2609: (*snes->ops->userdestroy)((void**)&snes->user);
2610: snes->user = NULL;
2611: }
2612: if (snes->pc) {
2613: SNESReset(snes->pc);
2614: }
2616: if (snes->ops->reset) {
2617: (*snes->ops->reset)(snes);
2618: }
2619: if (snes->ksp) {
2620: KSPReset(snes->ksp);
2621: }
2623: if (snes->linesearch) {
2624: SNESLineSearchReset(snes->linesearch);
2625: }
2627: VecDestroy(&snes->vec_rhs);
2628: VecDestroy(&snes->vec_sol);
2629: VecDestroy(&snes->vec_sol_update);
2630: VecDestroy(&snes->vec_func);
2631: MatDestroy(&snes->jacobian);
2632: MatDestroy(&snes->jacobian_pre);
2633: VecDestroyVecs(snes->nwork,&snes->work);
2634: VecDestroyVecs(snes->nvwork,&snes->vwork);
2636: snes->nwork = snes->nvwork = 0;
2637: snes->setupcalled = PETSC_FALSE;
2638: return(0);
2639: }
2643: /*@
2644: SNESDestroy - Destroys the nonlinear solver context that was created
2645: with SNESCreate().
2647: Collective on SNES
2649: Input Parameter:
2650: . snes - the SNES context
2652: Level: beginner
2654: .keywords: SNES, nonlinear, destroy
2656: .seealso: SNESCreate(), SNESSolve()
2657: @*/
2658: PetscErrorCode SNESDestroy(SNES *snes)
2659: {
2663: if (!*snes) return(0);
2665: if (--((PetscObject)(*snes))->refct > 0) {*snes = 0; return(0);}
2667: SNESReset((*snes));
2668: SNESDestroy(&(*snes)->pc);
2670: /* if memory was published with AMS then destroy it */
2671: PetscObjectAMSViewOff((PetscObject)*snes);
2672: if ((*snes)->ops->destroy) {(*((*snes))->ops->destroy)((*snes));}
2674: DMDestroy(&(*snes)->dm);
2675: KSPDestroy(&(*snes)->ksp);
2676: SNESLineSearchDestroy(&(*snes)->linesearch);
2678: PetscFree((*snes)->kspconvctx);
2679: if ((*snes)->ops->convergeddestroy) {
2680: (*(*snes)->ops->convergeddestroy)((*snes)->cnvP);
2681: }
2682: if ((*snes)->conv_malloc) {
2683: PetscFree((*snes)->conv_hist);
2684: PetscFree((*snes)->conv_hist_its);
2685: }
2686: SNESMonitorCancel((*snes));
2687: PetscHeaderDestroy(snes);
2688: return(0);
2689: }
2691: /* ----------- Routines to set solver parameters ---------- */
2695: /*@
2696: SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
2698: Logically Collective on SNES
2700: Input Parameters:
2701: + snes - the SNES context
2702: - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
2703: the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
2705: Options Database Keys:
2706: . -snes_lag_preconditioner <lag>
2708: Notes:
2709: The default is 1
2710: The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
2711: If -1 is used before the very first nonlinear solve the preconditioner is still built because there is no previous preconditioner to use
2713: Level: intermediate
2715: .keywords: SNES, nonlinear, set, convergence, tolerances
2717: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian()
2719: @*/
2720: PetscErrorCode SNESSetLagPreconditioner(SNES snes,PetscInt lag)
2721: {
2724: if (lag < -2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater");
2725: if (!lag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0");
2727: snes->lagpreconditioner = lag;
2728: return(0);
2729: }
2733: /*@
2734: SNESSetGridSequence - sets the number of steps of grid sequencing that SNES does
2736: Logically Collective on SNES
2738: Input Parameters:
2739: + snes - the SNES context
2740: - steps - the number of refinements to do, defaults to 0
2742: Options Database Keys:
2743: . -snes_grid_sequence <steps>
2745: Level: intermediate
2747: Notes:
2748: Use SNESGetSolution() to extract the fine grid solution after grid sequencing.
2750: .keywords: SNES, nonlinear, set, convergence, tolerances
2752: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian()
2754: @*/
2755: PetscErrorCode SNESSetGridSequence(SNES snes,PetscInt steps)
2756: {
2760: snes->gridsequence = steps;
2761: return(0);
2762: }
2766: /*@
2767: SNESGetLagPreconditioner - Indicates how often the preconditioner is rebuilt
2769: Not Collective
2771: Input Parameter:
2772: . snes - the SNES context
2774: Output Parameter:
2775: . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
2776: the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
2778: Options Database Keys:
2779: . -snes_lag_preconditioner <lag>
2781: Notes:
2782: The default is 1
2783: The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
2785: Level: intermediate
2787: .keywords: SNES, nonlinear, set, convergence, tolerances
2789: .seealso: SNESSetTrustRegionTolerance(), SNESSetLagPreconditioner()
2791: @*/
2792: PetscErrorCode SNESGetLagPreconditioner(SNES snes,PetscInt *lag)
2793: {
2796: *lag = snes->lagpreconditioner;
2797: return(0);
2798: }
2802: /*@
2803: SNESSetLagJacobian - Determines when the Jacobian is rebuilt in the nonlinear solve. See SNESSetLagPreconditioner() for determining how
2804: often the preconditioner is rebuilt.
2806: Logically Collective on SNES
2808: Input Parameters:
2809: + snes - the SNES context
2810: - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
2811: the Jacobian is built etc. -2 means rebuild at next chance but then never again
2813: Options Database Keys:
2814: . -snes_lag_jacobian <lag>
2816: Notes:
2817: The default is 1
2818: The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
2819: 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
2820: at the next Newton step but never again (unless it is reset to another value)
2822: Level: intermediate
2824: .keywords: SNES, nonlinear, set, convergence, tolerances
2826: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagPreconditioner(), SNESGetLagJacobian()
2828: @*/
2829: PetscErrorCode SNESSetLagJacobian(SNES snes,PetscInt lag)
2830: {
2833: if (lag < -2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater");
2834: if (!lag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0");
2836: snes->lagjacobian = lag;
2837: return(0);
2838: }
2842: /*@
2843: SNESGetLagJacobian - Indicates how often the Jacobian is rebuilt. See SNESGetLagPreconditioner() to determine when the preconditioner is rebuilt
2845: Not Collective
2847: Input Parameter:
2848: . snes - the SNES context
2850: Output Parameter:
2851: . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
2852: the Jacobian is built etc.
2854: Options Database Keys:
2855: . -snes_lag_jacobian <lag>
2857: Notes:
2858: The default is 1
2859: The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
2861: Level: intermediate
2863: .keywords: SNES, nonlinear, set, convergence, tolerances
2865: .seealso: SNESSetTrustRegionTolerance(), SNESSetLagJacobian(), SNESSetLagPreconditioner(), SNESGetLagPreconditioner()
2867: @*/
2868: PetscErrorCode SNESGetLagJacobian(SNES snes,PetscInt *lag)
2869: {
2872: *lag = snes->lagjacobian;
2873: return(0);
2874: }
2878: /*@
2879: SNESSetTolerances - Sets various parameters used in convergence tests.
2881: Logically Collective on SNES
2883: Input Parameters:
2884: + snes - the SNES context
2885: . abstol - absolute convergence tolerance
2886: . rtol - relative convergence tolerance
2887: . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x ||
2888: . maxit - maximum number of iterations
2889: - maxf - maximum number of function evaluations
2891: Options Database Keys:
2892: + -snes_atol <abstol> - Sets abstol
2893: . -snes_rtol <rtol> - Sets rtol
2894: . -snes_stol <stol> - Sets stol
2895: . -snes_max_it <maxit> - Sets maxit
2896: - -snes_max_funcs <maxf> - Sets maxf
2898: Notes:
2899: The default maximum number of iterations is 50.
2900: The default maximum number of function evaluations is 1000.
2902: Level: intermediate
2904: .keywords: SNES, nonlinear, set, convergence, tolerances
2906: .seealso: SNESSetTrustRegionTolerance()
2907: @*/
2908: PetscErrorCode SNESSetTolerances(SNES snes,PetscReal abstol,PetscReal rtol,PetscReal stol,PetscInt maxit,PetscInt maxf)
2909: {
2918: if (abstol != PETSC_DEFAULT) {
2919: if (abstol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %G must be non-negative",abstol);
2920: snes->abstol = abstol;
2921: }
2922: if (rtol != PETSC_DEFAULT) {
2923: if (rtol < 0.0 || 1.0 <= rtol) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Relative tolerance %G must be non-negative and less than 1.0",rtol);
2924: snes->rtol = rtol;
2925: }
2926: if (stol != PETSC_DEFAULT) {
2927: if (stol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Step tolerance %G must be non-negative",stol);
2928: snes->stol = stol;
2929: }
2930: if (maxit != PETSC_DEFAULT) {
2931: if (maxit < 0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",maxit);
2932: snes->max_its = maxit;
2933: }
2934: if (maxf != PETSC_DEFAULT) {
2935: if (maxf < 0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of function evaluations %D must be non-negative",maxf);
2936: snes->max_funcs = maxf;
2937: }
2938: snes->tolerancesset = PETSC_TRUE;
2939: return(0);
2940: }
2944: /*@
2945: SNESGetTolerances - Gets various parameters used in convergence tests.
2947: Not Collective
2949: Input Parameters:
2950: + snes - the SNES context
2951: . atol - absolute convergence tolerance
2952: . rtol - relative convergence tolerance
2953: . stol - convergence tolerance in terms of the norm
2954: of the change in the solution between steps
2955: . maxit - maximum number of iterations
2956: - maxf - maximum number of function evaluations
2958: Notes:
2959: The user can specify NULL for any parameter that is not needed.
2961: Level: intermediate
2963: .keywords: SNES, nonlinear, get, convergence, tolerances
2965: .seealso: SNESSetTolerances()
2966: @*/
2967: PetscErrorCode SNESGetTolerances(SNES snes,PetscReal *atol,PetscReal *rtol,PetscReal *stol,PetscInt *maxit,PetscInt *maxf)
2968: {
2971: if (atol) *atol = snes->abstol;
2972: if (rtol) *rtol = snes->rtol;
2973: if (stol) *stol = snes->stol;
2974: if (maxit) *maxit = snes->max_its;
2975: if (maxf) *maxf = snes->max_funcs;
2976: return(0);
2977: }
2981: /*@
2982: SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
2984: Logically Collective on SNES
2986: Input Parameters:
2987: + snes - the SNES context
2988: - tol - tolerance
2990: Options Database Key:
2991: . -snes_trtol <tol> - Sets tol
2993: Level: intermediate
2995: .keywords: SNES, nonlinear, set, trust region, tolerance
2997: .seealso: SNESSetTolerances()
2998: @*/
2999: PetscErrorCode SNESSetTrustRegionTolerance(SNES snes,PetscReal tol)
3000: {
3004: snes->deltatol = tol;
3005: return(0);
3006: }
3008: /*
3009: Duplicate the lg monitors for SNES from KSP; for some reason with
3010: dynamic libraries things don't work under Sun4 if we just use
3011: macros instead of functions
3012: */
3015: PetscErrorCode SNESMonitorLGResidualNorm(SNES snes,PetscInt it,PetscReal norm,void *ctx)
3016: {
3021: KSPMonitorLGResidualNorm((KSP)snes,it,norm,ctx);
3022: return(0);
3023: }
3027: PetscErrorCode SNESMonitorLGCreate(const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *draw)
3028: {
3032: KSPMonitorLGResidualNormCreate(host,label,x,y,m,n,draw);
3033: return(0);
3034: }
3038: PetscErrorCode SNESMonitorLGDestroy(PetscDrawLG *draw)
3039: {
3043: KSPMonitorLGResidualNormDestroy(draw);
3044: return(0);
3045: }
3047: extern PetscErrorCode SNESMonitorRange_Private(SNES,PetscInt,PetscReal*);
3050: PetscErrorCode SNESMonitorLGRange(SNES snes,PetscInt n,PetscReal rnorm,void *monctx)
3051: {
3052: PetscDrawLG lg;
3053: PetscErrorCode ierr;
3054: PetscReal x,y,per;
3055: PetscViewer v = (PetscViewer)monctx;
3056: static PetscReal prev; /* should be in the context */
3057: PetscDraw draw;
3060: PetscViewerDrawGetDrawLG(v,0,&lg);
3061: if (!n) {PetscDrawLGReset(lg);}
3062: PetscDrawLGGetDraw(lg,&draw);
3063: PetscDrawSetTitle(draw,"Residual norm");
3064: x = (PetscReal)n;
3065: if (rnorm > 0.0) y = log10(rnorm);
3066: else y = -15.0;
3067: PetscDrawLGAddPoint(lg,&x,&y);
3068: if (n < 20 || !(n % 5)) {
3069: PetscDrawLGDraw(lg);
3070: }
3072: PetscViewerDrawGetDrawLG(v,1,&lg);
3073: if (!n) {PetscDrawLGReset(lg);}
3074: PetscDrawLGGetDraw(lg,&draw);
3075: PetscDrawSetTitle(draw,"% elemts > .2*max elemt");
3076: SNESMonitorRange_Private(snes,n,&per);
3077: x = (PetscReal)n;
3078: y = 100.0*per;
3079: PetscDrawLGAddPoint(lg,&x,&y);
3080: if (n < 20 || !(n % 5)) {
3081: PetscDrawLGDraw(lg);
3082: }
3084: PetscViewerDrawGetDrawLG(v,2,&lg);
3085: if (!n) {prev = rnorm;PetscDrawLGReset(lg);}
3086: PetscDrawLGGetDraw(lg,&draw);
3087: PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm");
3088: x = (PetscReal)n;
3089: y = (prev - rnorm)/prev;
3090: PetscDrawLGAddPoint(lg,&x,&y);
3091: if (n < 20 || !(n % 5)) {
3092: PetscDrawLGDraw(lg);
3093: }
3095: PetscViewerDrawGetDrawLG(v,3,&lg);
3096: if (!n) {PetscDrawLGReset(lg);}
3097: PetscDrawLGGetDraw(lg,&draw);
3098: PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm*(% > .2 max)");
3099: x = (PetscReal)n;
3100: y = (prev - rnorm)/(prev*per);
3101: if (n > 2) { /*skip initial crazy value */
3102: PetscDrawLGAddPoint(lg,&x,&y);
3103: }
3104: if (n < 20 || !(n % 5)) {
3105: PetscDrawLGDraw(lg);
3106: }
3107: prev = rnorm;
3108: return(0);
3109: }
3113: /*@
3114: SNESMonitor - runs the user provided monitor routines, if they exist
3116: Collective on SNES
3118: Input Parameters:
3119: + snes - nonlinear solver context obtained from SNESCreate()
3120: . iter - iteration number
3121: - rnorm - relative norm of the residual
3123: Notes:
3124: This routine is called by the SNES implementations.
3125: It does not typically need to be called by the user.
3127: Level: developer
3129: .seealso: SNESMonitorSet()
3130: @*/
3131: PetscErrorCode SNESMonitor(SNES snes,PetscInt iter,PetscReal rnorm)
3132: {
3134: PetscInt i,n = snes->numbermonitors;
3137: for (i=0; i<n; i++) {
3138: (*snes->monitor[i])(snes,iter,rnorm,snes->monitorcontext[i]);
3139: }
3140: return(0);
3141: }
3143: /* ------------ Routines to set performance monitoring options ----------- */
3145: /*MC
3146: SNESMonitorFunction - functional form passed to SNESMonitorSet() to monitor convergence of nonlinear solver
3148: Synopsis:
3149: #include "petscsnes.h"
3150: $ PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx)
3152: + snes - the SNES context
3153: . its - iteration number
3154: . norm - 2-norm function value (may be estimated)
3155: - mctx - [optional] monitoring context
3157: Level: advanced
3159: .seealso: SNESMonitorSet(), SNESMonitorGet()
3160: M*/
3164: /*@C
3165: SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
3166: iteration of the nonlinear solver to display the iteration's
3167: progress.
3169: Logically Collective on SNES
3171: Input Parameters:
3172: + snes - the SNES context
3173: . SNESMonitorFunction - monitoring routine
3174: . mctx - [optional] user-defined context for private data for the
3175: monitor routine (use NULL if no context is desired)
3176: - monitordestroy - [optional] routine that frees monitor context
3177: (may be NULL)
3179: Options Database Keys:
3180: + -snes_monitor - sets SNESMonitorDefault()
3181: . -snes_monitor_lg_residualnorm - sets line graph monitor,
3182: uses SNESMonitorLGCreate()
3183: - -snes_monitor_cancel - cancels all monitors that have
3184: been hardwired into a code by
3185: calls to SNESMonitorSet(), but
3186: does not cancel those set via
3187: the options database.
3189: Notes:
3190: Several different monitoring routines may be set by calling
3191: SNESMonitorSet() multiple times; all will be called in the
3192: order in which they were set.
3194: Fortran notes: Only a single monitor function can be set for each SNES object
3196: Level: intermediate
3198: .keywords: SNES, nonlinear, set, monitor
3200: .seealso: SNESMonitorDefault(), SNESMonitorCancel(), SNESMonitorFunction
3201: @*/
3202: PetscErrorCode SNESMonitorSet(SNES snes,PetscErrorCode (*SNESMonitorFunction)(SNES,PetscInt,PetscReal,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
3203: {
3204: PetscInt i;
3209: if (snes->numbermonitors >= MAXSNESMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
3210: for (i=0; i<snes->numbermonitors;i++) {
3211: if (SNESMonitorFunction == snes->monitor[i] && monitordestroy == snes->monitordestroy[i] && mctx == snes->monitorcontext[i]) {
3212: if (monitordestroy) {
3213: (*monitordestroy)(&mctx);
3214: }
3215: return(0);
3216: }
3217: }
3218: snes->monitor[snes->numbermonitors] = SNESMonitorFunction;
3219: snes->monitordestroy[snes->numbermonitors] = monitordestroy;
3220: snes->monitorcontext[snes->numbermonitors++] = (void*)mctx;
3221: return(0);
3222: }
3226: /*@C
3227: SNESMonitorCancel - Clears all the monitor functions for a SNES object.
3229: Logically Collective on SNES
3231: Input Parameters:
3232: . snes - the SNES context
3234: Options Database Key:
3235: . -snes_monitor_cancel - cancels all monitors that have been hardwired
3236: into a code by calls to SNESMonitorSet(), but does not cancel those
3237: set via the options database
3239: Notes:
3240: There is no way to clear one specific monitor from a SNES object.
3242: Level: intermediate
3244: .keywords: SNES, nonlinear, set, monitor
3246: .seealso: SNESMonitorDefault(), SNESMonitorSet()
3247: @*/
3248: PetscErrorCode SNESMonitorCancel(SNES snes)
3249: {
3251: PetscInt i;
3255: for (i=0; i<snes->numbermonitors; i++) {
3256: if (snes->monitordestroy[i]) {
3257: (*snes->monitordestroy[i])(&snes->monitorcontext[i]);
3258: }
3259: }
3260: snes->numbermonitors = 0;
3261: return(0);
3262: }
3264: /*MC
3265: SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
3267: Synopsis:
3268: #include "petscsnes.h"
3269: $ PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx)
3271: + snes - the SNES context
3272: . it - current iteration (0 is the first and is before any Newton step)
3273: . cctx - [optional] convergence context
3274: . reason - reason for convergence/divergence
3275: . xnorm - 2-norm of current iterate
3276: . gnorm - 2-norm of current step
3277: - f - 2-norm of function
3279: Level: intermediate
3281: .seealso: SNESSetConvergenceTest(), SNESGetConvergenceTest()
3282: M*/
3286: /*@C
3287: SNESSetConvergenceTest - Sets the function that is to be used
3288: to test for convergence of the nonlinear iterative solution.
3290: Logically Collective on SNES
3292: Input Parameters:
3293: + snes - the SNES context
3294: . SNESConvergenceTestFunction - routine to test for convergence
3295: . cctx - [optional] context for private data for the convergence routine (may be NULL)
3296: - destroy - [optional] destructor for the context (may be NULL; NULL_FUNCTION in Fortran)
3298: Level: advanced
3300: .keywords: SNES, nonlinear, set, convergence, test
3302: .seealso: SNESConvergedDefault(), SNESSkipConverged(), SNESConvergenceTestFunction
3303: @*/
3304: PetscErrorCode SNESSetConvergenceTest(SNES snes,PetscErrorCode (*SNESConvergenceTestFunction)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void *cctx,PetscErrorCode (*destroy)(void*))
3305: {
3310: if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESSkipConverged;
3311: if (snes->ops->convergeddestroy) {
3312: (*snes->ops->convergeddestroy)(snes->cnvP);
3313: }
3314: snes->ops->converged = SNESConvergenceTestFunction;
3315: snes->ops->convergeddestroy = destroy;
3316: snes->cnvP = cctx;
3317: return(0);
3318: }
3322: /*@
3323: SNESGetConvergedReason - Gets the reason the SNES iteration was stopped.
3325: Not Collective
3327: Input Parameter:
3328: . snes - the SNES context
3330: Output Parameter:
3331: . reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the
3332: manual pages for the individual convergence tests for complete lists
3334: Level: intermediate
3336: Notes: Can only be called after the call the SNESSolve() is complete.
3338: .keywords: SNES, nonlinear, set, convergence, test
3340: .seealso: SNESSetConvergenceTest(), SNESConvergedReason
3341: @*/
3342: PetscErrorCode SNESGetConvergedReason(SNES snes,SNESConvergedReason *reason)
3343: {
3347: *reason = snes->reason;
3348: return(0);
3349: }
3353: /*@
3354: SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
3356: Logically Collective on SNES
3358: Input Parameters:
3359: + snes - iterative context obtained from SNESCreate()
3360: . a - array to hold history, this array will contain the function norms computed at each step
3361: . its - integer array holds the number of linear iterations for each solve.
3362: . na - size of a and its
3363: - reset - PETSC_TRUE indicates each new nonlinear solve resets the history counter to zero,
3364: else it continues storing new values for new nonlinear solves after the old ones
3366: Notes:
3367: If 'a' and 'its' are NULL then space is allocated for the history. If 'na' PETSC_DECIDE or PETSC_DEFAULT then a
3368: default array of length 10000 is allocated.
3370: This routine is useful, e.g., when running a code for purposes
3371: of accurate performance monitoring, when no I/O should be done
3372: during the section of code that is being timed.
3374: Level: intermediate
3376: .keywords: SNES, set, convergence, history
3378: .seealso: SNESGetConvergenceHistory()
3380: @*/
3381: PetscErrorCode SNESSetConvergenceHistory(SNES snes,PetscReal a[],PetscInt its[],PetscInt na,PetscBool reset)
3382: {
3389: if (!a) {
3390: if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
3391: PetscMalloc(na*sizeof(PetscReal),&a);
3392: PetscMalloc(na*sizeof(PetscInt),&its);
3394: snes->conv_malloc = PETSC_TRUE;
3395: }
3396: snes->conv_hist = a;
3397: snes->conv_hist_its = its;
3398: snes->conv_hist_max = na;
3399: snes->conv_hist_len = 0;
3400: snes->conv_hist_reset = reset;
3401: return(0);
3402: }
3404: #if defined(PETSC_HAVE_MATLAB_ENGINE)
3405: #include <engine.h> /* MATLAB include file */
3406: #include <mex.h> /* MATLAB include file */
3410: PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
3411: {
3412: mxArray *mat;
3413: PetscInt i;
3414: PetscReal *ar;
3417: mat = mxCreateDoubleMatrix(snes->conv_hist_len,1,mxREAL);
3418: ar = (PetscReal*) mxGetData(mat);
3419: for (i=0; i<snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
3420: PetscFunctionReturn(mat);
3421: }
3422: #endif
3426: /*@C
3427: SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
3429: Not Collective
3431: Input Parameter:
3432: . snes - iterative context obtained from SNESCreate()
3434: Output Parameters:
3435: . a - array to hold history
3436: . its - integer array holds the number of linear iterations (or
3437: negative if not converged) for each solve.
3438: - na - size of a and its
3440: Notes:
3441: The calling sequence for this routine in Fortran is
3442: $ call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
3444: This routine is useful, e.g., when running a code for purposes
3445: of accurate performance monitoring, when no I/O should be done
3446: during the section of code that is being timed.
3448: Level: intermediate
3450: .keywords: SNES, get, convergence, history
3452: .seealso: SNESSetConvergencHistory()
3454: @*/
3455: PetscErrorCode SNESGetConvergenceHistory(SNES snes,PetscReal *a[],PetscInt *its[],PetscInt *na)
3456: {
3459: if (a) *a = snes->conv_hist;
3460: if (its) *its = snes->conv_hist_its;
3461: if (na) *na = snes->conv_hist_len;
3462: return(0);
3463: }
3467: /*@C
3468: SNESSetUpdate - Sets the general-purpose update function called
3469: at the beginning of every iteration of the nonlinear solve. Specifically
3470: it is called just before the Jacobian is "evaluated".
3472: Logically Collective on SNES
3474: Input Parameters:
3475: . snes - The nonlinear solver context
3476: . func - The function
3478: Calling sequence of func:
3479: . func (SNES snes, PetscInt step);
3481: . step - The current step of the iteration
3483: Level: advanced
3485: Note: This is NOT what one uses to update the ghost points before a function evaluation, that should be done at the beginning of your FormFunction()
3486: This is not used by most users.
3488: .keywords: SNES, update
3490: .seealso SNESSetJacobian(), SNESSolve()
3491: @*/
3492: PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
3493: {
3496: snes->ops->update = func;
3497: return(0);
3498: }
3502: /*
3503: SNESScaleStep_Private - Scales a step so that its length is less than the
3504: positive parameter delta.
3506: Input Parameters:
3507: + snes - the SNES context
3508: . y - approximate solution of linear system
3509: . fnorm - 2-norm of current function
3510: - delta - trust region size
3512: Output Parameters:
3513: + gpnorm - predicted function norm at the new point, assuming local
3514: linearization. The value is zero if the step lies within the trust
3515: region, and exceeds zero otherwise.
3516: - ynorm - 2-norm of the step
3518: Note:
3519: For non-trust region methods such as SNESNEWTONLS, the parameter delta
3520: is set to be the maximum allowable step size.
3522: .keywords: SNES, nonlinear, scale, step
3523: */
3524: PetscErrorCode SNESScaleStep_Private(SNES snes,Vec y,PetscReal *fnorm,PetscReal *delta,PetscReal *gpnorm,PetscReal *ynorm)
3525: {
3526: PetscReal nrm;
3527: PetscScalar cnorm;
3535: VecNorm(y,NORM_2,&nrm);
3536: if (nrm > *delta) {
3537: nrm = *delta/nrm;
3538: *gpnorm = (1.0 - nrm)*(*fnorm);
3539: cnorm = nrm;
3540: VecScale(y,cnorm);
3541: *ynorm = *delta;
3542: } else {
3543: *gpnorm = 0.0;
3544: *ynorm = nrm;
3545: }
3546: return(0);
3547: }
3551: /*@C
3552: SNESSolve - Solves a nonlinear system F(x) = b.
3553: Call SNESSolve() after calling SNESCreate() and optional routines of the form SNESSetXXX().
3555: Collective on SNES
3557: Input Parameters:
3558: + snes - the SNES context
3559: . b - the constant part of the equation F(x) = b, or NULL to use zero.
3560: - x - the solution vector.
3562: Notes:
3563: The user should initialize the vector,x, with the initial guess
3564: for the nonlinear solve prior to calling SNESSolve. In particular,
3565: to employ an initial guess of zero, the user should explicitly set
3566: this vector to zero by calling VecSet().
3568: Level: beginner
3570: .keywords: SNES, nonlinear, solve
3572: .seealso: SNESCreate(), SNESDestroy(), SNESSetFunction(), SNESSetJacobian(), SNESSetGridSequence(), SNESGetSolution()
3573: @*/
3574: PetscErrorCode SNESSolve(SNES snes,Vec b,Vec x)
3575: {
3576: PetscErrorCode ierr;
3577: PetscBool flg;
3578: PetscViewer viewer;
3579: PetscInt grid;
3580: Vec xcreated = NULL;
3581: DM dm;
3582: PetscViewerFormat format;
3591: if (!x) {
3592: SNESGetDM(snes,&dm);
3593: DMCreateGlobalVector(dm,&xcreated);
3594: x = xcreated;
3595: }
3597: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_view_pre",&viewer,&format,&flg);
3598: if (flg && !PetscPreLoadingOn) {
3599: PetscViewerPushFormat(viewer,format);
3600: SNESView(snes,viewer);
3601: PetscViewerPopFormat(viewer);
3602: PetscViewerDestroy(&viewer);
3603: }
3605: for (grid=0; grid<snes->gridsequence; grid++) {PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));}
3606: for (grid=0; grid<snes->gridsequence+1; grid++) {
3608: /* set solution vector */
3609: if (!grid) {PetscObjectReference((PetscObject)x);}
3610: VecDestroy(&snes->vec_sol);
3611: snes->vec_sol = x;
3612: SNESGetDM(snes,&dm);
3614: /* set affine vector if provided */
3615: if (b) { PetscObjectReference((PetscObject)b); }
3616: VecDestroy(&snes->vec_rhs);
3617: snes->vec_rhs = b;
3619: SNESSetUp(snes);
3621: if (!grid) {
3622: if (snes->ops->computeinitialguess) {
3623: (*snes->ops->computeinitialguess)(snes,snes->vec_sol,snes->initialguessP);
3624: }
3625: }
3627: if (snes->conv_hist_reset) snes->conv_hist_len = 0;
3628: snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;
3630: PetscLogEventBegin(SNES_Solve,snes,0,0,0);
3631: (*snes->ops->solve)(snes);
3632: PetscLogEventEnd(SNES_Solve,snes,0,0,0);
3633: if (snes->domainerror) {
3634: snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
3635: snes->domainerror = PETSC_FALSE;
3636: }
3637: if (!snes->reason) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");
3639: flg = PETSC_FALSE;
3640: PetscOptionsGetBool(((PetscObject)snes)->prefix,"-snes_test_local_min",&flg,NULL);
3641: if (flg && !PetscPreLoadingOn) { SNESTestLocalMin(snes); }
3642: if (snes->printreason) {
3643: PetscViewerASCIIAddTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)),((PetscObject)snes)->tablevel);
3644: if (snes->reason > 0) {
3645: PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)),"Nonlinear solve converged due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);
3646: } else {
3647: PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)),"Nonlinear solve did not converge due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);
3648: }
3649: PetscViewerASCIISubtractTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)),((PetscObject)snes)->tablevel);
3650: }
3652: if (snes->errorifnotconverged && snes->reason < 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_NOT_CONVERGED,"SNESSolve has not converged");
3653: if (grid < snes->gridsequence) {
3654: DM fine;
3655: Vec xnew;
3656: Mat interp;
3658: DMRefine(snes->dm,PetscObjectComm((PetscObject)snes),&fine);
3659: if (!fine) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"DMRefine() did not perform any refinement, cannot continue grid sequencing");
3660: DMCreateInterpolation(snes->dm,fine,&interp,NULL);
3661: DMCreateGlobalVector(fine,&xnew);
3662: MatInterpolate(interp,x,xnew);
3663: DMInterpolate(snes->dm,interp,fine);
3664: MatDestroy(&interp);
3665: x = xnew;
3667: SNESReset(snes);
3668: SNESSetDM(snes,fine);
3669: DMDestroy(&fine);
3670: PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));
3671: }
3672: }
3673: /* monitoring and viewing */
3674: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_view",&viewer,&format,&flg);
3675: if (flg && !PetscPreLoadingOn) {
3676: PetscViewerPushFormat(viewer,format);
3677: SNESView(snes,viewer);
3678: PetscViewerPopFormat(viewer);
3679: PetscViewerDestroy(&viewer);
3680: }
3681: VecViewFromOptions(snes->vec_sol,((PetscObject)snes)->prefix,"-snes_view_solution");
3683: VecDestroy(&xcreated);
3684: PetscObjectAMSBlock((PetscObject)snes);
3685: return(0);
3686: }
3688: /* --------- Internal routines for SNES Package --------- */
3692: /*@C
3693: SNESSetType - Sets the method for the nonlinear solver.
3695: Collective on SNES
3697: Input Parameters:
3698: + snes - the SNES context
3699: - type - a known method
3701: Options Database Key:
3702: . -snes_type <type> - Sets the method; use -help for a list
3703: of available methods (for instance, newtonls or newtontr)
3705: Notes:
3706: See "petsc/include/petscsnes.h" for available methods (for instance)
3707: + SNESNEWTONLS - Newton's method with line search
3708: (systems of nonlinear equations)
3709: . SNESNEWTONTR - Newton's method with trust region
3710: (systems of nonlinear equations)
3712: Normally, it is best to use the SNESSetFromOptions() command and then
3713: set the SNES solver type from the options database rather than by using
3714: this routine. Using the options database provides the user with
3715: maximum flexibility in evaluating the many nonlinear solvers.
3716: The SNESSetType() routine is provided for those situations where it
3717: is necessary to set the nonlinear solver independently of the command
3718: line or options database. This might be the case, for example, when
3719: the choice of solver changes during the execution of the program,
3720: and the user's application is taking responsibility for choosing the
3721: appropriate method.
3723: Level: intermediate
3725: .keywords: SNES, set, type
3727: .seealso: SNESType, SNESCreate()
3729: @*/
3730: PetscErrorCode SNESSetType(SNES snes,SNESType type)
3731: {
3732: PetscErrorCode ierr,(*r)(SNES);
3733: PetscBool match;
3739: PetscObjectTypeCompare((PetscObject)snes,type,&match);
3740: if (match) return(0);
3742: PetscFunctionListFind(SNESList,type,&r);
3743: if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested SNES type %s",type);
3744: /* Destroy the previous private SNES context */
3745: if (snes->ops->destroy) {
3746: (*(snes)->ops->destroy)(snes);
3747: snes->ops->destroy = NULL;
3748: }
3749: /* Reinitialize function pointers in SNESOps structure */
3750: snes->ops->setup = 0;
3751: snes->ops->solve = 0;
3752: snes->ops->view = 0;
3753: snes->ops->setfromoptions = 0;
3754: snes->ops->destroy = 0;
3755: /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
3756: snes->setupcalled = PETSC_FALSE;
3758: PetscObjectChangeTypeName((PetscObject)snes,type);
3759: (*r)(snes);
3760: return(0);
3761: }
3765: /*@C
3766: SNESGetType - Gets the SNES method type and name (as a string).
3768: Not Collective
3770: Input Parameter:
3771: . snes - nonlinear solver context
3773: Output Parameter:
3774: . type - SNES method (a character string)
3776: Level: intermediate
3778: .keywords: SNES, nonlinear, get, type, name
3779: @*/
3780: PetscErrorCode SNESGetType(SNES snes,SNESType *type)
3781: {
3785: *type = ((PetscObject)snes)->type_name;
3786: return(0);
3787: }
3791: /*@
3792: SNESGetSolution - Returns the vector where the approximate solution is
3793: stored. This is the fine grid solution when using SNESSetGridSequence().
3795: Not Collective, but Vec is parallel if SNES is parallel
3797: Input Parameter:
3798: . snes - the SNES context
3800: Output Parameter:
3801: . x - the solution
3803: Level: intermediate
3805: .keywords: SNES, nonlinear, get, solution
3807: .seealso: SNESGetSolutionUpdate(), SNESGetFunction()
3808: @*/
3809: PetscErrorCode SNESGetSolution(SNES snes,Vec *x)
3810: {
3814: *x = snes->vec_sol;
3815: return(0);
3816: }
3820: /*@
3821: SNESGetSolutionUpdate - Returns the vector where the solution update is
3822: stored.
3824: Not Collective, but Vec is parallel if SNES is parallel
3826: Input Parameter:
3827: . snes - the SNES context
3829: Output Parameter:
3830: . x - the solution update
3832: Level: advanced
3834: .keywords: SNES, nonlinear, get, solution, update
3836: .seealso: SNESGetSolution(), SNESGetFunction()
3837: @*/
3838: PetscErrorCode SNESGetSolutionUpdate(SNES snes,Vec *x)
3839: {
3843: *x = snes->vec_sol_update;
3844: return(0);
3845: }
3849: /*@C
3850: SNESGetFunction - Returns the vector where the function is stored.
3852: Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet.
3854: Input Parameter:
3855: . snes - the SNES context
3857: Output Parameter:
3858: + r - the vector that is used to store residuals (or NULL if you don't want it)
3859: . SNESFunction- the function (or NULL if you don't want it)
3860: - ctx - the function context (or NULL if you don't want it)
3862: Level: advanced
3864: .keywords: SNES, nonlinear, get, function
3866: .seealso: SNESSetFunction(), SNESGetSolution(), SNESFunction
3867: @*/
3868: PetscErrorCode SNESGetFunction(SNES snes,Vec *r,PetscErrorCode (**SNESFunction)(SNES,Vec,Vec,void*),void **ctx)
3869: {
3871: DM dm;
3875: if (r) {
3876: if (!snes->vec_func) {
3877: if (snes->vec_rhs) {
3878: VecDuplicate(snes->vec_rhs,&snes->vec_func);
3879: } else if (snes->vec_sol) {
3880: VecDuplicate(snes->vec_sol,&snes->vec_func);
3881: } else if (snes->dm) {
3882: DMCreateGlobalVector(snes->dm,&snes->vec_func);
3883: }
3884: }
3885: *r = snes->vec_func;
3886: }
3887: SNESGetDM(snes,&dm);
3888: DMSNESGetFunction(dm,SNESFunction,ctx);
3889: return(0);
3890: }
3892: /*@C
3893: SNESGetGS - Returns the GS function and context.
3895: Input Parameter:
3896: . snes - the SNES context
3898: Output Parameter:
3899: + SNESGSFunction - the function (or NULL)
3900: - ctx - the function context (or NULL)
3902: Level: advanced
3904: .keywords: SNES, nonlinear, get, function
3906: .seealso: SNESSetGS(), SNESGetFunction()
3907: @*/
3911: PetscErrorCode SNESGetGS (SNES snes, PetscErrorCode (**SNESGSFunction)(SNES, Vec, Vec, void*), void ** ctx)
3912: {
3914: DM dm;
3918: SNESGetDM(snes,&dm);
3919: DMSNESGetGS(dm,SNESGSFunction,ctx);
3920: return(0);
3921: }
3925: /*@C
3926: SNESSetOptionsPrefix - Sets the prefix used for searching for all
3927: SNES options in the database.
3929: Logically Collective on SNES
3931: Input Parameter:
3932: + snes - the SNES context
3933: - prefix - the prefix to prepend to all option names
3935: Notes:
3936: A hyphen (-) must NOT be given at the beginning of the prefix name.
3937: The first character of all runtime options is AUTOMATICALLY the hyphen.
3939: Level: advanced
3941: .keywords: SNES, set, options, prefix, database
3943: .seealso: SNESSetFromOptions()
3944: @*/
3945: PetscErrorCode SNESSetOptionsPrefix(SNES snes,const char prefix[])
3946: {
3951: PetscObjectSetOptionsPrefix((PetscObject)snes,prefix);
3952: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
3953: if (snes->linesearch) {
3954: SNESGetLineSearch(snes,&snes->linesearch);
3955: PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch,prefix);
3956: }
3957: KSPSetOptionsPrefix(snes->ksp,prefix);
3958: return(0);
3959: }
3963: /*@C
3964: SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
3965: SNES options in the database.
3967: Logically Collective on SNES
3969: Input Parameters:
3970: + snes - the SNES context
3971: - prefix - the prefix to prepend to all option names
3973: Notes:
3974: A hyphen (-) must NOT be given at the beginning of the prefix name.
3975: The first character of all runtime options is AUTOMATICALLY the hyphen.
3977: Level: advanced
3979: .keywords: SNES, append, options, prefix, database
3981: .seealso: SNESGetOptionsPrefix()
3982: @*/
3983: PetscErrorCode SNESAppendOptionsPrefix(SNES snes,const char prefix[])
3984: {
3989: PetscObjectAppendOptionsPrefix((PetscObject)snes,prefix);
3990: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
3991: if (snes->linesearch) {
3992: SNESGetLineSearch(snes,&snes->linesearch);
3993: PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch,prefix);
3994: }
3995: KSPAppendOptionsPrefix(snes->ksp,prefix);
3996: return(0);
3997: }
4001: /*@C
4002: SNESGetOptionsPrefix - Sets the prefix used for searching for all
4003: SNES options in the database.
4005: Not Collective
4007: Input Parameter:
4008: . snes - the SNES context
4010: Output Parameter:
4011: . prefix - pointer to the prefix string used
4013: Notes: On the fortran side, the user should pass in a string 'prefix' of
4014: sufficient length to hold the prefix.
4016: Level: advanced
4018: .keywords: SNES, get, options, prefix, database
4020: .seealso: SNESAppendOptionsPrefix()
4021: @*/
4022: PetscErrorCode SNESGetOptionsPrefix(SNES snes,const char *prefix[])
4023: {
4028: PetscObjectGetOptionsPrefix((PetscObject)snes,prefix);
4029: return(0);
4030: }
4035: /*@C
4036: SNESRegister - Adds a method to the nonlinear solver package.
4038: Not collective
4040: Input Parameters:
4041: + name_solver - name of a new user-defined solver
4042: - routine_create - routine to create method context
4044: Notes:
4045: SNESRegister() may be called multiple times to add several user-defined solvers.
4047: Sample usage:
4048: .vb
4049: SNESRegister("my_solver",MySolverCreate);
4050: .ve
4052: Then, your solver can be chosen with the procedural interface via
4053: $ SNESSetType(snes,"my_solver")
4054: or at runtime via the option
4055: $ -snes_type my_solver
4057: Level: advanced
4059: Note: If your function is not being put into a shared library then use SNESRegister() instead
4061: .keywords: SNES, nonlinear, register
4063: .seealso: SNESRegisterAll(), SNESRegisterDestroy()
4065: Level: advanced
4066: @*/
4067: PetscErrorCode SNESRegister(const char sname[],PetscErrorCode (*function)(SNES))
4068: {
4072: PetscFunctionListAdd(&SNESList,sname,function);
4073: return(0);
4074: }
4078: PetscErrorCode SNESTestLocalMin(SNES snes)
4079: {
4081: PetscInt N,i,j;
4082: Vec u,uh,fh;
4083: PetscScalar value;
4084: PetscReal norm;
4087: SNESGetSolution(snes,&u);
4088: VecDuplicate(u,&uh);
4089: VecDuplicate(u,&fh);
4091: /* currently only works for sequential */
4092: PetscPrintf(PETSC_COMM_WORLD,"Testing FormFunction() for local min\n");
4093: VecGetSize(u,&N);
4094: for (i=0; i<N; i++) {
4095: VecCopy(u,uh);
4096: PetscPrintf(PETSC_COMM_WORLD,"i = %D\n",i);
4097: for (j=-10; j<11; j++) {
4098: value = PetscSign(j)*exp(PetscAbs(j)-10.0);
4099: VecSetValue(uh,i,value,ADD_VALUES);
4100: SNESComputeFunction(snes,uh,fh);
4101: VecNorm(fh,NORM_2,&norm);
4102: PetscPrintf(PETSC_COMM_WORLD," j norm %D %18.16e\n",j,norm);
4103: value = -value;
4104: VecSetValue(uh,i,value,ADD_VALUES);
4105: }
4106: }
4107: VecDestroy(&uh);
4108: VecDestroy(&fh);
4109: return(0);
4110: }
4114: /*@
4115: SNESKSPSetUseEW - Sets SNES use Eisenstat-Walker method for
4116: computing relative tolerance for linear solvers within an inexact
4117: Newton method.
4119: Logically Collective on SNES
4121: Input Parameters:
4122: + snes - SNES context
4123: - flag - PETSC_TRUE or PETSC_FALSE
4125: Options Database:
4126: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
4127: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
4128: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
4129: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
4130: . -snes_ksp_ew_gamma <gamma> - Sets gamma
4131: . -snes_ksp_ew_alpha <alpha> - Sets alpha
4132: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
4133: - -snes_ksp_ew_threshold <threshold> - Sets threshold
4135: Notes:
4136: Currently, the default is to use a constant relative tolerance for
4137: the inner linear solvers. Alternatively, one can use the
4138: Eisenstat-Walker method, where the relative convergence tolerance
4139: is reset at each Newton iteration according progress of the nonlinear
4140: solver.
4142: Level: advanced
4144: Reference:
4145: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
4146: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
4148: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
4150: .seealso: SNESKSPGetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
4151: @*/
4152: PetscErrorCode SNESKSPSetUseEW(SNES snes,PetscBool flag)
4153: {
4157: snes->ksp_ewconv = flag;
4158: return(0);
4159: }
4163: /*@
4164: SNESKSPGetUseEW - Gets if SNES is using Eisenstat-Walker method
4165: for computing relative tolerance for linear solvers within an
4166: inexact Newton method.
4168: Not Collective
4170: Input Parameter:
4171: . snes - SNES context
4173: Output Parameter:
4174: . flag - PETSC_TRUE or PETSC_FALSE
4176: Notes:
4177: Currently, the default is to use a constant relative tolerance for
4178: the inner linear solvers. Alternatively, one can use the
4179: Eisenstat-Walker method, where the relative convergence tolerance
4180: is reset at each Newton iteration according progress of the nonlinear
4181: solver.
4183: Level: advanced
4185: Reference:
4186: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
4187: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
4189: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
4191: .seealso: SNESKSPSetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
4192: @*/
4193: PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
4194: {
4198: *flag = snes->ksp_ewconv;
4199: return(0);
4200: }
4204: /*@
4205: SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
4206: convergence criteria for the linear solvers within an inexact
4207: Newton method.
4209: Logically Collective on SNES
4211: Input Parameters:
4212: + snes - SNES context
4213: . version - version 1, 2 (default is 2) or 3
4214: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
4215: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
4216: . gamma - multiplicative factor for version 2 rtol computation
4217: (0 <= gamma2 <= 1)
4218: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
4219: . alpha2 - power for safeguard
4220: - threshold - threshold for imposing safeguard (0 < threshold < 1)
4222: Note:
4223: Version 3 was contributed by Luis Chacon, June 2006.
4225: Use PETSC_DEFAULT to retain the default for any of the parameters.
4227: Level: advanced
4229: Reference:
4230: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
4231: inexact Newton method", Utah State University Math. Stat. Dept. Res.
4232: Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
4234: .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
4236: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPGetParametersEW()
4237: @*/
4238: PetscErrorCode SNESKSPSetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,PetscReal gamma,PetscReal alpha,PetscReal alpha2,PetscReal threshold)
4239: {
4240: SNESKSPEW *kctx;
4244: kctx = (SNESKSPEW*)snes->kspconvctx;
4245: if (!kctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
4254: if (version != PETSC_DEFAULT) kctx->version = version;
4255: if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
4256: if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max;
4257: if (gamma != PETSC_DEFAULT) kctx->gamma = gamma;
4258: if (alpha != PETSC_DEFAULT) kctx->alpha = alpha;
4259: if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2;
4260: if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
4262: if (kctx->version < 1 || kctx->version > 3) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 and 3 are supported: %D",kctx->version);
4263: if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %G",kctx->rtol_0);
4264: if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%G) < 1.0\n",kctx->rtol_max);
4265: if (kctx->gamma < 0.0 || kctx->gamma > 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%G) <= 1.0\n",kctx->gamma);
4266: if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%G) <= 2.0\n",kctx->alpha);
4267: if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%G) < 1.0\n",kctx->threshold);
4268: return(0);
4269: }
4273: /*@
4274: SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
4275: convergence criteria for the linear solvers within an inexact
4276: Newton method.
4278: Not Collective
4280: Input Parameters:
4281: snes - SNES context
4283: Output Parameters:
4284: + version - version 1, 2 (default is 2) or 3
4285: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
4286: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
4287: . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
4288: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
4289: . alpha2 - power for safeguard
4290: - threshold - threshold for imposing safeguard (0 < threshold < 1)
4292: Level: advanced
4294: .keywords: SNES, KSP, Eisenstat, Walker, get, parameters
4296: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPSetParametersEW()
4297: @*/
4298: PetscErrorCode SNESKSPGetParametersEW(SNES snes,PetscInt *version,PetscReal *rtol_0,PetscReal *rtol_max,PetscReal *gamma,PetscReal *alpha,PetscReal *alpha2,PetscReal *threshold)
4299: {
4300: SNESKSPEW *kctx;
4304: kctx = (SNESKSPEW*)snes->kspconvctx;
4305: if (!kctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
4306: if (version) *version = kctx->version;
4307: if (rtol_0) *rtol_0 = kctx->rtol_0;
4308: if (rtol_max) *rtol_max = kctx->rtol_max;
4309: if (gamma) *gamma = kctx->gamma;
4310: if (alpha) *alpha = kctx->alpha;
4311: if (alpha2) *alpha2 = kctx->alpha2;
4312: if (threshold) *threshold = kctx->threshold;
4313: return(0);
4314: }
4318: PetscErrorCode SNESKSPEW_PreSolve(KSP ksp, Vec b, Vec x, SNES snes)
4319: {
4321: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
4322: PetscReal rtol = PETSC_DEFAULT,stol;
4325: if (!snes->ksp_ewconv) return(0);
4326: if (!snes->iter) rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
4327: else {
4328: if (kctx->version == 1) {
4329: rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
4330: if (rtol < 0.0) rtol = -rtol;
4331: stol = PetscPowReal(kctx->rtol_last,kctx->alpha2);
4332: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
4333: } else if (kctx->version == 2) {
4334: rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha);
4335: stol = kctx->gamma * PetscPowReal(kctx->rtol_last,kctx->alpha);
4336: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
4337: } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
4338: rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha);
4339: /* safeguard: avoid sharp decrease of rtol */
4340: stol = kctx->gamma*PetscPowReal(kctx->rtol_last,kctx->alpha);
4341: stol = PetscMax(rtol,stol);
4342: rtol = PetscMin(kctx->rtol_0,stol);
4343: /* safeguard: avoid oversolving */
4344: stol = kctx->gamma*(snes->ttol)/snes->norm;
4345: stol = PetscMax(rtol,stol);
4346: rtol = PetscMin(kctx->rtol_0,stol);
4347: } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 or 3 are supported: %D",kctx->version);
4348: }
4349: /* safeguard: avoid rtol greater than one */
4350: rtol = PetscMin(rtol,kctx->rtol_max);
4351: KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
4352: PetscInfo3(snes,"iter %D, Eisenstat-Walker (version %D) KSP rtol=%G\n",snes->iter,kctx->version,rtol);
4353: return(0);
4354: }
4358: PetscErrorCode SNESKSPEW_PostSolve(KSP ksp, Vec b, Vec x, SNES snes)
4359: {
4361: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
4362: PCSide pcside;
4363: Vec lres;
4366: if (!snes->ksp_ewconv) return(0);
4367: KSPGetTolerances(ksp,&kctx->rtol_last,0,0,0);
4368: SNESGetFunctionNorm(snes,&kctx->norm_last);
4369: if (kctx->version == 1) {
4370: KSPGetPCSide(ksp,&pcside);
4371: if (pcside == PC_RIGHT) { /* XXX Should we also test KSP_UNPRECONDITIONED_NORM ? */
4372: /* KSP residual is true linear residual */
4373: KSPGetResidualNorm(ksp,&kctx->lresid_last);
4374: } else {
4375: /* KSP residual is preconditioned residual */
4376: /* compute true linear residual norm */
4377: VecDuplicate(b,&lres);
4378: MatMult(snes->jacobian,x,lres);
4379: VecAYPX(lres,-1.0,b);
4380: VecNorm(lres,NORM_2,&kctx->lresid_last);
4381: VecDestroy(&lres);
4382: }
4383: }
4384: return(0);
4385: }
4389: /*@
4390: SNESGetKSP - Returns the KSP context for a SNES solver.
4392: Not Collective, but if SNES object is parallel, then KSP object is parallel
4394: Input Parameter:
4395: . snes - the SNES context
4397: Output Parameter:
4398: . ksp - the KSP context
4400: Notes:
4401: The user can then directly manipulate the KSP context to set various
4402: options, etc. Likewise, the user can then extract and manipulate the
4403: PC contexts as well.
4405: Level: beginner
4407: .keywords: SNES, nonlinear, get, KSP, context
4409: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
4410: @*/
4411: PetscErrorCode SNESGetKSP(SNES snes,KSP *ksp)
4412: {
4419: if (!snes->ksp) {
4420: KSPCreate(PetscObjectComm((PetscObject)snes),&snes->ksp);
4421: PetscObjectIncrementTabLevel((PetscObject)snes->ksp,(PetscObject)snes,1);
4422: PetscLogObjectParent(snes,snes->ksp);
4424: KSPSetPreSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))SNESKSPEW_PreSolve,snes);
4425: KSPSetPostSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))SNESKSPEW_PostSolve,snes);
4426: }
4427: *ksp = snes->ksp;
4428: return(0);
4429: }
4432: #include <petsc-private/dmimpl.h>
4435: /*@
4436: SNESSetDM - Sets the DM that may be used by some preconditioners
4438: Logically Collective on SNES
4440: Input Parameters:
4441: + snes - the preconditioner context
4442: - dm - the dm
4444: Level: intermediate
4446: .seealso: SNESGetDM(), KSPSetDM(), KSPGetDM()
4447: @*/
4448: PetscErrorCode SNESSetDM(SNES snes,DM dm)
4449: {
4451: KSP ksp;
4452: DMSNES sdm;
4456: if (dm) {PetscObjectReference((PetscObject)dm);}
4457: if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
4458: if (snes->dm->dmsnes && snes->dmAuto && !dm->dmsnes) {
4459: DMCopyDMSNES(snes->dm,dm);
4460: DMGetDMSNES(snes->dm,&sdm);
4461: if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
4462: }
4463: DMDestroy(&snes->dm);
4464: }
4465: snes->dm = dm;
4466: snes->dmAuto = PETSC_FALSE;
4468: SNESGetKSP(snes,&ksp);
4469: KSPSetDM(ksp,dm);
4470: KSPSetDMActive(ksp,PETSC_FALSE);
4471: if (snes->pc) {
4472: SNESSetDM(snes->pc, snes->dm);
4473: SNESSetPCSide(snes,snes->pcside);
4474: }
4475: return(0);
4476: }
4480: /*@
4481: SNESGetDM - Gets the DM that may be used by some preconditioners
4483: Not Collective but DM obtained is parallel on SNES
4485: Input Parameter:
4486: . snes - the preconditioner context
4488: Output Parameter:
4489: . dm - the dm
4491: Level: intermediate
4493: .seealso: SNESSetDM(), KSPSetDM(), KSPGetDM()
4494: @*/
4495: PetscErrorCode SNESGetDM(SNES snes,DM *dm)
4496: {
4501: if (!snes->dm) {
4502: DMShellCreate(PetscObjectComm((PetscObject)snes),&snes->dm);
4503: snes->dmAuto = PETSC_TRUE;
4504: }
4505: *dm = snes->dm;
4506: return(0);
4507: }
4511: /*@
4512: SNESSetPC - Sets the nonlinear preconditioner to be used.
4514: Collective on SNES
4516: Input Parameters:
4517: + snes - iterative context obtained from SNESCreate()
4518: - pc - the preconditioner object
4520: Notes:
4521: Use SNESGetPC() to retrieve the preconditioner context (for example,
4522: to configure it using the API).
4524: Level: developer
4526: .keywords: SNES, set, precondition
4527: .seealso: SNESGetPC()
4528: @*/
4529: PetscErrorCode SNESSetPC(SNES snes, SNES pc)
4530: {
4537: PetscObjectReference((PetscObject) pc);
4538: SNESDestroy(&snes->pc);
4539: snes->pc = pc;
4540: PetscLogObjectParent(snes, snes->pc);
4541: return(0);
4542: }
4546: /*@
4547: SNESGetPC - Returns a pointer to the nonlinear preconditioning context set with SNESSetPC().
4549: Not Collective
4551: Input Parameter:
4552: . snes - iterative context obtained from SNESCreate()
4554: Output Parameter:
4555: . pc - preconditioner context
4557: Level: developer
4559: .keywords: SNES, get, preconditioner
4560: .seealso: SNESSetPC()
4561: @*/
4562: PetscErrorCode SNESGetPC(SNES snes, SNES *pc)
4563: {
4565: const char *optionsprefix;
4570: if (!snes->pc) {
4571: SNESCreate(PetscObjectComm((PetscObject)snes),&snes->pc);
4572: PetscObjectIncrementTabLevel((PetscObject)snes->pc,(PetscObject)snes,1);
4573: PetscLogObjectParent(snes,snes->pc);
4574: SNESGetOptionsPrefix(snes,&optionsprefix);
4575: SNESSetOptionsPrefix(snes->pc,optionsprefix);
4576: SNESAppendOptionsPrefix(snes->pc,"npc_");
4577: }
4578: *pc = snes->pc;
4579: return(0);
4580: }
4584: /*@
4585: SNESSetPCSide - Sets the preconditioning side.
4587: Logically Collective on SNES
4589: Input Parameter:
4590: . snes - iterative context obtained from SNESCreate()
4592: Output Parameter:
4593: . side - the preconditioning side, where side is one of
4594: .vb
4595: PC_LEFT - left preconditioning (default)
4596: PC_RIGHT - right preconditioning
4597: .ve
4599: Options Database Keys:
4600: . -snes_pc_side <right,left>
4602: Level: intermediate
4604: .keywords: SNES, set, right, left, side, preconditioner, flag
4606: .seealso: SNESGetPCSide(), KSPSetPCSide()
4607: @*/
4608: PetscErrorCode SNESSetPCSide(SNES snes,PCSide side)
4609: {
4613: snes->pcside = side;
4614: return(0);
4615: }
4619: /*@
4620: SNESGetPCSide - Gets the preconditioning side.
4622: Not Collective
4624: Input Parameter:
4625: . snes - iterative context obtained from SNESCreate()
4627: Output Parameter:
4628: . side - the preconditioning side, where side is one of
4629: .vb
4630: PC_LEFT - left preconditioning (default)
4631: PC_RIGHT - right preconditioning
4632: .ve
4634: Level: intermediate
4636: .keywords: SNES, get, right, left, side, preconditioner, flag
4638: .seealso: SNESSetPCSide(), KSPGetPCSide()
4639: @*/
4640: PetscErrorCode SNESGetPCSide(SNES snes,PCSide *side)
4641: {
4645: *side = snes->pcside;
4646: return(0);
4647: }
4651: /*@
4652: SNESSetLineSearch - Sets the linesearch on the SNES instance.
4654: Collective on SNES
4656: Input Parameters:
4657: + snes - iterative context obtained from SNESCreate()
4658: - linesearch - the linesearch object
4660: Notes:
4661: Use SNESGetLineSearch() to retrieve the preconditioner context (for example,
4662: to configure it using the API).
4664: Level: developer
4666: .keywords: SNES, set, linesearch
4667: .seealso: SNESGetLineSearch()
4668: @*/
4669: PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
4670: {
4677: PetscObjectReference((PetscObject) linesearch);
4678: SNESLineSearchDestroy(&snes->linesearch);
4680: snes->linesearch = linesearch;
4682: PetscLogObjectParent(snes, snes->linesearch);
4683: return(0);
4684: }
4688: /*@
4689: SNESGetLineSearch - Returns a pointer to the line search context set with SNESSetLineSearch()
4690: or creates a default line search instance associated with the SNES and returns it.
4692: Not Collective
4694: Input Parameter:
4695: . snes - iterative context obtained from SNESCreate()
4697: Output Parameter:
4698: . linesearch - linesearch context
4700: Level: developer
4702: .keywords: SNES, get, linesearch
4703: .seealso: SNESSetLineSearch()
4704: @*/
4705: PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
4706: {
4708: const char *optionsprefix;
4713: if (!snes->linesearch) {
4714: SNESGetOptionsPrefix(snes, &optionsprefix);
4715: SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch);
4716: SNESLineSearchSetSNES(snes->linesearch, snes);
4717: SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix);
4718: PetscObjectIncrementTabLevel((PetscObject) snes->linesearch, (PetscObject) snes, 1);
4719: PetscLogObjectParent(snes, snes->linesearch);
4720: }
4721: *linesearch = snes->linesearch;
4722: return(0);
4723: }
4725: #if defined(PETSC_HAVE_MATLAB_ENGINE)
4726: #include <mex.h>
4728: typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
4732: /*
4733: SNESComputeFunction_Matlab - Calls the function that has been set with SNESSetFunctionMatlab().
4735: Collective on SNES
4737: Input Parameters:
4738: + snes - the SNES context
4739: - x - input vector
4741: Output Parameter:
4742: . y - function vector, as set by SNESSetFunction()
4744: Notes:
4745: SNESComputeFunction() is typically used within nonlinear solvers
4746: implementations, so most users would not generally call this routine
4747: themselves.
4749: Level: developer
4751: .keywords: SNES, nonlinear, compute, function
4753: .seealso: SNESSetFunction(), SNESGetFunction()
4754: */
4755: PetscErrorCode SNESComputeFunction_Matlab(SNES snes,Vec x,Vec y, void *ctx)
4756: {
4757: PetscErrorCode ierr;
4758: SNESMatlabContext *sctx = (SNESMatlabContext*)ctx;
4759: int nlhs = 1,nrhs = 5;
4760: mxArray *plhs[1],*prhs[5];
4761: long long int lx = 0,ly = 0,ls = 0;
4770: /* call Matlab function in ctx with arguments x and y */
4772: PetscMemcpy(&ls,&snes,sizeof(snes));
4773: PetscMemcpy(&lx,&x,sizeof(x));
4774: PetscMemcpy(&ly,&y,sizeof(x));
4775: prhs[0] = mxCreateDoubleScalar((double)ls);
4776: prhs[1] = mxCreateDoubleScalar((double)lx);
4777: prhs[2] = mxCreateDoubleScalar((double)ly);
4778: prhs[3] = mxCreateString(sctx->funcname);
4779: prhs[4] = sctx->ctx;
4780: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESComputeFunctionInternal");
4781: mxGetScalar(plhs[0]);
4782: mxDestroyArray(prhs[0]);
4783: mxDestroyArray(prhs[1]);
4784: mxDestroyArray(prhs[2]);
4785: mxDestroyArray(prhs[3]);
4786: mxDestroyArray(plhs[0]);
4787: return(0);
4788: }
4792: /*
4793: SNESSetFunctionMatlab - Sets the function evaluation routine and function
4794: vector for use by the SNES routines in solving systems of nonlinear
4795: equations from MATLAB. Here the function is a string containing the name of a MATLAB function
4797: Logically Collective on SNES
4799: Input Parameters:
4800: + snes - the SNES context
4801: . r - vector to store function value
4802: - SNESFunction - function evaluation routine
4804: Notes:
4805: The Newton-like methods typically solve linear systems of the form
4806: $ f'(x) x = -f(x),
4807: where f'(x) denotes the Jacobian matrix and f(x) is the function.
4809: Level: beginner
4811: Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx;
4813: .keywords: SNES, nonlinear, set, function
4815: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
4816: */
4817: PetscErrorCode SNESSetFunctionMatlab(SNES snes,Vec r,const char *SNESFunction,mxArray *ctx)
4818: {
4819: PetscErrorCode ierr;
4820: SNESMatlabContext *sctx;
4823: /* currently sctx is memory bleed */
4824: PetscMalloc(sizeof(SNESMatlabContext),&sctx);
4825: PetscStrallocpy(SNESFunction,&sctx->funcname);
4826: /*
4827: This should work, but it doesn't
4828: sctx->ctx = ctx;
4829: mexMakeArrayPersistent(sctx->ctx);
4830: */
4831: sctx->ctx = mxDuplicateArray(ctx);
4832: SNESSetFunction(snes,r,SNESComputeFunction_Matlab,sctx);
4833: return(0);
4834: }
4838: /*
4839: SNESComputeJacobian_Matlab - Calls the function that has been set with SNESSetJacobianMatlab().
4841: Collective on SNES
4843: Input Parameters:
4844: + snes - the SNES context
4845: . x - input vector
4846: . A, B - the matrices
4847: - ctx - user context
4849: Output Parameter:
4850: . flag - structure of the matrix
4852: Level: developer
4854: .keywords: SNES, nonlinear, compute, function
4856: .seealso: SNESSetFunction(), SNESGetFunction()
4857: @*/
4858: PetscErrorCode SNESComputeJacobian_Matlab(SNES snes,Vec x,Mat *A,Mat *B,MatStructure *flag, void *ctx)
4859: {
4860: PetscErrorCode ierr;
4861: SNESMatlabContext *sctx = (SNESMatlabContext*)ctx;
4862: int nlhs = 2,nrhs = 6;
4863: mxArray *plhs[2],*prhs[6];
4864: long long int lx = 0,lA = 0,ls = 0, lB = 0;
4870: /* call Matlab function in ctx with arguments x and y */
4872: PetscMemcpy(&ls,&snes,sizeof(snes));
4873: PetscMemcpy(&lx,&x,sizeof(x));
4874: PetscMemcpy(&lA,A,sizeof(x));
4875: PetscMemcpy(&lB,B,sizeof(x));
4876: prhs[0] = mxCreateDoubleScalar((double)ls);
4877: prhs[1] = mxCreateDoubleScalar((double)lx);
4878: prhs[2] = mxCreateDoubleScalar((double)lA);
4879: prhs[3] = mxCreateDoubleScalar((double)lB);
4880: prhs[4] = mxCreateString(sctx->funcname);
4881: prhs[5] = sctx->ctx;
4882: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESComputeJacobianInternal");
4883: mxGetScalar(plhs[0]);
4884: *flag = (MatStructure) mxGetScalar(plhs[1]);
4885: mxDestroyArray(prhs[0]);
4886: mxDestroyArray(prhs[1]);
4887: mxDestroyArray(prhs[2]);
4888: mxDestroyArray(prhs[3]);
4889: mxDestroyArray(prhs[4]);
4890: mxDestroyArray(plhs[0]);
4891: mxDestroyArray(plhs[1]);
4892: return(0);
4893: }
4897: /*
4898: SNESSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
4899: vector for use by the SNES routines in solving systems of nonlinear
4900: equations from MATLAB. Here the function is a string containing the name of a MATLAB function
4902: Logically Collective on SNES
4904: Input Parameters:
4905: + snes - the SNES context
4906: . A,B - Jacobian matrices
4907: . SNESJacobianFunction - function evaluation routine
4908: - ctx - user context
4910: Level: developer
4912: Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx;
4914: .keywords: SNES, nonlinear, set, function
4916: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction(), SNESJacobianFunction
4917: */
4918: PetscErrorCode SNESSetJacobianMatlab(SNES snes,Mat A,Mat B,const char *SNESJacobianFunction,mxArray *ctx)
4919: {
4920: PetscErrorCode ierr;
4921: SNESMatlabContext *sctx;
4924: /* currently sctx is memory bleed */
4925: PetscMalloc(sizeof(SNESMatlabContext),&sctx);
4926: PetscStrallocpy(SNESJacobianFunction,&sctx->funcname);
4927: /*
4928: This should work, but it doesn't
4929: sctx->ctx = ctx;
4930: mexMakeArrayPersistent(sctx->ctx);
4931: */
4932: sctx->ctx = mxDuplicateArray(ctx);
4933: SNESSetJacobian(snes,A,B,SNESComputeJacobian_Matlab,sctx);
4934: return(0);
4935: }
4939: /*
4940: SNESMonitor_Matlab - Calls the function that has been set with SNESMonitorSetMatlab().
4942: Collective on SNES
4944: .seealso: SNESSetFunction(), SNESGetFunction()
4945: @*/
4946: PetscErrorCode SNESMonitor_Matlab(SNES snes,PetscInt it, PetscReal fnorm, void *ctx)
4947: {
4948: PetscErrorCode ierr;
4949: SNESMatlabContext *sctx = (SNESMatlabContext*)ctx;
4950: int nlhs = 1,nrhs = 6;
4951: mxArray *plhs[1],*prhs[6];
4952: long long int lx = 0,ls = 0;
4953: Vec x = snes->vec_sol;
4958: PetscMemcpy(&ls,&snes,sizeof(snes));
4959: PetscMemcpy(&lx,&x,sizeof(x));
4960: prhs[0] = mxCreateDoubleScalar((double)ls);
4961: prhs[1] = mxCreateDoubleScalar((double)it);
4962: prhs[2] = mxCreateDoubleScalar((double)fnorm);
4963: prhs[3] = mxCreateDoubleScalar((double)lx);
4964: prhs[4] = mxCreateString(sctx->funcname);
4965: prhs[5] = sctx->ctx;
4966: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESMonitorInternal");
4967: mxGetScalar(plhs[0]);
4968: mxDestroyArray(prhs[0]);
4969: mxDestroyArray(prhs[1]);
4970: mxDestroyArray(prhs[2]);
4971: mxDestroyArray(prhs[3]);
4972: mxDestroyArray(prhs[4]);
4973: mxDestroyArray(plhs[0]);
4974: return(0);
4975: }
4979: /*
4980: SNESMonitorSetMatlab - Sets the monitor function from MATLAB
4982: Level: developer
4984: Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx;
4986: .keywords: SNES, nonlinear, set, function
4988: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
4989: */
4990: PetscErrorCode SNESMonitorSetMatlab(SNES snes,const char *SNESMonitorFunction,mxArray *ctx)
4991: {
4992: PetscErrorCode ierr;
4993: SNESMatlabContext *sctx;
4996: /* currently sctx is memory bleed */
4997: PetscMalloc(sizeof(SNESMatlabContext),&sctx);
4998: PetscStrallocpy(SNESMonitorFunction,&sctx->funcname);
4999: /*
5000: This should work, but it doesn't
5001: sctx->ctx = ctx;
5002: mexMakeArrayPersistent(sctx->ctx);
5003: */
5004: sctx->ctx = mxDuplicateArray(ctx);
5005: SNESMonitorSet(snes,SNESMonitor_Matlab,sctx,NULL);
5006: return(0);
5007: }
5009: #endif