Actual source code: snes.c
petsc-3.9.2 2018-05-20
2: #include <petsc/private/snesimpl.h>
3: #include <petscdmshell.h>
4: #include <petscdraw.h>
5: #include <petscds.h>
6: #include <petscdmadaptor.h>
7: #include <petscconvest.h>
9: PetscBool SNESRegisterAllCalled = PETSC_FALSE;
10: PetscFunctionList SNESList = NULL;
12: /* Logging support */
13: PetscClassId SNES_CLASSID, DMSNES_CLASSID;
14: PetscLogEvent SNES_Solve, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval;
16: /*@
17: SNESSetErrorIfNotConverged - Causes SNESSolve() to generate an error if the solver has not converged.
19: Logically Collective on SNES
21: Input Parameters:
22: + snes - iterative context obtained from SNESCreate()
23: - flg - PETSC_TRUE indicates you want the error generated
25: Options database keys:
26: . -snes_error_if_not_converged : this takes an optional truth value (0/1/no/yes/true/false)
28: Level: intermediate
30: Notes:
31: Normally PETSc continues if a linear solver fails to converge, you can call SNESGetConvergedReason() after a SNESSolve()
32: to determine if it has converged.
34: .keywords: SNES, set, initial guess, nonzero
36: .seealso: SNESGetErrorIfNotConverged(), KSPGetErrorIfNotConverged(), KSPSetErrorIFNotConverged()
37: @*/
38: PetscErrorCode SNESSetErrorIfNotConverged(SNES snes,PetscBool flg)
39: {
43: snes->errorifnotconverged = flg;
44: return(0);
45: }
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: }
73: /*@
74: SNESSetAlwaysComputesFinalResidual - does the SNES always compute the residual at the final solution?
76: Logically Collective on SNES
78: Input Parameters:
79: + snes - the shell SNES
80: - flg - is the residual computed?
82: Level: advanced
84: .seealso: SNESGetAlwaysComputesFinalResidual()
85: @*/
86: PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg)
87: {
90: snes->alwayscomputesfinalresidual = flg;
91: return(0);
92: }
94: /*@
95: SNESGetAlwaysComputesFinalResidual - does the SNES always compute the residual at the final solution?
97: Logically Collective on SNES
99: Input Parameter:
100: . snes - the shell SNES
102: Output Parameter:
103: . flg - is the residual computed?
105: Level: advanced
107: .seealso: SNESSetAlwaysComputesFinalResidual()
108: @*/
109: PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg)
110: {
113: *flg = snes->alwayscomputesfinalresidual;
114: return(0);
115: }
117: /*@
118: SNESSetFunctionDomainError - tells SNES that the input vector to your SNESFunction is not
119: in the functions domain. For example, negative pressure.
121: Logically Collective on SNES
123: Input Parameters:
124: . snes - the SNES context
126: Level: advanced
128: .keywords: SNES, view
130: .seealso: SNESCreate(), SNESSetFunction(), SNESFunction
131: @*/
132: PetscErrorCode SNESSetFunctionDomainError(SNES snes)
133: {
136: if (snes->errorifnotconverged) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"User code indicates input vector is not in the function domain");
137: snes->domainerror = PETSC_TRUE;
138: return(0);
139: }
141: /*@
142: SNESGetFunctionDomainError - Gets the status of the domain error after a call to SNESComputeFunction;
144: Logically Collective on SNES
146: Input Parameters:
147: . snes - the SNES context
149: Output Parameters:
150: . domainerror - Set to PETSC_TRUE if there's a domain error; PETSC_FALSE otherwise.
152: Level: advanced
154: .keywords: SNES, view
156: .seealso: SNESSetFunctionDomainError(), SNESComputeFunction()
157: @*/
158: PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
159: {
163: *domainerror = snes->domainerror;
164: return(0);
165: }
167: /*@C
168: SNESLoad - Loads a SNES that has been stored in binary with SNESView().
170: Collective on PetscViewer
172: Input Parameters:
173: + newdm - the newly loaded SNES, this needs to have been created with SNESCreate() or
174: some related function before a call to SNESLoad().
175: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
177: Level: intermediate
179: Notes:
180: The type is determined by the data in the file, any type set into the SNES before this call is ignored.
182: Notes for advanced users:
183: Most users should not need to know the details of the binary storage
184: format, since SNESLoad() and TSView() completely hide these details.
185: But for anyone who's interested, the standard binary matrix storage
186: format is
187: .vb
188: has not yet been determined
189: .ve
191: .seealso: PetscViewerBinaryOpen(), SNESView(), MatLoad(), VecLoad()
192: @*/
193: PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
194: {
196: PetscBool isbinary;
197: PetscInt classid;
198: char type[256];
199: KSP ksp;
200: DM dm;
201: DMSNES dmsnes;
206: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
207: if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
209: PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);
210: if (classid != SNES_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONG,"Not SNES next in file");
211: PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);
212: SNESSetType(snes, type);
213: if (snes->ops->load) {
214: (*snes->ops->load)(snes,viewer);
215: }
216: SNESGetDM(snes,&dm);
217: DMGetDMSNES(dm,&dmsnes);
218: DMSNESLoad(dmsnes,viewer);
219: SNESGetKSP(snes,&ksp);
220: KSPLoad(ksp,viewer);
221: return(0);
222: }
224: #include <petscdraw.h>
225: #if defined(PETSC_HAVE_SAWS)
226: #include <petscviewersaws.h>
227: #endif
229: /*@C
230: SNESView - Prints the SNES data structure.
232: Collective on SNES
234: Input Parameters:
235: + SNES - the SNES context
236: - viewer - visualization context
238: Options Database Key:
239: . -snes_view - Calls SNESView() at end of SNESSolve()
241: Notes:
242: The available visualization contexts include
243: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
244: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
245: output where only the first processor opens
246: the file. All other processors send their
247: data to the first processor to print.
249: The user can open an alternative visualization context with
250: PetscViewerASCIIOpen() - output to a specified file.
252: Level: beginner
254: .keywords: SNES, view
256: .seealso: PetscViewerASCIIOpen()
257: @*/
258: PetscErrorCode SNESView(SNES snes,PetscViewer viewer)
259: {
260: SNESKSPEW *kctx;
262: KSP ksp;
263: SNESLineSearch linesearch;
264: PetscBool iascii,isstring,isbinary,isdraw;
265: DMSNES dmsnes;
266: #if defined(PETSC_HAVE_SAWS)
267: PetscBool issaws;
268: #endif
272: if (!viewer) {
273: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);
274: }
278: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
279: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
280: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
281: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
282: #if defined(PETSC_HAVE_SAWS)
283: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);
284: #endif
285: if (iascii) {
286: SNESNormSchedule normschedule;
287: DM dm;
288: PetscErrorCode (*cJ)(SNES,Vec,Mat,Mat,void*);
289: void *ctx;
290: PetscInt tabs;
292: PetscViewerASCIIGetTab(viewer, &tabs);
293: PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel);
294: PetscObjectPrintClassNamePrefixType((PetscObject)snes,viewer);
295: if (!snes->setupcalled) {
296: PetscViewerASCIIPrintf(viewer," SNES has not been set up so information may be incomplete\n");
297: }
298: if (snes->ops->view) {
299: PetscViewerASCIIPushTab(viewer);
300: (*snes->ops->view)(snes,viewer);
301: PetscViewerASCIIPopTab(viewer);
302: }
303: PetscViewerASCIIPrintf(viewer," maximum iterations=%D, maximum function evaluations=%D\n",snes->max_its,snes->max_funcs);
304: PetscViewerASCIIPrintf(viewer," tolerances: relative=%g, absolute=%g, solution=%g\n",(double)snes->rtol,(double)snes->abstol,(double)snes->stol);
305: if (snes->usesksp) {
306: PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",snes->linear_its);
307: }
308: PetscViewerASCIIPrintf(viewer," total number of function evaluations=%D\n",snes->nfuncs);
309: SNESGetNormSchedule(snes, &normschedule);
310: if (normschedule > 0) {PetscViewerASCIIPrintf(viewer," norm schedule %s\n",SNESNormSchedules[normschedule]);}
311: if (snes->gridsequence) {
312: PetscViewerASCIIPrintf(viewer," total number of grid sequence refinements=%D\n",snes->gridsequence);
313: }
314: if (snes->ksp_ewconv) {
315: kctx = (SNESKSPEW*)snes->kspconvctx;
316: if (kctx) {
317: PetscViewerASCIIPrintf(viewer," Eisenstat-Walker computation of KSP relative tolerance (version %D)\n",kctx->version);
318: PetscViewerASCIIPrintf(viewer," rtol_0=%g, rtol_max=%g, threshold=%g\n",(double)kctx->rtol_0,(double)kctx->rtol_max,(double)kctx->threshold);
319: PetscViewerASCIIPrintf(viewer," gamma=%g, alpha=%g, alpha2=%g\n",(double)kctx->gamma,(double)kctx->alpha,(double)kctx->alpha2);
320: }
321: }
322: if (snes->lagpreconditioner == -1) {
323: PetscViewerASCIIPrintf(viewer," Preconditioned is never rebuilt\n");
324: } else if (snes->lagpreconditioner > 1) {
325: PetscViewerASCIIPrintf(viewer," Preconditioned is rebuilt every %D new Jacobians\n",snes->lagpreconditioner);
326: }
327: if (snes->lagjacobian == -1) {
328: PetscViewerASCIIPrintf(viewer," Jacobian is never rebuilt\n");
329: } else if (snes->lagjacobian > 1) {
330: PetscViewerASCIIPrintf(viewer," Jacobian is rebuilt every %D SNES iterations\n",snes->lagjacobian);
331: }
332: SNESGetDM(snes,&dm);
333: DMSNESGetJacobian(dm,&cJ,&ctx);
334: if (cJ == SNESComputeJacobianDefault) {
335: PetscViewerASCIIPrintf(viewer," Jacobian is built using finite differences one column at a time\n");
336: } else if (cJ == SNESComputeJacobianDefaultColor) {
337: PetscViewerASCIIPrintf(viewer," Jacobian is built using finite differences with coloring\n");
338: }
339: PetscViewerASCIISetTab(viewer, tabs);
340: } else if (isstring) {
341: const char *type;
342: SNESGetType(snes,&type);
343: PetscViewerStringSPrintf(viewer," %-3.3s",type);
344: } else if (isbinary) {
345: PetscInt classid = SNES_FILE_CLASSID;
346: MPI_Comm comm;
347: PetscMPIInt rank;
348: char type[256];
350: PetscObjectGetComm((PetscObject)snes,&comm);
351: MPI_Comm_rank(comm,&rank);
352: if (!rank) {
353: PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);
354: PetscStrncpy(type,((PetscObject)snes)->type_name,sizeof(type));
355: PetscViewerBinaryWrite(viewer,type,sizeof(type),PETSC_CHAR,PETSC_FALSE);
356: }
357: if (snes->ops->view) {
358: (*snes->ops->view)(snes,viewer);
359: }
360: } else if (isdraw) {
361: PetscDraw draw;
362: char str[36];
363: PetscReal x,y,bottom,h;
365: PetscViewerDrawGetDraw(viewer,0,&draw);
366: PetscDrawGetCurrentPoint(draw,&x,&y);
367: PetscStrncpy(str,"SNES: ",sizeof(str));
368: PetscStrlcat(str,((PetscObject)snes)->type_name,sizeof(str));
369: PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_BLUE,PETSC_DRAW_BLACK,str,NULL,&h);
370: bottom = y - h;
371: PetscDrawPushCurrentPoint(draw,x,bottom);
372: if (snes->ops->view) {
373: (*snes->ops->view)(snes,viewer);
374: }
375: #if defined(PETSC_HAVE_SAWS)
376: } else if (issaws) {
377: PetscMPIInt rank;
378: const char *name;
380: PetscObjectGetName((PetscObject)snes,&name);
381: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
382: if (!((PetscObject)snes)->amsmem && !rank) {
383: char dir[1024];
385: PetscObjectViewSAWs((PetscObject)snes,viewer);
386: PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/its",name);
387: PetscStackCallSAWs(SAWs_Register,(dir,&snes->iter,1,SAWs_READ,SAWs_INT));
388: if (!snes->conv_hist) {
389: SNESSetConvergenceHistory(snes,NULL,NULL,PETSC_DECIDE,PETSC_TRUE);
390: }
391: PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/conv_hist",name);
392: PetscStackCallSAWs(SAWs_Register,(dir,snes->conv_hist,10,SAWs_READ,SAWs_DOUBLE));
393: }
394: #endif
395: }
396: if (snes->linesearch) {
397: SNESGetLineSearch(snes, &linesearch);
398: SNESLineSearchView(linesearch, viewer);
399: }
400: if (snes->npc && snes->usesnpc) {
401: SNESView(snes->npc, viewer);
402: }
403: PetscViewerASCIIPushTab(viewer);
404: DMGetDMSNES(snes->dm,&dmsnes);
405: DMSNESView(dmsnes, viewer);
406: PetscViewerASCIIPopTab(viewer);
407: if (snes->usesksp) {
408: SNESGetKSP(snes,&ksp);
409: KSPView(ksp,viewer);
410: }
411: if (isdraw) {
412: PetscDraw draw;
413: PetscViewerDrawGetDraw(viewer,0,&draw);
414: PetscDrawPopCurrentPoint(draw);
415: }
416: return(0);
417: }
419: /*
420: We retain a list of functions that also take SNES command
421: line options. These are called at the end SNESSetFromOptions()
422: */
423: #define MAXSETFROMOPTIONS 5
424: static PetscInt numberofsetfromoptions;
425: static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
427: /*@C
428: SNESAddOptionsChecker - Adds an additional function to check for SNES options.
430: Not Collective
432: Input Parameter:
433: . snescheck - function that checks for options
435: Level: developer
437: .seealso: SNESSetFromOptions()
438: @*/
439: PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES))
440: {
442: if (numberofsetfromoptions >= MAXSETFROMOPTIONS) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %D allowed", MAXSETFROMOPTIONS);
443: othersetfromoptions[numberofsetfromoptions++] = snescheck;
444: return(0);
445: }
447: extern PetscErrorCode SNESDefaultMatrixFreeCreate2(SNES,Vec,Mat*);
449: static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
450: {
451: Mat J;
452: KSP ksp;
453: PC pc;
454: PetscBool match;
456: MatNullSpace nullsp;
461: if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
462: Mat A = snes->jacobian, B = snes->jacobian_pre;
463: MatCreateVecs(A ? A : B, NULL,&snes->vec_func);
464: }
466: if (version == 1) {
467: MatCreateSNESMF(snes,&J);
468: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
469: MatSetFromOptions(J);
470: } else if (version == 2) {
471: if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"SNESSetFunction() must be called first");
472: #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
473: SNESDefaultMatrixFreeCreate2(snes,snes->vec_func,&J);
474: #else
475: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "matrix-free operator rutines (version 2)");
476: #endif
477: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator rutines, only version 1 and 2");
479: /* attach any user provided null space that was on Amat to the newly created matrix free matrix */
480: if (snes->jacobian) {
481: MatGetNullSpace(snes->jacobian,&nullsp);
482: if (nullsp) {
483: MatSetNullSpace(J,nullsp);
484: }
485: }
487: PetscInfo1(snes,"Setting default matrix-free operator routines (version %D)\n", version);
488: if (hasOperator) {
490: /* This version replaces the user provided Jacobian matrix with a
491: matrix-free version but still employs the user-provided preconditioner matrix. */
492: SNESSetJacobian(snes,J,0,0,0);
493: } else {
494: /* This version replaces both the user-provided Jacobian and the user-
495: provided preconditioner Jacobian with the default matrix free version. */
496: if ((snes->npcside== PC_LEFT) && snes->npc) {
497: if (!snes->jacobian){SNESSetJacobian(snes,J,0,0,0);}
498: } else {
499: SNESSetJacobian(snes,J,J,MatMFFDComputeJacobian,0);
500: }
501: /* Force no preconditioner */
502: SNESGetKSP(snes,&ksp);
503: KSPGetPC(ksp,&pc);
504: PetscObjectTypeCompare((PetscObject)pc,PCSHELL,&match);
505: if (!match) {
506: PetscInfo(snes,"Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n");
507: PCSetType(pc,PCNONE);
508: }
509: }
510: MatDestroy(&J);
511: return(0);
512: }
514: static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine,Mat Restrict,Vec Rscale,Mat Inject,DM dmcoarse,void *ctx)
515: {
516: SNES snes = (SNES)ctx;
518: Vec Xfine,Xfine_named = NULL,Xcoarse;
521: if (PetscLogPrintInfo) {
522: PetscInt finelevel,coarselevel,fineclevel,coarseclevel;
523: DMGetRefineLevel(dmfine,&finelevel);
524: DMGetCoarsenLevel(dmfine,&fineclevel);
525: DMGetRefineLevel(dmcoarse,&coarselevel);
526: DMGetCoarsenLevel(dmcoarse,&coarseclevel);
527: PetscInfo4(dmfine,"Restricting SNES solution vector from level %D-%D to level %D-%D\n",finelevel,fineclevel,coarselevel,coarseclevel);
528: }
529: if (dmfine == snes->dm) Xfine = snes->vec_sol;
530: else {
531: DMGetNamedGlobalVector(dmfine,"SNESVecSol",&Xfine_named);
532: Xfine = Xfine_named;
533: }
534: DMGetNamedGlobalVector(dmcoarse,"SNESVecSol",&Xcoarse);
535: if (Inject) {
536: MatRestrict(Inject,Xfine,Xcoarse);
537: } else {
538: MatRestrict(Restrict,Xfine,Xcoarse);
539: VecPointwiseMult(Xcoarse,Xcoarse,Rscale);
540: }
541: DMRestoreNamedGlobalVector(dmcoarse,"SNESVecSol",&Xcoarse);
542: if (Xfine_named) {DMRestoreNamedGlobalVector(dmfine,"SNESVecSol",&Xfine_named);}
543: return(0);
544: }
546: static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm,DM dmc,void *ctx)
547: {
551: DMCoarsenHookAdd(dmc,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,ctx);
552: return(0);
553: }
555: /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
556: * safely call SNESGetDM() in their residual evaluation routine. */
557: static PetscErrorCode KSPComputeOperators_SNES(KSP ksp,Mat A,Mat B,void *ctx)
558: {
559: SNES snes = (SNES)ctx;
561: Mat Asave = A,Bsave = B;
562: Vec X,Xnamed = NULL;
563: DM dmsave;
564: void *ctxsave;
565: PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*) = NULL;
568: dmsave = snes->dm;
569: KSPGetDM(ksp,&snes->dm);
570: if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
571: else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */
572: DMGetNamedGlobalVector(snes->dm,"SNESVecSol",&Xnamed);
573: X = Xnamed;
574: SNESGetJacobian(snes,NULL,NULL,&jac,&ctxsave);
575: /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
576: if (jac == SNESComputeJacobianDefaultColor) {
577: SNESSetJacobian(snes,NULL,NULL,SNESComputeJacobianDefaultColor,0);
578: }
579: }
580: /* put the previous context back */
582: SNESComputeJacobian(snes,X,A,B);
583: if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) {
584: SNESSetJacobian(snes,NULL,NULL,jac,ctxsave);
585: }
587: if (A != Asave || B != Bsave) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"No support for changing matrices at this time");
588: if (Xnamed) {
589: DMRestoreNamedGlobalVector(snes->dm,"SNESVecSol",&Xnamed);
590: }
591: snes->dm = dmsave;
592: return(0);
593: }
595: /*@
596: SNESSetUpMatrices - ensures that matrices are available for SNES, to be called by SNESSetUp_XXX()
598: Collective
600: Input Arguments:
601: . snes - snes to configure
603: Level: developer
605: .seealso: SNESSetUp()
606: @*/
607: PetscErrorCode SNESSetUpMatrices(SNES snes)
608: {
610: DM dm;
611: DMSNES sdm;
614: SNESGetDM(snes,&dm);
615: DMGetDMSNES(dm,&sdm);
616: if (!sdm->ops->computejacobian) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"DMSNES not properly configured");
617: else if (!snes->jacobian && snes->mf) {
618: Mat J;
619: void *functx;
620: MatCreateSNESMF(snes,&J);
621: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
622: MatSetFromOptions(J);
623: SNESGetFunction(snes,NULL,NULL,&functx);
624: SNESSetJacobian(snes,J,J,0,0);
625: MatDestroy(&J);
626: } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
627: Mat J,B;
628: MatCreateSNESMF(snes,&J);
629: MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);
630: MatSetFromOptions(J);
631: DMCreateMatrix(snes->dm,&B);
632: /* sdm->computejacobian was already set to reach here */
633: SNESSetJacobian(snes,J,B,NULL,NULL);
634: MatDestroy(&J);
635: MatDestroy(&B);
636: } else if (!snes->jacobian_pre) {
637: PetscDS prob;
638: Mat J, B;
639: PetscBool hasPrec = PETSC_FALSE;
641: J = snes->jacobian;
642: DMGetDS(dm, &prob);
643: if (prob) {PetscDSHasJacobianPreconditioner(prob, &hasPrec);}
644: if (J) {PetscObjectReference((PetscObject) J);}
645: else if (hasPrec) {DMCreateMatrix(snes->dm, &J);}
646: DMCreateMatrix(snes->dm, &B);
647: SNESSetJacobian(snes, J ? J : B, B, NULL, NULL);
648: MatDestroy(&J);
649: MatDestroy(&B);
650: }
651: {
652: KSP ksp;
653: SNESGetKSP(snes,&ksp);
654: KSPSetComputeOperators(ksp,KSPComputeOperators_SNES,snes);
655: DMCoarsenHookAdd(snes->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,snes);
656: }
657: return(0);
658: }
660: /*@C
661: SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
663: Collective on SNES
665: Input Parameters:
666: + snes - SNES object you wish to monitor
667: . name - the monitor type one is seeking
668: . help - message indicating what monitoring is done
669: . manual - manual page for the monitor
670: . monitor - the monitor function
671: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the SNES or PetscViewer objects
673: Level: developer
675: .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
676: PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
677: PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
678: PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
679: PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
680: PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
681: PetscOptionsFList(), PetscOptionsEList()
682: @*/
683: PetscErrorCode SNESMonitorSetFromOptions(SNES snes,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(SNES,PetscInt,PetscReal,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(SNES,PetscViewerAndFormat*))
684: {
685: PetscErrorCode ierr;
686: PetscViewer viewer;
687: PetscViewerFormat format;
688: PetscBool flg;
691: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,name,&viewer,&format,&flg);
692: if (flg) {
693: PetscViewerAndFormat *vf;
694: PetscViewerAndFormatCreate(viewer,format,&vf);
695: PetscObjectDereference((PetscObject)viewer);
696: if (monitorsetup) {
697: (*monitorsetup)(snes,vf);
698: }
699: SNESMonitorSet(snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);
700: }
701: return(0);
702: }
704: /*@
705: SNESSetFromOptions - Sets various SNES and KSP parameters from user options.
707: Collective on SNES
709: Input Parameter:
710: . snes - the SNES context
712: Options Database Keys:
713: + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, SNESType for complete list
714: . -snes_stol - convergence tolerance in terms of the norm
715: of the change in the solution between steps
716: . -snes_atol <abstol> - absolute tolerance of residual norm
717: . -snes_rtol <rtol> - relative decrease in tolerance norm from initial
718: . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
719: . -snes_force_iteration <force> - force SNESSolve() to take at least one iteration
720: . -snes_max_it <max_it> - maximum number of iterations
721: . -snes_max_funcs <max_funcs> - maximum number of function evaluations
722: . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
723: . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
724: . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild)
725: . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild)
726: . -snes_trtol <trtol> - trust region tolerance
727: . -snes_no_convergence_test - skip convergence test in nonlinear
728: solver; hence iterations will continue until max_it
729: or some other criterion is reached. Saves expense
730: of convergence test
731: . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout
732: . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
733: . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration
734: . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
735: . -snes_monitor_lg_residualnorm - plots residual norm at each iteration
736: . -snes_monitor_lg_range - plots residual norm at each iteration
737: . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
738: . -snes_fd_color - use finite differences with coloring to compute Jacobian
739: . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration
740: - -snes_converged_reason - print the reason for convergence/divergence after each solve
742: Options Database for Eisenstat-Walker method:
743: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
744: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
745: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
746: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
747: . -snes_ksp_ew_gamma <gamma> - Sets gamma
748: . -snes_ksp_ew_alpha <alpha> - Sets alpha
749: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
750: - -snes_ksp_ew_threshold <threshold> - Sets threshold
752: Notes:
753: To see all options, run your program with the -help option or consult
754: Users-Manual: ch_snes
756: Level: beginner
758: .keywords: SNES, nonlinear, set, options, database
760: .seealso: SNESSetOptionsPrefix()
761: @*/
762: PetscErrorCode SNESSetFromOptions(SNES snes)
763: {
764: PetscBool flg,pcset,persist,set;
765: PetscInt i,indx,lag,grids;
766: const char *deft = SNESNEWTONLS;
767: const char *convtests[] = {"default","skip"};
768: SNESKSPEW *kctx = NULL;
769: char type[256], monfilename[PETSC_MAX_PATH_LEN];
771: PCSide pcside;
772: const char *optionsprefix;
776: SNESRegisterAll();
777: PetscObjectOptionsBegin((PetscObject)snes);
778: if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
779: PetscOptionsFList("-snes_type","Nonlinear solver method","SNESSetType",SNESList,deft,type,256,&flg);
780: if (flg) {
781: SNESSetType(snes,type);
782: } else if (!((PetscObject)snes)->type_name) {
783: SNESSetType(snes,deft);
784: }
785: PetscOptionsReal("-snes_stol","Stop if step length less than","SNESSetTolerances",snes->stol,&snes->stol,NULL);
786: PetscOptionsReal("-snes_atol","Stop if function norm less than","SNESSetTolerances",snes->abstol,&snes->abstol,NULL);
788: PetscOptionsReal("-snes_rtol","Stop if decrease in function norm less than","SNESSetTolerances",snes->rtol,&snes->rtol,NULL);
789: PetscOptionsReal("-snes_divergence_tolerance","Stop if residual norm increases by this factor","SNESSetDivergenceTolerance",snes->divtol,&snes->divtol,NULL);
790: PetscOptionsInt("-snes_max_it","Maximum iterations","SNESSetTolerances",snes->max_its,&snes->max_its,NULL);
791: PetscOptionsInt("-snes_max_funcs","Maximum function evaluations","SNESSetTolerances",snes->max_funcs,&snes->max_funcs,NULL);
792: PetscOptionsInt("-snes_max_fail","Maximum nonlinear step failures","SNESSetMaxNonlinearStepFailures",snes->maxFailures,&snes->maxFailures,NULL);
793: PetscOptionsInt("-snes_max_linear_solve_fail","Maximum failures in linear solves allowed","SNESSetMaxLinearSolveFailures",snes->maxLinearSolveFailures,&snes->maxLinearSolveFailures,NULL);
794: PetscOptionsBool("-snes_error_if_not_converged","Generate error if solver does not converge","SNESSetErrorIfNotConverged",snes->errorifnotconverged,&snes->errorifnotconverged,NULL);
795: PetscOptionsBool("-snes_force_iteration","Force SNESSolve() to take at least one iteration","SNESSetForceIteration",snes->forceiteration,&snes->forceiteration,NULL);
797: PetscOptionsInt("-snes_lag_preconditioner","How often to rebuild preconditioner","SNESSetLagPreconditioner",snes->lagpreconditioner,&lag,&flg);
798: if (flg) {
799: SNESSetLagPreconditioner(snes,lag);
800: }
801: PetscOptionsBool("-snes_lag_preconditioner_persists","Preconditioner lagging through multiple solves","SNESSetLagPreconditionerPersists",snes->lagjac_persist,&persist,&flg);
802: if (flg) {
803: SNESSetLagPreconditionerPersists(snes,persist);
804: }
805: PetscOptionsInt("-snes_lag_jacobian","How often to rebuild Jacobian","SNESSetLagJacobian",snes->lagjacobian,&lag,&flg);
806: if (flg) {
807: SNESSetLagJacobian(snes,lag);
808: }
809: PetscOptionsBool("-snes_lag_jacobian_persists","Jacobian lagging through multiple solves","SNESSetLagJacobianPersists",snes->lagjac_persist,&persist,&flg);
810: if (flg) {
811: SNESSetLagJacobianPersists(snes,persist);
812: }
814: PetscOptionsInt("-snes_grid_sequence","Use grid sequencing to generate initial guess","SNESSetGridSequence",snes->gridsequence,&grids,&flg);
815: if (flg) {
816: SNESSetGridSequence(snes,grids);
817: }
819: PetscOptionsEList("-snes_convergence_test","Convergence test","SNESSetConvergenceTest",convtests,2,"default",&indx,&flg);
820: if (flg) {
821: switch (indx) {
822: case 0: SNESSetConvergenceTest(snes,SNESConvergedDefault,NULL,NULL); break;
823: case 1: SNESSetConvergenceTest(snes,SNESConvergedSkip,NULL,NULL); break;
824: }
825: }
827: PetscOptionsEList("-snes_norm_schedule","SNES Norm schedule","SNESSetNormSchedule",SNESNormSchedules,5,"function",&indx,&flg);
828: if (flg) { SNESSetNormSchedule(snes,(SNESNormSchedule)indx); }
830: PetscOptionsEList("-snes_function_type","SNES Norm schedule","SNESSetFunctionType",SNESFunctionTypes,2,"unpreconditioned",&indx,&flg);
831: if (flg) { SNESSetFunctionType(snes,(SNESFunctionType)indx); }
833: kctx = (SNESKSPEW*)snes->kspconvctx;
835: PetscOptionsBool("-snes_ksp_ew","Use Eisentat-Walker linear system convergence test","SNESKSPSetUseEW",snes->ksp_ewconv,&snes->ksp_ewconv,NULL);
837: PetscOptionsInt("-snes_ksp_ew_version","Version 1, 2 or 3","SNESKSPSetParametersEW",kctx->version,&kctx->version,NULL);
838: PetscOptionsReal("-snes_ksp_ew_rtol0","0 <= rtol0 < 1","SNESKSPSetParametersEW",kctx->rtol_0,&kctx->rtol_0,NULL);
839: PetscOptionsReal("-snes_ksp_ew_rtolmax","0 <= rtolmax < 1","SNESKSPSetParametersEW",kctx->rtol_max,&kctx->rtol_max,NULL);
840: PetscOptionsReal("-snes_ksp_ew_gamma","0 <= gamma <= 1","SNESKSPSetParametersEW",kctx->gamma,&kctx->gamma,NULL);
841: PetscOptionsReal("-snes_ksp_ew_alpha","1 < alpha <= 2","SNESKSPSetParametersEW",kctx->alpha,&kctx->alpha,NULL);
842: PetscOptionsReal("-snes_ksp_ew_alpha2","alpha2","SNESKSPSetParametersEW",kctx->alpha2,&kctx->alpha2,NULL);
843: PetscOptionsReal("-snes_ksp_ew_threshold","0 < threshold < 1","SNESKSPSetParametersEW",kctx->threshold,&kctx->threshold,NULL);
845: flg = PETSC_FALSE;
846: PetscOptionsBool("-snes_monitor_cancel","Remove all monitors","SNESMonitorCancel",flg,&flg,&set);
847: if (set && flg) {SNESMonitorCancel(snes);}
849: SNESMonitorSetFromOptions(snes,"-snes_monitor","Monitor norm of function","SNESMonitorDefault",SNESMonitorDefault,NULL);
850: SNESMonitorSetFromOptions(snes,"-snes_monitor_short","Monitor norm of function with fewer digits","SNESMonitorDefaultShort",SNESMonitorDefaultShort,NULL);
851: SNESMonitorSetFromOptions(snes,"-snes_monitor_range","Monitor range of elements of function","SNESMonitorRange",SNESMonitorRange,NULL);
853: SNESMonitorSetFromOptions(snes,"-snes_monitor_ratio","Monitor ratios of the norm of function for consecutive steps","SNESMonitorRatio",SNESMonitorRatio,SNESMonitorRatioSetUp);
854: SNESMonitorSetFromOptions(snes,"-snes_monitor_field","Monitor norm of function (split into fields)","SNESMonitorDefaultField",SNESMonitorDefaultField,NULL);
855: SNESMonitorSetFromOptions(snes,"-snes_monitor_solution","View solution at each iteration","SNESMonitorSolution",SNESMonitorSolution,NULL);
856: SNESMonitorSetFromOptions(snes,"-snes_monitor_solution_update","View correction at each iteration","SNESMonitorSolutionUpdate",SNESMonitorSolutionUpdate,NULL);
857: SNESMonitorSetFromOptions(snes,"-snes_monitor_residual","View residual at each iteration","SNESMonitorResidual",SNESMonitorResidual,NULL);
858: SNESMonitorSetFromOptions(snes,"-snes_monitor_jacupdate_spectrum","Print the change in the spectrum of the Jacobian","SNESMonitorJacUpdateSpectrum",SNESMonitorJacUpdateSpectrum,NULL);
859: SNESMonitorSetFromOptions(snes,"-snes_monitor_fields","Monitor norm of function per field","SNESMonitorSet",SNESMonitorFields,NULL);
861: PetscOptionsString("-snes_monitor_python","Use Python function","SNESMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);
862: if (flg) {PetscPythonMonitorSet((PetscObject)snes,monfilename);}
865: flg = PETSC_FALSE;
866: PetscOptionsBool("-snes_monitor_lg_residualnorm","Plot function norm at each iteration","SNESMonitorLGResidualNorm",flg,&flg,NULL);
867: if (flg) {
868: PetscDrawLG ctx;
870: SNESMonitorLGCreate(PetscObjectComm((PetscObject)snes),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&ctx);
871: SNESMonitorSet(snes,SNESMonitorLGResidualNorm,ctx,(PetscErrorCode (*)(void**))PetscDrawLGDestroy);
872: }
873: flg = PETSC_FALSE;
874: PetscOptionsBool("-snes_monitor_lg_range","Plot function range at each iteration","SNESMonitorLGRange",flg,&flg,NULL);
875: if (flg) {
876: PetscViewer ctx;
878: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&ctx);
879: SNESMonitorSet(snes,SNESMonitorLGRange,ctx,(PetscErrorCode (*)(void**))PetscViewerDestroy);
880: }
884: flg = PETSC_FALSE;
885: PetscOptionsBool("-snes_fd","Use finite differences (slow) to compute Jacobian","SNESComputeJacobianDefault",flg,&flg,NULL);
886: if (flg) {
887: void *functx;
888: DM dm;
889: DMSNES sdm;
890: SNESGetDM(snes,&dm);
891: DMGetDMSNES(dm,&sdm);
892: sdm->jacobianctx = NULL;
893: SNESGetFunction(snes,NULL,NULL,&functx);
894: SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESComputeJacobianDefault,functx);
895: PetscInfo(snes,"Setting default finite difference Jacobian matrix\n");
896: }
898: flg = PETSC_FALSE;
899: PetscOptionsBool("-snes_fd_function","Use finite differences (slow) to compute function from user objective","SNESObjectiveComputeFunctionDefaultFD",flg,&flg,NULL);
900: if (flg) {
901: SNESSetFunction(snes,NULL,SNESObjectiveComputeFunctionDefaultFD,NULL);
902: }
904: flg = PETSC_FALSE;
905: PetscOptionsBool("-snes_fd_color","Use finite differences with coloring to compute Jacobian","SNESComputeJacobianDefaultColor",flg,&flg,NULL);
906: if (flg) {
907: DM dm;
908: DMSNES sdm;
909: SNESGetDM(snes,&dm);
910: DMGetDMSNES(dm,&sdm);
911: sdm->jacobianctx = NULL;
912: SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESComputeJacobianDefaultColor,0);
913: PetscInfo(snes,"Setting default finite difference coloring Jacobian matrix\n");
914: }
916: flg = PETSC_FALSE;
917: PetscOptionsBool("-snes_mf_operator","Use a Matrix-Free Jacobian with user-provided preconditioner matrix","SNESSetUseMatrixFree",PETSC_FALSE,&snes->mf_operator,&flg);
918: if (flg && snes->mf_operator) {
919: snes->mf_operator = PETSC_TRUE;
920: snes->mf = PETSC_TRUE;
921: }
922: flg = PETSC_FALSE;
923: PetscOptionsBool("-snes_mf","Use a Matrix-Free Jacobian with no preconditioner matrix","SNESSetUseMatrixFree",PETSC_FALSE,&snes->mf,&flg);
924: if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
925: PetscOptionsInt("-snes_mf_version","Matrix-Free routines version 1 or 2","None",snes->mf_version,&snes->mf_version,0);
927: flg = PETSC_FALSE;
928: SNESGetNPCSide(snes,&pcside);
929: PetscOptionsEnum("-snes_npc_side","SNES nonlinear preconditioner side","SNESSetNPCSide",PCSides,(PetscEnum)pcside,(PetscEnum*)&pcside,&flg);
930: if (flg) {SNESSetNPCSide(snes,pcside);}
932: #if defined(PETSC_HAVE_SAWS)
933: /*
934: Publish convergence information using SAWs
935: */
936: flg = PETSC_FALSE;
937: PetscOptionsBool("-snes_monitor_saws","Publish SNES progress using SAWs","SNESMonitorSet",flg,&flg,NULL);
938: if (flg) {
939: void *ctx;
940: SNESMonitorSAWsCreate(snes,&ctx);
941: SNESMonitorSet(snes,SNESMonitorSAWs,ctx,SNESMonitorSAWsDestroy);
942: }
943: #endif
944: #if defined(PETSC_HAVE_SAWS)
945: {
946: PetscBool set;
947: flg = PETSC_FALSE;
948: PetscOptionsBool("-snes_saws_block","Block for SAWs at end of SNESSolve","PetscObjectSAWsBlock",((PetscObject)snes)->amspublishblock,&flg,&set);
949: if (set) {
950: PetscObjectSAWsSetBlock((PetscObject)snes,flg);
951: }
952: }
953: #endif
955: for (i = 0; i < numberofsetfromoptions; i++) {
956: (*othersetfromoptions[i])(snes);
957: }
959: if (snes->ops->setfromoptions) {
960: (*snes->ops->setfromoptions)(PetscOptionsObject,snes);
961: }
963: /* process any options handlers added with PetscObjectAddOptionsHandler() */
964: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)snes);
965: PetscOptionsEnd();
967: if (!snes->linesearch) {
968: SNESGetLineSearch(snes, &snes->linesearch);
969: }
970: SNESLineSearchSetFromOptions(snes->linesearch);
972: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
973: KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);
974: KSPSetFromOptions(snes->ksp);
976: /* if someone has set the SNES NPC type, create it. */
977: SNESGetOptionsPrefix(snes, &optionsprefix);
978: PetscOptionsHasName(((PetscObject)snes)->options,optionsprefix, "-npc_snes_type", &pcset);
979: if (pcset && (!snes->npc)) {
980: SNESGetNPC(snes, &snes->npc);
981: }
982: return(0);
983: }
985: /*@C
986: SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
987: the nonlinear solvers.
989: Logically Collective on SNES
991: Input Parameters:
992: + snes - the SNES context
993: . compute - function to compute the context
994: - destroy - function to destroy the context
996: Level: intermediate
998: Notes:
999: This function is currently not available from Fortran.
1001: .keywords: SNES, nonlinear, set, application, context
1003: .seealso: SNESGetApplicationContext(), SNESSetComputeApplicationContext(), SNESGetApplicationContext()
1004: @*/
1005: PetscErrorCode SNESSetComputeApplicationContext(SNES snes,PetscErrorCode (*compute)(SNES,void**),PetscErrorCode (*destroy)(void**))
1006: {
1009: snes->ops->usercompute = compute;
1010: snes->ops->userdestroy = destroy;
1011: return(0);
1012: }
1014: /*@
1015: SNESSetApplicationContext - Sets the optional user-defined context for
1016: the nonlinear solvers.
1018: Logically Collective on SNES
1020: Input Parameters:
1021: + snes - the SNES context
1022: - usrP - optional user context
1024: Level: intermediate
1026: Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
1027: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1029: .keywords: SNES, nonlinear, set, application, context
1031: .seealso: SNESGetApplicationContext()
1032: @*/
1033: PetscErrorCode SNESSetApplicationContext(SNES snes,void *usrP)
1034: {
1036: KSP ksp;
1040: SNESGetKSP(snes,&ksp);
1041: KSPSetApplicationContext(ksp,usrP);
1042: snes->user = usrP;
1043: return(0);
1044: }
1046: /*@
1047: SNESGetApplicationContext - Gets the user-defined context for the
1048: nonlinear solvers.
1050: Not Collective
1052: Input Parameter:
1053: . snes - SNES context
1055: Output Parameter:
1056: . usrP - user context
1058: Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
1059: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1061: Level: intermediate
1063: .keywords: SNES, nonlinear, get, application, context
1065: .seealso: SNESSetApplicationContext()
1066: @*/
1067: PetscErrorCode SNESGetApplicationContext(SNES snes,void *usrP)
1068: {
1071: *(void**)usrP = snes->user;
1072: return(0);
1073: }
1075: /*@
1076: SNESSetUseMatrixFree - indicates that SNES should use matrix free finite difference matrix vector products internally to apply
1077: the Jacobian.
1079: Collective on SNES
1081: Input Parameters:
1082: + snes - SNES context
1083: . mf - use matrix-free for both the Amat and Pmat used by SNESSetJacobian(), both the Amat and Pmat set in SNESSetJacobian() will be ignored
1084: - mf_operator - use matrix-free only for the Amat used by SNESSetJacobian(), this means the user provided Pmat will continue to be used
1086: Options Database:
1087: + -snes_mf - use matrix free for both the mat and pmat operator
1088: - -snes_mf_operator - use matrix free only for the mat operator
1090: Level: intermediate
1092: .keywords: SNES, nonlinear, get, iteration, number,
1094: .seealso: SNESGetUseMatrixFree(), MatCreateSNESMF()
1095: @*/
1096: PetscErrorCode SNESSetUseMatrixFree(SNES snes,PetscBool mf_operator,PetscBool mf)
1097: {
1102: if (mf && !mf_operator) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"If using mf must also use mf_operator");
1103: snes->mf = mf;
1104: snes->mf_operator = mf_operator;
1105: return(0);
1106: }
1108: /*@
1109: SNESGetUseMatrixFree - indicates if the SNES uses matrix free finite difference matrix vector products to apply
1110: the Jacobian.
1112: Collective on SNES
1114: Input Parameter:
1115: . snes - SNES context
1117: Output Parameters:
1118: + mf - use matrix-free for both the Amat and Pmat used by SNESSetJacobian(), both the Amat and Pmat set in SNESSetJacobian() will be ignored
1119: - mf_operator - use matrix-free only for the Amat used by SNESSetJacobian(), this means the user provided Pmat will continue to be used
1121: Options Database:
1122: + -snes_mf - use matrix free for both the mat and pmat operator
1123: - -snes_mf_operator - use matrix free only for the mat operator
1125: Level: intermediate
1127: .keywords: SNES, nonlinear, get, iteration, number,
1129: .seealso: SNESSetUseMatrixFree(), MatCreateSNESMF()
1130: @*/
1131: PetscErrorCode SNESGetUseMatrixFree(SNES snes,PetscBool *mf_operator,PetscBool *mf)
1132: {
1135: if (mf) *mf = snes->mf;
1136: if (mf_operator) *mf_operator = snes->mf_operator;
1137: return(0);
1138: }
1140: /*@
1141: SNESGetIterationNumber - Gets the number of nonlinear iterations completed
1142: at this time.
1144: Not Collective
1146: Input Parameter:
1147: . snes - SNES context
1149: Output Parameter:
1150: . iter - iteration number
1152: Notes:
1153: For example, during the computation of iteration 2 this would return 1.
1155: This is useful for using lagged Jacobians (where one does not recompute the
1156: Jacobian at each SNES iteration). For example, the code
1157: .vb
1158: SNESGetIterationNumber(snes,&it);
1159: if (!(it % 2)) {
1160: [compute Jacobian here]
1161: }
1162: .ve
1163: can be used in your ComputeJacobian() function to cause the Jacobian to be
1164: recomputed every second SNES iteration.
1166: After the SNES solve is complete this will return the number of nonlinear iterations used.
1168: Level: intermediate
1170: .keywords: SNES, nonlinear, get, iteration, number,
1172: .seealso: SNESGetLinearSolveIterations()
1173: @*/
1174: PetscErrorCode SNESGetIterationNumber(SNES snes,PetscInt *iter)
1175: {
1179: *iter = snes->iter;
1180: return(0);
1181: }
1183: /*@
1184: SNESSetIterationNumber - Sets the current iteration number.
1186: Not Collective
1188: Input Parameter:
1189: . snes - SNES context
1190: . iter - iteration number
1192: Level: developer
1194: .keywords: SNES, nonlinear, set, iteration, number,
1196: .seealso: SNESGetLinearSolveIterations()
1197: @*/
1198: PetscErrorCode SNESSetIterationNumber(SNES snes,PetscInt iter)
1199: {
1204: PetscObjectSAWsTakeAccess((PetscObject)snes);
1205: snes->iter = iter;
1206: PetscObjectSAWsGrantAccess((PetscObject)snes);
1207: return(0);
1208: }
1210: /*@
1211: SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1212: attempted by the nonlinear solver.
1214: Not Collective
1216: Input Parameter:
1217: . snes - SNES context
1219: Output Parameter:
1220: . nfails - number of unsuccessful steps attempted
1222: Notes:
1223: This counter is reset to zero for each successive call to SNESSolve().
1225: Level: intermediate
1227: .keywords: SNES, nonlinear, get, number, unsuccessful, steps
1229: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1230: SNESSetMaxNonlinearStepFailures(), SNESGetMaxNonlinearStepFailures()
1231: @*/
1232: PetscErrorCode SNESGetNonlinearStepFailures(SNES snes,PetscInt *nfails)
1233: {
1237: *nfails = snes->numFailures;
1238: return(0);
1239: }
1241: /*@
1242: SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1243: attempted by the nonlinear solver before it gives up.
1245: Not Collective
1247: Input Parameters:
1248: + snes - SNES context
1249: - maxFails - maximum of unsuccessful steps
1251: Level: intermediate
1253: .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps
1255: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1256: SNESGetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
1257: @*/
1258: PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1259: {
1262: snes->maxFailures = maxFails;
1263: return(0);
1264: }
1266: /*@
1267: SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1268: attempted by the nonlinear solver before it gives up.
1270: Not Collective
1272: Input Parameter:
1273: . snes - SNES context
1275: Output Parameter:
1276: . maxFails - maximum of unsuccessful steps
1278: Level: intermediate
1280: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
1282: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(),
1283: SNESSetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures()
1285: @*/
1286: PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1287: {
1291: *maxFails = snes->maxFailures;
1292: return(0);
1293: }
1295: /*@
1296: SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1297: done by SNES.
1299: Not Collective
1301: Input Parameter:
1302: . snes - SNES context
1304: Output Parameter:
1305: . nfuncs - number of evaluations
1307: Level: intermediate
1309: Notes: Reset every time SNESSolve is called unless SNESSetCountersReset() is used.
1311: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
1313: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(), SNESSetCountersReset()
1314: @*/
1315: PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1316: {
1320: *nfuncs = snes->nfuncs;
1321: return(0);
1322: }
1324: /*@
1325: SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1326: linear solvers.
1328: Not Collective
1330: Input Parameter:
1331: . snes - SNES context
1333: Output Parameter:
1334: . nfails - number of failed solves
1336: Level: intermediate
1338: Options Database Keys:
1339: . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
1341: Notes:
1342: This counter is reset to zero for each successive call to SNESSolve().
1344: .keywords: SNES, nonlinear, get, number, unsuccessful, steps
1346: .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures()
1347: @*/
1348: PetscErrorCode SNESGetLinearSolveFailures(SNES snes,PetscInt *nfails)
1349: {
1353: *nfails = snes->numLinearSolveFailures;
1354: return(0);
1355: }
1357: /*@
1358: SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1359: allowed before SNES returns with a diverged reason of SNES_DIVERGED_LINEAR_SOLVE
1361: Logically Collective on SNES
1363: Input Parameters:
1364: + snes - SNES context
1365: - maxFails - maximum allowed linear solve failures
1367: Level: intermediate
1369: Options Database Keys:
1370: . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
1372: Notes: By default this is 0; that is SNES returns on the first failed linear solve
1374: .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps
1376: .seealso: SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations()
1377: @*/
1378: PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1379: {
1383: snes->maxLinearSolveFailures = maxFails;
1384: return(0);
1385: }
1387: /*@
1388: SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1389: are allowed before SNES terminates
1391: Not Collective
1393: Input Parameter:
1394: . snes - SNES context
1396: Output Parameter:
1397: . maxFails - maximum of unsuccessful solves allowed
1399: Level: intermediate
1401: Notes: By default this is 1; that is SNES returns on the first failed linear solve
1403: .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps
1405: .seealso: SNESGetLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(),
1406: @*/
1407: PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1408: {
1412: *maxFails = snes->maxLinearSolveFailures;
1413: return(0);
1414: }
1416: /*@
1417: SNESGetLinearSolveIterations - Gets the total number of linear iterations
1418: used by the nonlinear solver.
1420: Not Collective
1422: Input Parameter:
1423: . snes - SNES context
1425: Output Parameter:
1426: . lits - number of linear iterations
1428: Notes:
1429: This counter is reset to zero for each successive call to SNESSolve() unless SNESSetCountersReset() is used.
1431: If the linear solver fails inside the SNESSolve() the iterations for that call to the linear solver are not included. If you wish to count them
1432: then call KSPGetIterationNumber() after the failed solve.
1434: Level: intermediate
1436: .keywords: SNES, nonlinear, get, number, linear, iterations
1438: .seealso: SNESGetIterationNumber(), SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESSetCountersReset()
1439: @*/
1440: PetscErrorCode SNESGetLinearSolveIterations(SNES snes,PetscInt *lits)
1441: {
1445: *lits = snes->linear_its;
1446: return(0);
1447: }
1449: /*@
1450: SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1451: are reset every time SNESSolve() is called.
1453: Logically Collective on SNES
1455: Input Parameter:
1456: + snes - SNES context
1457: - reset - whether to reset the counters or not
1459: Notes:
1460: This defaults to PETSC_TRUE
1462: Level: developer
1464: .keywords: SNES, nonlinear, set, reset, number, linear, iterations
1466: .seealso: SNESGetNumberFunctionEvals(), SNESGetLinearSolveIterations(), SNESGetNPC()
1467: @*/
1468: PetscErrorCode SNESSetCountersReset(SNES snes,PetscBool reset)
1469: {
1473: snes->counters_reset = reset;
1474: return(0);
1475: }
1478: /*@
1479: SNESSetKSP - Sets a KSP context for the SNES object to use
1481: Not Collective, but the SNES and KSP objects must live on the same MPI_Comm
1483: Input Parameters:
1484: + snes - the SNES context
1485: - ksp - the KSP context
1487: Notes:
1488: The SNES object already has its KSP object, you can obtain with SNESGetKSP()
1489: so this routine is rarely needed.
1491: The KSP object that is already in the SNES object has its reference count
1492: decreased by one.
1494: Level: developer
1496: .keywords: SNES, nonlinear, get, KSP, context
1498: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
1499: @*/
1500: PetscErrorCode SNESSetKSP(SNES snes,KSP ksp)
1501: {
1508: PetscObjectReference((PetscObject)ksp);
1509: if (snes->ksp) {PetscObjectDereference((PetscObject)snes->ksp);}
1510: snes->ksp = ksp;
1511: return(0);
1512: }
1514: /* -----------------------------------------------------------*/
1515: /*@
1516: SNESCreate - Creates a nonlinear solver context.
1518: Collective on MPI_Comm
1520: Input Parameters:
1521: . comm - MPI communicator
1523: Output Parameter:
1524: . outsnes - the new SNES context
1526: Options Database Keys:
1527: + -snes_mf - Activates default matrix-free Jacobian-vector products,
1528: and no preconditioning matrix
1529: . -snes_mf_operator - Activates default matrix-free Jacobian-vector
1530: products, and a user-provided preconditioning matrix
1531: as set by SNESSetJacobian()
1532: - -snes_fd - Uses (slow!) finite differences to compute Jacobian
1534: Level: beginner
1536: Developer Notes: SNES always creates a KSP object even though many SNES methods do not use it. This is
1537: unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1538: particular method does use KSP and regulates if the information about the KSP is printed
1539: in SNESView(). TSSetFromOptions() does call SNESSetFromOptions() which can lead to users being confused
1540: by help messages about meaningless SNES options.
1542: SNES always creates the snes->kspconvctx even though it is used by only one type. This should
1543: be fixed.
1545: .keywords: SNES, nonlinear, create, context
1547: .seealso: SNESSolve(), SNESDestroy(), SNES, SNESSetLagPreconditioner()
1549: @*/
1550: PetscErrorCode SNESCreate(MPI_Comm comm,SNES *outsnes)
1551: {
1553: SNES snes;
1554: SNESKSPEW *kctx;
1558: *outsnes = NULL;
1559: SNESInitializePackage();
1561: PetscHeaderCreate(snes,SNES_CLASSID,"SNES","Nonlinear solver","SNES",comm,SNESDestroy,SNESView);
1563: snes->ops->converged = SNESConvergedDefault;
1564: snes->usesksp = PETSC_TRUE;
1565: snes->tolerancesset = PETSC_FALSE;
1566: snes->max_its = 50;
1567: snes->max_funcs = 10000;
1568: snes->norm = 0.0;
1569: snes->normschedule = SNES_NORM_ALWAYS;
1570: snes->functype = SNES_FUNCTION_DEFAULT;
1571: #if defined(PETSC_USE_REAL_SINGLE)
1572: snes->rtol = 1.e-5;
1573: #else
1574: snes->rtol = 1.e-8;
1575: #endif
1576: snes->ttol = 0.0;
1577: #if defined(PETSC_USE_REAL_SINGLE)
1578: snes->abstol = 1.e-25;
1579: #else
1580: snes->abstol = 1.e-50;
1581: #endif
1582: #if defined(PETSC_USE_REAL_SINGLE)
1583: snes->stol = 1.e-5;
1584: #else
1585: snes->stol = 1.e-8;
1586: #endif
1587: #if defined(PETSC_USE_REAL_SINGLE)
1588: snes->deltatol = 1.e-6;
1589: #else
1590: snes->deltatol = 1.e-12;
1591: #endif
1592: snes->divtol = 1.e4;
1593: snes->rnorm0 = 0;
1594: snes->nfuncs = 0;
1595: snes->numFailures = 0;
1596: snes->maxFailures = 1;
1597: snes->linear_its = 0;
1598: snes->lagjacobian = 1;
1599: snes->jac_iter = 0;
1600: snes->lagjac_persist = PETSC_FALSE;
1601: snes->lagpreconditioner = 1;
1602: snes->pre_iter = 0;
1603: snes->lagpre_persist = PETSC_FALSE;
1604: snes->numbermonitors = 0;
1605: snes->data = 0;
1606: snes->setupcalled = PETSC_FALSE;
1607: snes->ksp_ewconv = PETSC_FALSE;
1608: snes->nwork = 0;
1609: snes->work = 0;
1610: snes->nvwork = 0;
1611: snes->vwork = 0;
1612: snes->conv_hist_len = 0;
1613: snes->conv_hist_max = 0;
1614: snes->conv_hist = NULL;
1615: snes->conv_hist_its = NULL;
1616: snes->conv_hist_reset = PETSC_TRUE;
1617: snes->counters_reset = PETSC_TRUE;
1618: snes->vec_func_init_set = PETSC_FALSE;
1619: snes->reason = SNES_CONVERGED_ITERATING;
1620: snes->npcside = PC_RIGHT;
1622: snes->mf = PETSC_FALSE;
1623: snes->mf_operator = PETSC_FALSE;
1624: snes->mf_version = 1;
1626: snes->numLinearSolveFailures = 0;
1627: snes->maxLinearSolveFailures = 1;
1629: snes->vizerotolerance = 1.e-8;
1631: /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
1632: snes->alwayscomputesfinalresidual = PETSC_FALSE;
1634: /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
1635: PetscNewLog(snes,&kctx);
1637: snes->kspconvctx = (void*)kctx;
1638: kctx->version = 2;
1639: kctx->rtol_0 = .3; /* Eisenstat and Walker suggest rtol_0=.5, but
1640: this was too large for some test cases */
1641: kctx->rtol_last = 0.0;
1642: kctx->rtol_max = .9;
1643: kctx->gamma = 1.0;
1644: kctx->alpha = .5*(1.0 + PetscSqrtReal(5.0));
1645: kctx->alpha2 = kctx->alpha;
1646: kctx->threshold = .1;
1647: kctx->lresid_last = 0.0;
1648: kctx->norm_last = 0.0;
1650: *outsnes = snes;
1651: return(0);
1652: }
1654: /*MC
1655: SNESFunction - Functional form used to convey the nonlinear function to be solved by SNES
1657: Synopsis:
1658: #include "petscsnes.h"
1659: PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
1661: Input Parameters:
1662: + snes - the SNES context
1663: . x - state at which to evaluate residual
1664: - ctx - optional user-defined function context, passed in with SNESSetFunction()
1666: Output Parameter:
1667: . f - vector to put residual (function value)
1669: Level: intermediate
1671: .seealso: SNESSetFunction(), SNESGetFunction()
1672: M*/
1674: /*@C
1675: SNESSetFunction - Sets the function evaluation routine and function
1676: vector for use by the SNES routines in solving systems of nonlinear
1677: equations.
1679: Logically Collective on SNES
1681: Input Parameters:
1682: + snes - the SNES context
1683: . r - vector to store function value
1684: . f - function evaluation routine; see SNESFunction for calling sequence details
1685: - ctx - [optional] user-defined context for private data for the
1686: function evaluation routine (may be NULL)
1688: Notes:
1689: The Newton-like methods typically solve linear systems of the form
1690: $ f'(x) x = -f(x),
1691: where f'(x) denotes the Jacobian matrix and f(x) is the function.
1693: Level: beginner
1695: .keywords: SNES, nonlinear, set, function
1697: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetPicard(), SNESFunction
1698: @*/
1699: PetscErrorCode SNESSetFunction(SNES snes,Vec r,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
1700: {
1702: DM dm;
1706: if (r) {
1709: PetscObjectReference((PetscObject)r);
1710: VecDestroy(&snes->vec_func);
1712: snes->vec_func = r;
1713: }
1714: SNESGetDM(snes,&dm);
1715: DMSNESSetFunction(dm,f,ctx);
1716: return(0);
1717: }
1720: /*@C
1721: SNESSetInitialFunction - Sets the function vector to be used as the
1722: function norm at the initialization of the method. In some
1723: instances, the user has precomputed the function before calling
1724: SNESSolve. This function allows one to avoid a redundant call
1725: to SNESComputeFunction in that case.
1727: Logically Collective on SNES
1729: Input Parameters:
1730: + snes - the SNES context
1731: - f - vector to store function value
1733: Notes:
1734: This should not be modified during the solution procedure.
1736: This is used extensively in the SNESFAS hierarchy and in nonlinear preconditioning.
1738: Level: developer
1740: .keywords: SNES, nonlinear, set, function
1742: .seealso: SNESSetFunction(), SNESComputeFunction(), SNESSetInitialFunctionNorm()
1743: @*/
1744: PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1745: {
1747: Vec vec_func;
1753: if (snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1754: snes->vec_func_init_set = PETSC_FALSE;
1755: return(0);
1756: }
1757: SNESGetFunction(snes,&vec_func,NULL,NULL);
1758: VecCopy(f, vec_func);
1760: snes->vec_func_init_set = PETSC_TRUE;
1761: return(0);
1762: }
1764: /*@
1765: SNESSetNormSchedule - Sets the SNESNormSchedule used in covergence and monitoring
1766: of the SNES method.
1768: Logically Collective on SNES
1770: Input Parameters:
1771: + snes - the SNES context
1772: - normschedule - the frequency of norm computation
1774: Options Database Key:
1775: . -snes_norm_schedule <none, always, initialonly, finalonly, initalfinalonly>
1777: Notes:
1778: Only certain SNES methods support certain SNESNormSchedules. Most require evaluation
1779: of the nonlinear function and the taking of its norm at every iteration to
1780: even ensure convergence at all. However, methods such as custom Gauss-Seidel methods
1781: (SNESNGS) and the like do not require the norm of the function to be computed, and therfore
1782: may either be monitored for convergence or not. As these are often used as nonlinear
1783: preconditioners, monitoring the norm of their error is not a useful enterprise within
1784: their solution.
1786: Level: developer
1788: .keywords: SNES, nonlinear, set, function, norm, type
1790: .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1791: @*/
1792: PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1793: {
1796: snes->normschedule = normschedule;
1797: return(0);
1798: }
1801: /*@
1802: SNESGetNormSchedule - Gets the SNESNormSchedule used in covergence and monitoring
1803: of the SNES method.
1805: Logically Collective on SNES
1807: Input Parameters:
1808: + snes - the SNES context
1809: - normschedule - the type of the norm used
1811: Level: advanced
1813: .keywords: SNES, nonlinear, set, function, norm, type
1815: .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1816: @*/
1817: PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1818: {
1821: *normschedule = snes->normschedule;
1822: return(0);
1823: }
1826: /*@
1827: SNESSetFunctionNorm - Sets the last computed residual norm.
1829: Logically Collective on SNES
1831: Input Parameters:
1832: + snes - the SNES context
1834: - normschedule - the frequency of norm computation
1836: Level: developer
1838: .keywords: SNES, nonlinear, set, function, norm, type
1839: .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1840: @*/
1841: PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1842: {
1845: snes->norm = norm;
1846: return(0);
1847: }
1849: /*@
1850: SNESGetFunctionNorm - Gets the last computed norm of the residual
1852: Not Collective
1854: Input Parameter:
1855: . snes - the SNES context
1857: Output Parameter:
1858: . norm - the last computed residual norm
1860: Level: developer
1862: .keywords: SNES, nonlinear, set, function, norm, type
1863: .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1864: @*/
1865: PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
1866: {
1870: *norm = snes->norm;
1871: return(0);
1872: }
1874: /*@C
1875: SNESSetFunctionType - Sets the SNESNormSchedule used in covergence and monitoring
1876: of the SNES method.
1878: Logically Collective on SNES
1880: Input Parameters:
1881: + snes - the SNES context
1882: - normschedule - the frequency of norm computation
1884: Notes:
1885: Only certain SNES methods support certain SNESNormSchedules. Most require evaluation
1886: of the nonlinear function and the taking of its norm at every iteration to
1887: even ensure convergence at all. However, methods such as custom Gauss-Seidel methods
1888: (SNESNGS) and the like do not require the norm of the function to be computed, and therfore
1889: may either be monitored for convergence or not. As these are often used as nonlinear
1890: preconditioners, monitoring the norm of their error is not a useful enterprise within
1891: their solution.
1893: Level: developer
1895: .keywords: SNES, nonlinear, set, function, norm, type
1897: .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1898: @*/
1899: PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
1900: {
1903: snes->functype = type;
1904: return(0);
1905: }
1908: /*@C
1909: SNESGetFunctionType - Gets the SNESNormSchedule used in covergence and monitoring
1910: of the SNES method.
1912: Logically Collective on SNES
1914: Input Parameters:
1915: + snes - the SNES context
1916: - normschedule - the type of the norm used
1918: Level: advanced
1920: .keywords: SNES, nonlinear, set, function, norm, type
1922: .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule
1923: @*/
1924: PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
1925: {
1928: *type = snes->functype;
1929: return(0);
1930: }
1932: /*MC
1933: SNESNGSFunction - function used to convey a Gauss-Seidel sweep on the nonlinear function
1935: Synopsis:
1936: #include <petscsnes.h>
1937: $ SNESNGSFunction(SNES snes,Vec x,Vec b,void *ctx);
1939: + X - solution vector
1940: . B - RHS vector
1941: - ctx - optional user-defined Gauss-Seidel context
1943: Level: intermediate
1945: .seealso: SNESSetNGS(), SNESGetNGS()
1946: M*/
1948: /*@C
1949: SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
1950: use with composed nonlinear solvers.
1952: Input Parameters:
1953: + snes - the SNES context
1954: . f - function evaluation routine to apply Gauss-Seidel see SNESNGSFunction
1955: - ctx - [optional] user-defined context for private data for the
1956: smoother evaluation routine (may be NULL)
1958: Notes:
1959: The NGS routines are used by the composed nonlinear solver to generate
1960: a problem appropriate update to the solution, particularly FAS.
1962: Level: intermediate
1964: .keywords: SNES, nonlinear, set, Gauss-Seidel
1966: .seealso: SNESGetFunction(), SNESComputeNGS()
1967: @*/
1968: PetscErrorCode SNESSetNGS(SNES snes,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
1969: {
1971: DM dm;
1975: SNESGetDM(snes,&dm);
1976: DMSNESSetNGS(dm,f,ctx);
1977: return(0);
1978: }
1980: PETSC_EXTERN PetscErrorCode SNESPicardComputeFunction(SNES snes,Vec x,Vec f,void *ctx)
1981: {
1983: DM dm;
1984: DMSNES sdm;
1987: SNESGetDM(snes,&dm);
1988: DMGetDMSNES(dm,&sdm);
1989: /* A(x)*x - b(x) */
1990: if (sdm->ops->computepfunction) {
1991: (*sdm->ops->computepfunction)(snes,x,f,sdm->pctx);
1992: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetPicard() to provide Picard function.");
1994: if (sdm->ops->computepjacobian) {
1995: (*sdm->ops->computepjacobian)(snes,x,snes->jacobian,snes->jacobian_pre,sdm->pctx);
1996: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetPicard() to provide Picard matrix.");
1997: VecScale(f,-1.0);
1998: MatMultAdd(snes->jacobian,x,f,f);
1999: return(0);
2000: }
2002: PETSC_EXTERN PetscErrorCode SNESPicardComputeJacobian(SNES snes,Vec x1,Mat J,Mat B,void *ctx)
2003: {
2005: /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2006: return(0);
2007: }
2009: /*@C
2010: SNESSetPicard - Use SNES to solve the semilinear-system A(x) x = b(x) via a Picard type iteration (Picard linearization)
2012: Logically Collective on SNES
2014: Input Parameters:
2015: + snes - the SNES context
2016: . r - vector to store function value
2017: . b - function evaluation routine
2018: . Amat - matrix with which A(x) x - b(x) is to be computed
2019: . Pmat - matrix from which preconditioner is computed (usually the same as Amat)
2020: . J - function to compute matrix value, see SNESJacobianFunction for details on its calling sequence
2021: - ctx - [optional] user-defined context for private data for the
2022: function evaluation routine (may be NULL)
2024: Notes:
2025: 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
2026: 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.
2028: One can call SNESSetPicard() or SNESSetFunction() (and possibly SNESSetJacobian()) but cannot call both
2030: $ 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}
2031: $ Note that when an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = b(x^{n}) iteration.
2033: Run with -snes_mf_operator to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
2035: We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
2036: the direct Picard iteration A(x^n) x^{n+1} = b(x^n)
2038: 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
2039: 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
2040: different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
2042: Level: intermediate
2044: .keywords: SNES, nonlinear, set, function
2046: .seealso: SNESGetFunction(), SNESSetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESGetPicard(), SNESLineSearchPreCheckPicard(), SNESJacobianFunction
2047: @*/
2048: PetscErrorCode SNESSetPicard(SNES snes,Vec r,PetscErrorCode (*b)(SNES,Vec,Vec,void*),Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
2049: {
2051: DM dm;
2055: SNESGetDM(snes, &dm);
2056: DMSNESSetPicard(dm,b,J,ctx);
2057: SNESSetFunction(snes,r,SNESPicardComputeFunction,ctx);
2058: SNESSetJacobian(snes,Amat,Pmat,SNESPicardComputeJacobian,ctx);
2059: return(0);
2060: }
2062: /*@C
2063: SNESGetPicard - Returns the context for the Picard iteration
2065: Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet.
2067: Input Parameter:
2068: . snes - the SNES context
2070: Output Parameter:
2071: + r - the function (or NULL)
2072: . f - the function (or NULL); see SNESFunction for calling sequence details
2073: . Amat - the matrix used to defined the operation A(x) x - b(x) (or NULL)
2074: . Pmat - the matrix from which the preconditioner will be constructed (or NULL)
2075: . J - the function for matrix evaluation (or NULL); see SNESJacobianFunction for calling sequence details
2076: - ctx - the function context (or NULL)
2078: Level: advanced
2080: .keywords: SNES, nonlinear, get, function
2082: .seealso: SNESSetPicard(), SNESGetFunction(), SNESGetJacobian(), SNESGetDM(), SNESFunction, SNESJacobianFunction
2083: @*/
2084: PetscErrorCode SNESGetPicard(SNES snes,Vec *r,PetscErrorCode (**f)(SNES,Vec,Vec,void*),Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
2085: {
2087: DM dm;
2091: SNESGetFunction(snes,r,NULL,NULL);
2092: SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);
2093: SNESGetDM(snes,&dm);
2094: DMSNESGetPicard(dm,f,J,ctx);
2095: return(0);
2096: }
2098: /*@C
2099: SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the problem
2101: Logically Collective on SNES
2103: Input Parameters:
2104: + snes - the SNES context
2105: . func - function evaluation routine
2106: - ctx - [optional] user-defined context for private data for the
2107: function evaluation routine (may be NULL)
2109: Calling sequence of func:
2110: $ func (SNES snes,Vec x,void *ctx);
2112: . f - function vector
2113: - ctx - optional user-defined function context
2115: Level: intermediate
2117: .keywords: SNES, nonlinear, set, function
2119: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian()
2120: @*/
2121: PetscErrorCode SNESSetComputeInitialGuess(SNES snes,PetscErrorCode (*func)(SNES,Vec,void*),void *ctx)
2122: {
2125: if (func) snes->ops->computeinitialguess = func;
2126: if (ctx) snes->initialguessP = ctx;
2127: return(0);
2128: }
2130: /* --------------------------------------------------------------- */
2131: /*@C
2132: SNESGetRhs - Gets the vector for solving F(x) = rhs. If rhs is not set
2133: it assumes a zero right hand side.
2135: Logically Collective on SNES
2137: Input Parameter:
2138: . snes - the SNES context
2140: Output Parameter:
2141: . rhs - the right hand side vector or NULL if the right hand side vector is null
2143: Level: intermediate
2145: .keywords: SNES, nonlinear, get, function, right hand side
2147: .seealso: SNESGetSolution(), SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
2148: @*/
2149: PetscErrorCode SNESGetRhs(SNES snes,Vec *rhs)
2150: {
2154: *rhs = snes->vec_rhs;
2155: return(0);
2156: }
2158: /*@
2159: SNESComputeFunction - Calls the function that has been set with SNESSetFunction().
2161: Collective on SNES
2163: Input Parameters:
2164: + snes - the SNES context
2165: - x - input vector
2167: Output Parameter:
2168: . y - function vector, as set by SNESSetFunction()
2170: Notes:
2171: SNESComputeFunction() is typically used within nonlinear solvers
2172: implementations, so most users would not generally call this routine
2173: themselves.
2175: Level: developer
2177: .keywords: SNES, nonlinear, compute, function
2179: .seealso: SNESSetFunction(), SNESGetFunction()
2180: @*/
2181: PetscErrorCode SNESComputeFunction(SNES snes,Vec x,Vec y)
2182: {
2184: DM dm;
2185: DMSNES sdm;
2193: VecValidValues(x,2,PETSC_TRUE);
2195: SNESGetDM(snes,&dm);
2196: DMGetDMSNES(dm,&sdm);
2197: if (sdm->ops->computefunction) {
2198: if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) {
2199: PetscLogEventBegin(SNES_FunctionEval,snes,x,y,0);
2200: }
2201: VecLockPush(x);
2202: PetscStackPush("SNES user function");
2203: (*sdm->ops->computefunction)(snes,x,y,sdm->functionctx);
2204: PetscStackPop;
2205: VecLockPop(x);
2206: if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) {
2207: PetscLogEventEnd(SNES_FunctionEval,snes,x,y,0);
2208: }
2209: } else if (snes->vec_rhs) {
2210: MatMult(snes->jacobian, x, y);
2211: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve().");
2212: if (snes->vec_rhs) {
2213: VecAXPY(y,-1.0,snes->vec_rhs);
2214: }
2215: snes->nfuncs++;
2216: /*
2217: domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2218: propagate the value to all processes
2219: */
2220: if (snes->domainerror) {
2221: VecSetInf(y);
2222: }
2223: return(0);
2224: }
2226: /*@
2227: SNESComputeNGS - Calls the Gauss-Seidel function that has been set with SNESSetNGS().
2229: Collective on SNES
2231: Input Parameters:
2232: + snes - the SNES context
2233: . x - input vector
2234: - b - rhs vector
2236: Output Parameter:
2237: . x - new solution vector
2239: Notes:
2240: SNESComputeNGS() is typically used within composed nonlinear solver
2241: implementations, so most users would not generally call this routine
2242: themselves.
2244: Level: developer
2246: .keywords: SNES, nonlinear, compute, function
2248: .seealso: SNESSetNGS(), SNESComputeFunction()
2249: @*/
2250: PetscErrorCode SNESComputeNGS(SNES snes,Vec b,Vec x)
2251: {
2253: DM dm;
2254: DMSNES sdm;
2262: if (b) {VecValidValues(b,2,PETSC_TRUE);}
2263: PetscLogEventBegin(SNES_NGSEval,snes,x,b,0);
2264: SNESGetDM(snes,&dm);
2265: DMGetDMSNES(dm,&sdm);
2266: if (sdm->ops->computegs) {
2267: if (b) {VecLockPush(b);}
2268: PetscStackPush("SNES user NGS");
2269: (*sdm->ops->computegs)(snes,x,b,sdm->gsctx);
2270: PetscStackPop;
2271: if (b) {VecLockPop(b);}
2272: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
2273: PetscLogEventEnd(SNES_NGSEval,snes,x,b,0);
2274: return(0);
2275: }
2277: PetscErrorCode SNESTestJacobian(SNES snes)
2278: {
2279: Mat A = snes->jacobian,B,C;
2280: Vec x = snes->vec_sol,f = snes->vec_func;
2282: PetscReal nrm,gnorm;
2283: PetscReal threshold = 1.e-5;
2284: PetscInt m,n,M,N;
2285: void *functx;
2286: PetscBool complete_print = PETSC_FALSE,threshold_print = PETSC_FALSE,test = PETSC_FALSE;
2287: PetscViewer viewer;
2288: MPI_Comm comm;
2289: PetscInt tabs;
2292: PetscObjectOptionsBegin((PetscObject)snes);
2293: PetscOptionsBool("-snes_test_jacobian","Compare hand-coded and finite difference Jacobians","None",test,&test,NULL);
2294: PetscOptionsBool("-snes_test_jacobian_display","Display difference between hand-coded and finite difference Jacobians","None",complete_print,&complete_print,NULL);
2295: PetscOptionsReal("-snes_test_jacobian_display_threshold", "Display difference between hand-coded and finite difference Jacobians which exceed input threshold", "None", threshold, &threshold, &threshold_print);
2296: PetscOptionsEnd();
2297: if (!test) return(0);
2299: PetscObjectGetComm((PetscObject)snes,&comm);
2300: PetscViewerASCIIGetStdout(comm,&viewer);
2301: PetscViewerASCIIGetTab(viewer, &tabs);
2302: PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel);
2303: if (A != snes->jacobian_pre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot test with alternative preconditioner");
2305: PetscViewerASCIIPrintf(viewer," Testing hand-coded Jacobian, if the ratio is\n");
2306: PetscViewerASCIIPrintf(viewer," O(1.e-8), the hand-coded Jacobian is probably correct.\n");
2307: if (!complete_print) {
2308: PetscViewerASCIIPrintf(viewer," Run with -snes_test_jacobian_display to show difference\n");
2309: PetscViewerASCIIPrintf(viewer," of hand-coded and finite difference Jacobian.\n");
2310: PetscViewerASCIIPrintf(viewer," Run with -snes_test_jacobian_display_threshold to show difference\n");
2311: PetscViewerASCIIPrintf(viewer," of hand-coded and finite difference Jacobian entries great than threshold.\n");
2312: }
2314: /* evaluate the function at this point because SNESComputeJacobianDefaultColor() assumes that the function has been evaluated and put into snes->vec_func */
2315: SNESComputeFunction(snes,x,f);
2316: A = snes->jacobian_pre;
2318: MatCreate(PetscObjectComm((PetscObject)A),&B);
2319: MatGetSize(A,&M,&N);
2320: MatGetLocalSize(A,&m,&n);
2321: MatSetSizes(B,m,n,M,N);
2322: MatSetType(B,((PetscObject)A)->type_name);
2323: MatSetUp(B);
2324: MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);
2326: SNESGetFunction(snes,NULL,NULL,&functx);
2327: SNESComputeJacobianDefault(snes,x,B,B,functx);
2328: if (complete_print) {
2329: PetscViewerASCIIPrintf(viewer," Finite difference Jacobian\n");
2330: MatView(B,viewer);
2331: }
2332: /* compare */
2333: MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);
2334: MatNorm(B,NORM_FROBENIUS,&nrm);
2335: MatNorm(A,NORM_FROBENIUS,&gnorm);
2336: if (complete_print) {
2337: PetscViewerASCIIPrintf(viewer,"Hand-coded Jacobian\n");
2338: PetscObjectGetComm((PetscObject)B,&comm);
2339: PetscViewerASCIIGetStdout(comm,&viewer);
2340: MatView(A,viewer);
2341: PetscViewerASCIIPrintf(viewer," Hand-coded minus finite-difference Jacobian\n");
2342: MatView(B,viewer);
2343: }
2345: if (threshold_print) {
2346: PetscInt Istart, Iend, *ccols, bncols, cncols, j, row;
2347: PetscScalar *cvals;
2348: const PetscInt *bcols;
2349: const PetscScalar *bvals;
2351: MatCreate(PetscObjectComm((PetscObject)A),&C);
2352: MatSetSizes(C,m,n,M,N);
2353: MatSetType(C,((PetscObject)A)->type_name);
2354: MatSetUp(C);
2355: MatSetOption(C,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);
2356: MatGetOwnershipRange(B,&Istart,&Iend);
2358: for (row = Istart; row < Iend; row++) {
2359: MatGetRow(B,row,&bncols,&bcols,&bvals);
2360: PetscMalloc2(bncols,&ccols,bncols,&cvals);
2361: for (j = 0, cncols = 0; j < bncols; j++) {
2362: if (PetscAbsScalar(bvals[j]) > threshold) {
2363: ccols[cncols] = bcols[j];
2364: cvals[cncols] = bvals[j];
2365: cncols += 1;
2366: }
2367: }
2368: if(cncols) {
2369: MatSetValues(C,1,&row,cncols,ccols,cvals,INSERT_VALUES);
2370: }
2371: MatRestoreRow(B,row,&bncols,&bcols,&bvals);
2372: PetscFree2(ccols,cvals);
2373: }
2374: MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
2375: MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
2377: PetscViewerASCIIPrintf(viewer," Entries where difference is over threshold\n");
2378: MatView(C,viewer);
2379: MatDestroy(&C);
2380: }
2382: if (!gnorm) gnorm = 1; /* just in case */
2383: PetscViewerASCIIPrintf(viewer,"||J - Jfd||_F/||J||_F %g, ||J - Jfd||_F %g\n",(double)(nrm/gnorm),(double)nrm);
2384: MatDestroy(&B);
2385: PetscViewerASCIISetTab(viewer,tabs);
2386: return(0);
2387: }
2389: /*@
2390: SNESComputeJacobian - Computes the Jacobian matrix that has been set with SNESSetJacobian().
2392: Collective on SNES and Mat
2394: Input Parameters:
2395: + snes - the SNES context
2396: - x - input vector
2398: Output Parameters:
2399: + A - Jacobian matrix
2400: - B - optional preconditioning matrix
2402: Options Database Keys:
2403: + -snes_lag_preconditioner <lag>
2404: . -snes_lag_jacobian <lag>
2405: . -snes_test_jacobian - compare the user provided Jacobian with one compute via finite differences to check for errors
2406: . -snes_test_jacobian_display - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian
2407: . -snes_test_jacobian_display_threshold <numerical value> - display entries in the difference between the user provided Jacobian and finite difference Jacobian that are greater than a certain value to help users detect errors
2408: . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2409: . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2410: . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
2411: . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix
2412: . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference
2413: . -snes_compare_coloring_display - Compute the finite differece Jacobian using coloring and display verbose differences
2414: . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold
2415: . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold
2416: . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold
2417: . -snes_compare_coloring_draw - Compute the finite differece Jacobian using coloring and draw differences
2418: - -snes_compare_coloring_draw_contour - Compute the finite differece Jacobian using coloring and show contours of matrices and differences
2421: Notes:
2422: Most users should not need to explicitly call this routine, as it
2423: is used internally within the nonlinear solvers.
2425: Developer Notes: This has duplicative ways of checking the accuracy of the user provided Jacobian (see the options above). This is for historical reasons, the routine SNESTestJacobian() use to used
2426: for with the SNESType of test that has been removed.
2428: Level: developer
2430: .keywords: SNES, compute, Jacobian, matrix
2432: .seealso: SNESSetJacobian(), KSPSetOperators(), MatStructure, SNESSetLagPreconditioner(), SNESSetLagJacobian()
2433: @*/
2434: PetscErrorCode SNESComputeJacobian(SNES snes,Vec X,Mat A,Mat B)
2435: {
2437: PetscBool flag;
2438: DM dm;
2439: DMSNES sdm;
2440: KSP ksp;
2446: VecValidValues(X,2,PETSC_TRUE);
2447: SNESGetDM(snes,&dm);
2448: DMGetDMSNES(dm,&sdm);
2450: if (!sdm->ops->computejacobian) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_USER,"Must call SNESSetJacobian(), DMSNESSetJacobian(), DMDASNESSetJacobianLocal(), etc");
2452: /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
2454: if (snes->lagjacobian == -2) {
2455: snes->lagjacobian = -1;
2457: PetscInfo(snes,"Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n");
2458: } else if (snes->lagjacobian == -1) {
2459: PetscInfo(snes,"Reusing Jacobian/preconditioner because lag is -1\n");
2460: PetscObjectTypeCompare((PetscObject)A,MATMFFD,&flag);
2461: if (flag) {
2462: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
2463: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
2464: }
2465: return(0);
2466: } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
2467: PetscInfo2(snes,"Reusing Jacobian/preconditioner because lag is %D and SNES iteration is %D\n",snes->lagjacobian,snes->iter);
2468: PetscObjectTypeCompare((PetscObject)A,MATMFFD,&flag);
2469: if (flag) {
2470: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
2471: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
2472: }
2473: return(0);
2474: }
2475: if (snes->npc && snes->npcside== PC_LEFT) {
2476: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
2477: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
2478: return(0);
2479: }
2481: PetscLogEventBegin(SNES_JacobianEval,snes,X,A,B);
2482: VecLockPush(X);
2483: PetscStackPush("SNES user Jacobian function");
2484: (*sdm->ops->computejacobian)(snes,X,A,B,sdm->jacobianctx);
2485: PetscStackPop;
2486: VecLockPop(X);
2487: PetscLogEventEnd(SNES_JacobianEval,snes,X,A,B);
2489: /* the next line ensures that snes->ksp exists */
2490: SNESGetKSP(snes,&ksp);
2491: if (snes->lagpreconditioner == -2) {
2492: PetscInfo(snes,"Rebuilding preconditioner exactly once since lag is -2\n");
2493: KSPSetReusePreconditioner(snes->ksp,PETSC_FALSE);
2494: snes->lagpreconditioner = -1;
2495: } else if (snes->lagpreconditioner == -1) {
2496: PetscInfo(snes,"Reusing preconditioner because lag is -1\n");
2497: KSPSetReusePreconditioner(snes->ksp,PETSC_TRUE);
2498: } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
2499: PetscInfo2(snes,"Reusing preconditioner because lag is %D and SNES iteration is %D\n",snes->lagpreconditioner,snes->iter);
2500: KSPSetReusePreconditioner(snes->ksp,PETSC_TRUE);
2501: } else {
2502: PetscInfo(snes,"Rebuilding preconditioner\n");
2503: KSPSetReusePreconditioner(snes->ksp,PETSC_FALSE);
2504: }
2506: SNESTestJacobian(snes);
2507: /* make sure user returned a correct Jacobian and preconditioner */
2510: {
2511: PetscBool flag = PETSC_FALSE,flag_draw = PETSC_FALSE,flag_contour = PETSC_FALSE,flag_operator = PETSC_FALSE;
2512: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_explicit",NULL,NULL,&flag);
2513: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_explicit_draw",NULL,NULL,&flag_draw);
2514: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_explicit_draw_contour",NULL,NULL,&flag_contour);
2515: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_operator",NULL,NULL,&flag_operator);
2516: if (flag || flag_draw || flag_contour) {
2517: Mat Bexp_mine = NULL,Bexp,FDexp;
2518: PetscViewer vdraw,vstdout;
2519: PetscBool flg;
2520: if (flag_operator) {
2521: MatComputeExplicitOperator(A,&Bexp_mine);
2522: Bexp = Bexp_mine;
2523: } else {
2524: /* See if the preconditioning matrix can be viewed and added directly */
2525: PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQAIJ,MATMPIAIJ,MATSEQDENSE,MATMPIDENSE,MATSEQBAIJ,MATMPIBAIJ,MATSEQSBAIJ,MATMPIBAIJ,"");
2526: if (flg) Bexp = B;
2527: else {
2528: /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
2529: MatComputeExplicitOperator(B,&Bexp_mine);
2530: Bexp = Bexp_mine;
2531: }
2532: }
2533: MatConvert(Bexp,MATSAME,MAT_INITIAL_MATRIX,&FDexp);
2534: SNESComputeJacobianDefault(snes,X,FDexp,FDexp,NULL);
2535: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&vstdout);
2536: if (flag_draw || flag_contour) {
2537: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),0,"Explicit Jacobians",PETSC_DECIDE,PETSC_DECIDE,300,300,&vdraw);
2538: if (flag_contour) {PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);}
2539: } else vdraw = NULL;
2540: PetscViewerASCIIPrintf(vstdout,"Explicit %s\n",flag_operator ? "Jacobian" : "preconditioning Jacobian");
2541: if (flag) {MatView(Bexp,vstdout);}
2542: if (vdraw) {MatView(Bexp,vdraw);}
2543: PetscViewerASCIIPrintf(vstdout,"Finite difference Jacobian\n");
2544: if (flag) {MatView(FDexp,vstdout);}
2545: if (vdraw) {MatView(FDexp,vdraw);}
2546: MatAYPX(FDexp,-1.0,Bexp,SAME_NONZERO_PATTERN);
2547: PetscViewerASCIIPrintf(vstdout,"User-provided matrix minus finite difference Jacobian\n");
2548: if (flag) {MatView(FDexp,vstdout);}
2549: if (vdraw) { /* Always use contour for the difference */
2550: PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);
2551: MatView(FDexp,vdraw);
2552: PetscViewerPopFormat(vdraw);
2553: }
2554: if (flag_contour) {PetscViewerPopFormat(vdraw);}
2555: PetscViewerDestroy(&vdraw);
2556: MatDestroy(&Bexp_mine);
2557: MatDestroy(&FDexp);
2558: }
2559: }
2560: {
2561: PetscBool flag = PETSC_FALSE,flag_display = PETSC_FALSE,flag_draw = PETSC_FALSE,flag_contour = PETSC_FALSE,flag_threshold = PETSC_FALSE;
2562: PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON,threshold_rtol = 10*PETSC_SQRT_MACHINE_EPSILON;
2563: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_coloring",NULL,NULL,&flag);
2564: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_coloring_display",NULL,NULL,&flag_display);
2565: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_coloring_draw",NULL,NULL,&flag_draw);
2566: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_coloring_draw_contour",NULL,NULL,&flag_contour);
2567: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold",NULL,NULL,&flag_threshold);
2568: if (flag_threshold) {
2569: PetscOptionsGetReal(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold_rtol",&threshold_rtol,NULL);
2570: PetscOptionsGetReal(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold_atol",&threshold_atol,NULL);
2571: }
2572: if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
2573: Mat Bfd;
2574: PetscViewer vdraw,vstdout;
2575: MatColoring coloring;
2576: ISColoring iscoloring;
2577: MatFDColoring matfdcoloring;
2578: PetscErrorCode (*func)(SNES,Vec,Vec,void*);
2579: void *funcctx;
2580: PetscReal norm1,norm2,normmax;
2582: MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&Bfd);
2583: MatColoringCreate(Bfd,&coloring);
2584: MatColoringSetType(coloring,MATCOLORINGSL);
2585: MatColoringSetFromOptions(coloring);
2586: MatColoringApply(coloring,&iscoloring);
2587: MatColoringDestroy(&coloring);
2588: MatFDColoringCreate(Bfd,iscoloring,&matfdcoloring);
2589: MatFDColoringSetFromOptions(matfdcoloring);
2590: MatFDColoringSetUp(Bfd,iscoloring,matfdcoloring);
2591: ISColoringDestroy(&iscoloring);
2593: /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
2594: SNESGetFunction(snes,NULL,&func,&funcctx);
2595: MatFDColoringSetFunction(matfdcoloring,(PetscErrorCode (*)(void))func,funcctx);
2596: PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring,((PetscObject)snes)->prefix);
2597: PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring,"coloring_");
2598: MatFDColoringSetFromOptions(matfdcoloring);
2599: MatFDColoringApply(Bfd,matfdcoloring,X,snes);
2600: MatFDColoringDestroy(&matfdcoloring);
2602: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&vstdout);
2603: if (flag_draw || flag_contour) {
2604: PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),0,"Colored Jacobians",PETSC_DECIDE,PETSC_DECIDE,300,300,&vdraw);
2605: if (flag_contour) {PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);}
2606: } else vdraw = NULL;
2607: PetscViewerASCIIPrintf(vstdout,"Explicit preconditioning Jacobian\n");
2608: if (flag_display) {MatView(B,vstdout);}
2609: if (vdraw) {MatView(B,vdraw);}
2610: PetscViewerASCIIPrintf(vstdout,"Colored Finite difference Jacobian\n");
2611: if (flag_display) {MatView(Bfd,vstdout);}
2612: if (vdraw) {MatView(Bfd,vdraw);}
2613: MatAYPX(Bfd,-1.0,B,SAME_NONZERO_PATTERN);
2614: MatNorm(Bfd,NORM_1,&norm1);
2615: MatNorm(Bfd,NORM_FROBENIUS,&norm2);
2616: MatNorm(Bfd,NORM_MAX,&normmax);
2617: PetscViewerASCIIPrintf(vstdout,"User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n",(double)norm1,(double)norm2,(double)normmax);
2618: if (flag_display) {MatView(Bfd,vstdout);}
2619: if (vdraw) { /* Always use contour for the difference */
2620: PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);
2621: MatView(Bfd,vdraw);
2622: PetscViewerPopFormat(vdraw);
2623: }
2624: if (flag_contour) {PetscViewerPopFormat(vdraw);}
2626: if (flag_threshold) {
2627: PetscInt bs,rstart,rend,i;
2628: MatGetBlockSize(B,&bs);
2629: MatGetOwnershipRange(B,&rstart,&rend);
2630: for (i=rstart; i<rend; i++) {
2631: const PetscScalar *ba,*ca;
2632: const PetscInt *bj,*cj;
2633: PetscInt bn,cn,j,maxentrycol = -1,maxdiffcol = -1,maxrdiffcol = -1;
2634: PetscReal maxentry = 0,maxdiff = 0,maxrdiff = 0;
2635: MatGetRow(B,i,&bn,&bj,&ba);
2636: MatGetRow(Bfd,i,&cn,&cj,&ca);
2637: if (bn != cn) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_PLIB,"Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
2638: for (j=0; j<bn; j++) {
2639: PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol*PetscAbsScalar(ba[j]));
2640: if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
2641: maxentrycol = bj[j];
2642: maxentry = PetscRealPart(ba[j]);
2643: }
2644: if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
2645: maxdiffcol = bj[j];
2646: maxdiff = PetscRealPart(ca[j]);
2647: }
2648: if (rdiff > maxrdiff) {
2649: maxrdiffcol = bj[j];
2650: maxrdiff = rdiff;
2651: }
2652: }
2653: if (maxrdiff > 1) {
2654: PetscViewerASCIIPrintf(vstdout,"row %D (maxentry=%g at %D, maxdiff=%g at %D, maxrdiff=%g at %D):",i,(double)maxentry,maxentrycol,(double)maxdiff,maxdiffcol,(double)maxrdiff,maxrdiffcol);
2655: for (j=0; j<bn; j++) {
2656: PetscReal rdiff;
2657: rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol*PetscAbsScalar(ba[j]));
2658: if (rdiff > 1) {
2659: PetscViewerASCIIPrintf(vstdout," (%D,%g:%g)",bj[j],(double)PetscRealPart(ba[j]),(double)PetscRealPart(ca[j]));
2660: }
2661: }
2662: PetscViewerASCIIPrintf(vstdout,"\n",i,maxentry,maxdiff,maxrdiff);
2663: }
2664: MatRestoreRow(B,i,&bn,&bj,&ba);
2665: MatRestoreRow(Bfd,i,&cn,&cj,&ca);
2666: }
2667: }
2668: PetscViewerDestroy(&vdraw);
2669: MatDestroy(&Bfd);
2670: }
2671: }
2672: return(0);
2673: }
2675: /*MC
2676: SNESJacobianFunction - Function used to convey the nonlinear Jacobian of the function to be solved by SNES
2678: Synopsis:
2679: #include "petscsnes.h"
2680: PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
2682: + x - input vector
2683: . Amat - the matrix that defines the (approximate) Jacobian
2684: . Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
2685: - ctx - [optional] user-defined Jacobian context
2687: Level: intermediate
2689: .seealso: SNESSetFunction(), SNESGetFunction(), SNESSetJacobian(), SNESGetJacobian()
2690: M*/
2692: /*@C
2693: SNESSetJacobian - Sets the function to compute Jacobian as well as the
2694: location to store the matrix.
2696: Logically Collective on SNES and Mat
2698: Input Parameters:
2699: + snes - the SNES context
2700: . Amat - the matrix that defines the (approximate) Jacobian
2701: . Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
2702: . J - Jacobian evaluation routine (if NULL then SNES retains any previously set value), see SNESJacobianFunction for details
2703: - ctx - [optional] user-defined context for private data for the
2704: Jacobian evaluation routine (may be NULL) (if NULL then SNES retains any previously set value)
2706: Notes:
2707: If the Amat matrix and Pmat matrix are different you must call MatAssemblyBegin/End() on
2708: each matrix.
2710: If you know the operator Amat has a null space you can use MatSetNullSpace() and MatSetTransposeNullSpace() to supply the null
2711: space to Amat and the KSP solvers will automatically use that null space as needed during the solution process.
2713: If using SNESComputeJacobianDefaultColor() to assemble a Jacobian, the ctx argument
2714: must be a MatFDColoring.
2716: Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common
2717: example is to use the "Picard linearization" which only differentiates through the highest order parts of each term.
2719: Level: beginner
2721: .keywords: SNES, nonlinear, set, Jacobian, matrix
2723: .seealso: KSPSetOperators(), SNESSetFunction(), MatMFFDComputeJacobian(), SNESComputeJacobianDefaultColor(), MatStructure, J,
2724: SNESSetPicard(), SNESJacobianFunction
2725: @*/
2726: PetscErrorCode SNESSetJacobian(SNES snes,Mat Amat,Mat Pmat,PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
2727: {
2729: DM dm;
2737: SNESGetDM(snes,&dm);
2738: DMSNESSetJacobian(dm,J,ctx);
2739: if (Amat) {
2740: PetscObjectReference((PetscObject)Amat);
2741: MatDestroy(&snes->jacobian);
2743: snes->jacobian = Amat;
2744: }
2745: if (Pmat) {
2746: PetscObjectReference((PetscObject)Pmat);
2747: MatDestroy(&snes->jacobian_pre);
2749: snes->jacobian_pre = Pmat;
2750: }
2751: return(0);
2752: }
2754: /*@C
2755: SNESGetJacobian - Returns the Jacobian matrix and optionally the user
2756: provided context for evaluating the Jacobian.
2758: Not Collective, but Mat object will be parallel if SNES object is
2760: Input Parameter:
2761: . snes - the nonlinear solver context
2763: Output Parameters:
2764: + Amat - location to stash (approximate) Jacobian matrix (or NULL)
2765: . Pmat - location to stash matrix used to compute the preconditioner (or NULL)
2766: . J - location to put Jacobian function (or NULL), see SNESJacobianFunction for details on its calling sequence
2767: - ctx - location to stash Jacobian ctx (or NULL)
2769: Level: advanced
2771: .seealso: SNESSetJacobian(), SNESComputeJacobian(), SNESJacobianFunction, SNESGetFunction()
2772: @*/
2773: PetscErrorCode SNESGetJacobian(SNES snes,Mat *Amat,Mat *Pmat,PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
2774: {
2776: DM dm;
2777: DMSNES sdm;
2781: if (Amat) *Amat = snes->jacobian;
2782: if (Pmat) *Pmat = snes->jacobian_pre;
2783: SNESGetDM(snes,&dm);
2784: DMGetDMSNES(dm,&sdm);
2785: if (J) *J = sdm->ops->computejacobian;
2786: if (ctx) *ctx = sdm->jacobianctx;
2787: return(0);
2788: }
2790: /*@
2791: SNESSetUp - Sets up the internal data structures for the later use
2792: of a nonlinear solver.
2794: Collective on SNES
2796: Input Parameters:
2797: . snes - the SNES context
2799: Notes:
2800: For basic use of the SNES solvers the user need not explicitly call
2801: SNESSetUp(), since these actions will automatically occur during
2802: the call to SNESSolve(). However, if one wishes to control this
2803: phase separately, SNESSetUp() should be called after SNESCreate()
2804: and optional routines of the form SNESSetXXX(), but before SNESSolve().
2806: Level: advanced
2808: .keywords: SNES, nonlinear, setup
2810: .seealso: SNESCreate(), SNESSolve(), SNESDestroy()
2811: @*/
2812: PetscErrorCode SNESSetUp(SNES snes)
2813: {
2815: DM dm;
2816: DMSNES sdm;
2817: SNESLineSearch linesearch, pclinesearch;
2818: void *lsprectx,*lspostctx;
2819: PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*);
2820: PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*);
2821: PetscErrorCode (*func)(SNES,Vec,Vec,void*);
2822: Vec f,fpc;
2823: void *funcctx;
2824: PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*);
2825: void *jacctx,*appctx;
2826: Mat j,jpre;
2830: if (snes->setupcalled) return(0);
2832: if (!((PetscObject)snes)->type_name) {
2833: SNESSetType(snes,SNESNEWTONLS);
2834: }
2836: SNESGetFunction(snes,&snes->vec_func,NULL,NULL);
2838: SNESGetDM(snes,&dm);
2839: DMGetDMSNES(dm,&sdm);
2840: if (!sdm->ops->computefunction) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Function never provided to SNES object");
2841: if (!sdm->ops->computejacobian) {
2842: DMSNESSetJacobian(dm,SNESComputeJacobianDefaultColor,NULL);
2843: }
2844: if (!snes->vec_func) {
2845: DMCreateGlobalVector(dm,&snes->vec_func);
2846: }
2848: if (!snes->ksp) {
2849: SNESGetKSP(snes, &snes->ksp);
2850: }
2852: if (!snes->linesearch) {
2853: SNESGetLineSearch(snes, &snes->linesearch);
2854: }
2855: SNESLineSearchSetFunction(snes->linesearch,SNESComputeFunction);
2857: if (snes->npc && (snes->npcside== PC_LEFT)) {
2858: snes->mf = PETSC_TRUE;
2859: snes->mf_operator = PETSC_FALSE;
2860: }
2862: if (snes->npc) {
2863: /* copy the DM over */
2864: SNESGetDM(snes,&dm);
2865: SNESSetDM(snes->npc,dm);
2867: SNESGetFunction(snes,&f,&func,&funcctx);
2868: VecDuplicate(f,&fpc);
2869: SNESSetFunction(snes->npc,fpc,func,funcctx);
2870: SNESGetJacobian(snes,&j,&jpre,&jac,&jacctx);
2871: SNESSetJacobian(snes->npc,j,jpre,jac,jacctx);
2872: SNESGetApplicationContext(snes,&appctx);
2873: SNESSetApplicationContext(snes->npc,appctx);
2874: VecDestroy(&fpc);
2876: /* copy the function pointers over */
2877: PetscObjectCopyFortranFunctionPointers((PetscObject)snes,(PetscObject)snes->npc);
2879: /* default to 1 iteration */
2880: SNESSetTolerances(snes->npc,0.0,0.0,0.0,1,snes->npc->max_funcs);
2881: if (snes->npcside==PC_RIGHT) {
2882: SNESSetNormSchedule(snes->npc,SNES_NORM_FINAL_ONLY);
2883: } else {
2884: SNESSetNormSchedule(snes->npc,SNES_NORM_NONE);
2885: }
2886: SNESSetFromOptions(snes->npc);
2888: /* copy the line search context over */
2889: SNESGetLineSearch(snes,&linesearch);
2890: SNESGetLineSearch(snes->npc,&pclinesearch);
2891: SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);
2892: SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);
2893: SNESLineSearchSetPreCheck(pclinesearch,precheck,lsprectx);
2894: SNESLineSearchSetPostCheck(pclinesearch,postcheck,lspostctx);
2895: PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch);
2896: }
2897: if (snes->mf) {
2898: SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version);
2899: }
2900: if (snes->ops->usercompute && !snes->user) {
2901: (*snes->ops->usercompute)(snes,(void**)&snes->user);
2902: }
2904: snes->jac_iter = 0;
2905: snes->pre_iter = 0;
2907: if (snes->ops->setup) {
2908: (*snes->ops->setup)(snes);
2909: }
2911: if (snes->npc && (snes->npcside== PC_LEFT)) {
2912: if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
2913: SNESGetLineSearch(snes,&linesearch);
2914: SNESLineSearchSetFunction(linesearch,SNESComputeFunctionDefaultNPC);
2915: }
2916: }
2918: snes->setupcalled = PETSC_TRUE;
2919: return(0);
2920: }
2922: /*@
2923: SNESReset - Resets a SNES context to the snessetupcalled = 0 state and removes any allocated Vecs and Mats
2925: Collective on SNES
2927: Input Parameter:
2928: . snes - iterative context obtained from SNESCreate()
2930: Level: intermediate
2932: Notes: Also calls the application context destroy routine set with SNESSetComputeApplicationContext()
2934: .keywords: SNES, destroy
2936: .seealso: SNESCreate(), SNESSetUp(), SNESSolve()
2937: @*/
2938: PetscErrorCode SNESReset(SNES snes)
2939: {
2944: if (snes->ops->userdestroy && snes->user) {
2945: (*snes->ops->userdestroy)((void**)&snes->user);
2946: snes->user = NULL;
2947: }
2948: if (snes->npc) {
2949: SNESReset(snes->npc);
2950: }
2952: if (snes->ops->reset) {
2953: (*snes->ops->reset)(snes);
2954: }
2955: if (snes->ksp) {
2956: KSPReset(snes->ksp);
2957: }
2959: if (snes->linesearch) {
2960: SNESLineSearchReset(snes->linesearch);
2961: }
2963: VecDestroy(&snes->vec_rhs);
2964: VecDestroy(&snes->vec_sol);
2965: VecDestroy(&snes->vec_sol_update);
2966: VecDestroy(&snes->vec_func);
2967: MatDestroy(&snes->jacobian);
2968: MatDestroy(&snes->jacobian_pre);
2969: VecDestroyVecs(snes->nwork,&snes->work);
2970: VecDestroyVecs(snes->nvwork,&snes->vwork);
2972: snes->alwayscomputesfinalresidual = PETSC_FALSE;
2974: snes->nwork = snes->nvwork = 0;
2975: snes->setupcalled = PETSC_FALSE;
2976: return(0);
2977: }
2979: /*@
2980: SNESDestroy - Destroys the nonlinear solver context that was created
2981: with SNESCreate().
2983: Collective on SNES
2985: Input Parameter:
2986: . snes - the SNES context
2988: Level: beginner
2990: .keywords: SNES, nonlinear, destroy
2992: .seealso: SNESCreate(), SNESSolve()
2993: @*/
2994: PetscErrorCode SNESDestroy(SNES *snes)
2995: {
2999: if (!*snes) return(0);
3001: if (--((PetscObject)(*snes))->refct > 0) {*snes = 0; return(0);}
3003: SNESReset((*snes));
3004: SNESDestroy(&(*snes)->npc);
3006: /* if memory was published with SAWs then destroy it */
3007: PetscObjectSAWsViewOff((PetscObject)*snes);
3008: if ((*snes)->ops->destroy) {(*((*snes))->ops->destroy)((*snes));}
3010: if ((*snes)->dm) {DMCoarsenHookRemove((*snes)->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,*snes);}
3011: DMDestroy(&(*snes)->dm);
3012: KSPDestroy(&(*snes)->ksp);
3013: SNESLineSearchDestroy(&(*snes)->linesearch);
3015: PetscFree((*snes)->kspconvctx);
3016: if ((*snes)->ops->convergeddestroy) {
3017: (*(*snes)->ops->convergeddestroy)((*snes)->cnvP);
3018: }
3019: if ((*snes)->conv_malloc) {
3020: PetscFree((*snes)->conv_hist);
3021: PetscFree((*snes)->conv_hist_its);
3022: }
3023: SNESMonitorCancel((*snes));
3024: PetscHeaderDestroy(snes);
3025: return(0);
3026: }
3028: /* ----------- Routines to set solver parameters ---------- */
3030: /*@
3031: SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3033: Logically Collective on SNES
3035: Input Parameters:
3036: + snes - the SNES context
3037: - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3038: the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3040: Options Database Keys:
3041: . -snes_lag_preconditioner <lag>
3043: Notes:
3044: The default is 1
3045: The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3046: If -1 is used before the very first nonlinear solve the preconditioner is still built because there is no previous preconditioner to use
3048: Level: intermediate
3050: .keywords: SNES, nonlinear, set, convergence, tolerances
3052: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian()
3054: @*/
3055: PetscErrorCode SNESSetLagPreconditioner(SNES snes,PetscInt lag)
3056: {
3059: if (lag < -2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater");
3060: if (!lag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0");
3062: snes->lagpreconditioner = lag;
3063: return(0);
3064: }
3066: /*@
3067: SNESSetGridSequence - sets the number of steps of grid sequencing that SNES does
3069: Logically Collective on SNES
3071: Input Parameters:
3072: + snes - the SNES context
3073: - steps - the number of refinements to do, defaults to 0
3075: Options Database Keys:
3076: . -snes_grid_sequence <steps>
3078: Level: intermediate
3080: Notes:
3081: Use SNESGetSolution() to extract the fine grid solution after grid sequencing.
3083: .keywords: SNES, nonlinear, set, convergence, tolerances
3085: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetGridSequence()
3087: @*/
3088: PetscErrorCode SNESSetGridSequence(SNES snes,PetscInt steps)
3089: {
3093: snes->gridsequence = steps;
3094: return(0);
3095: }
3097: /*@
3098: SNESGetGridSequence - gets the number of steps of grid sequencing that SNES does
3100: Logically Collective on SNES
3102: Input Parameter:
3103: . snes - the SNES context
3105: Output Parameter:
3106: . steps - the number of refinements to do, defaults to 0
3108: Options Database Keys:
3109: . -snes_grid_sequence <steps>
3111: Level: intermediate
3113: Notes:
3114: Use SNESGetSolution() to extract the fine grid solution after grid sequencing.
3116: .keywords: SNES, nonlinear, set, convergence, tolerances
3118: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESSetGridSequence()
3120: @*/
3121: PetscErrorCode SNESGetGridSequence(SNES snes,PetscInt *steps)
3122: {
3125: *steps = snes->gridsequence;
3126: return(0);
3127: }
3129: /*@
3130: SNESGetLagPreconditioner - Indicates how often the preconditioner is rebuilt
3132: Not Collective
3134: Input Parameter:
3135: . snes - the SNES context
3137: Output Parameter:
3138: . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3139: the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3141: Options Database Keys:
3142: . -snes_lag_preconditioner <lag>
3144: Notes:
3145: The default is 1
3146: The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3148: Level: intermediate
3150: .keywords: SNES, nonlinear, set, convergence, tolerances
3152: .seealso: SNESSetTrustRegionTolerance(), SNESSetLagPreconditioner()
3154: @*/
3155: PetscErrorCode SNESGetLagPreconditioner(SNES snes,PetscInt *lag)
3156: {
3159: *lag = snes->lagpreconditioner;
3160: return(0);
3161: }
3163: /*@
3164: SNESSetLagJacobian - Determines when the Jacobian is rebuilt in the nonlinear solve. See SNESSetLagPreconditioner() for determining how
3165: often the preconditioner is rebuilt.
3167: Logically Collective on SNES
3169: Input Parameters:
3170: + snes - the SNES context
3171: - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3172: the Jacobian is built etc. -2 means rebuild at next chance but then never again
3174: Options Database Keys:
3175: . -snes_lag_jacobian <lag>
3177: Notes:
3178: The default is 1
3179: The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3180: 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
3181: at the next Newton step but never again (unless it is reset to another value)
3183: Level: intermediate
3185: .keywords: SNES, nonlinear, set, convergence, tolerances
3187: .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagPreconditioner(), SNESGetLagJacobian()
3189: @*/
3190: PetscErrorCode SNESSetLagJacobian(SNES snes,PetscInt lag)
3191: {
3194: if (lag < -2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater");
3195: if (!lag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0");
3197: snes->lagjacobian = lag;
3198: return(0);
3199: }
3201: /*@
3202: SNESGetLagJacobian - Indicates how often the Jacobian is rebuilt. See SNESGetLagPreconditioner() to determine when the preconditioner is rebuilt
3204: Not Collective
3206: Input Parameter:
3207: . snes - the SNES context
3209: Output Parameter:
3210: . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3211: the Jacobian is built etc.
3213: Options Database Keys:
3214: . -snes_lag_jacobian <lag>
3216: Notes:
3217: The default is 1
3218: The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3220: Level: intermediate
3222: .keywords: SNES, nonlinear, set, convergence, tolerances
3224: .seealso: SNESSetTrustRegionTolerance(), SNESSetLagJacobian(), SNESSetLagPreconditioner(), SNESGetLagPreconditioner()
3226: @*/
3227: PetscErrorCode SNESGetLagJacobian(SNES snes,PetscInt *lag)
3228: {
3231: *lag = snes->lagjacobian;
3232: return(0);
3233: }
3235: /*@
3236: SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple solves
3238: Logically collective on SNES
3240: Input Parameter:
3241: + snes - the SNES context
3242: - flg - jacobian lagging persists if true
3244: Options Database Keys:
3245: . -snes_lag_jacobian_persists <flg>
3247: Notes: This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
3248: several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
3249: timesteps may present huge efficiency gains.
3251: Level: developer
3253: .keywords: SNES, nonlinear, lag
3255: .seealso: SNESSetLagPreconditionerPersists(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetNPC()
3257: @*/
3258: PetscErrorCode SNESSetLagJacobianPersists(SNES snes,PetscBool flg)
3259: {
3263: snes->lagjac_persist = flg;
3264: return(0);
3265: }
3267: /*@
3268: SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple solves
3270: Logically Collective on SNES
3272: Input Parameter:
3273: + snes - the SNES context
3274: - flg - preconditioner lagging persists if true
3276: Options Database Keys:
3277: . -snes_lag_jacobian_persists <flg>
3279: Notes: This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
3280: by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
3281: several timesteps may present huge efficiency gains.
3283: Level: developer
3285: .keywords: SNES, nonlinear, lag
3287: .seealso: SNESSetLagJacobianPersists(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetNPC()
3289: @*/
3290: PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes,PetscBool flg)
3291: {
3295: snes->lagpre_persist = flg;
3296: return(0);
3297: }
3299: /*@
3300: SNESSetForceIteration - force SNESSolve() to take at least one iteration regardless of the initial residual norm
3302: Logically Collective on SNES
3304: Input Parameters:
3305: + snes - the SNES context
3306: - force - PETSC_TRUE require at least one iteration
3308: Options Database Keys:
3309: . -snes_force_iteration <force> - Sets forcing an iteration
3311: Notes:
3312: This is used sometimes with TS to prevent TS from detecting a false steady state solution
3314: Level: intermediate
3316: .keywords: SNES, nonlinear, set, convergence, tolerances
3318: .seealso: SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance()
3319: @*/
3320: PetscErrorCode SNESSetForceIteration(SNES snes,PetscBool force)
3321: {
3324: snes->forceiteration = force;
3325: return(0);
3326: }
3328: /*@
3329: SNESGetForceIteration - Whether or not to force SNESSolve() take at least one iteration regardless of the initial residual norm
3331: Logically Collective on SNES
3333: Input Parameters:
3334: . snes - the SNES context
3336: Output Parameter:
3337: . force - PETSC_TRUE requires at least one iteration.
3339: .keywords: SNES, nonlinear, set, convergence, tolerances
3341: .seealso: SNESSetForceIteration(), SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance()
3342: @*/
3343: PetscErrorCode SNESGetForceIteration(SNES snes,PetscBool *force)
3344: {
3347: *force = snes->forceiteration;
3348: return(0);
3349: }
3351: /*@
3352: SNESSetTolerances - Sets various parameters used in convergence tests.
3354: Logically Collective on SNES
3356: Input Parameters:
3357: + snes - the SNES context
3358: . abstol - absolute convergence tolerance
3359: . rtol - relative convergence tolerance
3360: . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x ||
3361: . maxit - maximum number of iterations
3362: - maxf - maximum number of function evaluations
3364: Options Database Keys:
3365: + -snes_atol <abstol> - Sets abstol
3366: . -snes_rtol <rtol> - Sets rtol
3367: . -snes_stol <stol> - Sets stol
3368: . -snes_max_it <maxit> - Sets maxit
3369: - -snes_max_funcs <maxf> - Sets maxf
3371: Notes:
3372: The default maximum number of iterations is 50.
3373: The default maximum number of function evaluations is 1000.
3375: Level: intermediate
3377: .keywords: SNES, nonlinear, set, convergence, tolerances
3379: .seealso: SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance(), SNESSetForceIteration()
3380: @*/
3381: PetscErrorCode SNESSetTolerances(SNES snes,PetscReal abstol,PetscReal rtol,PetscReal stol,PetscInt maxit,PetscInt maxf)
3382: {
3391: if (abstol != PETSC_DEFAULT) {
3392: if (abstol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g must be non-negative",(double)abstol);
3393: snes->abstol = abstol;
3394: }
3395: if (rtol != PETSC_DEFAULT) {
3396: 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",(double)rtol);
3397: snes->rtol = rtol;
3398: }
3399: if (stol != PETSC_DEFAULT) {
3400: if (stol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Step tolerance %g must be non-negative",(double)stol);
3401: snes->stol = stol;
3402: }
3403: if (maxit != PETSC_DEFAULT) {
3404: if (maxit < 0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",maxit);
3405: snes->max_its = maxit;
3406: }
3407: if (maxf != PETSC_DEFAULT) {
3408: if (maxf < 0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of function evaluations %D must be non-negative",maxf);
3409: snes->max_funcs = maxf;
3410: }
3411: snes->tolerancesset = PETSC_TRUE;
3412: return(0);
3413: }
3415: /*@
3416: SNESSetDivergenceTolerance - Sets the divergence tolerance used for the SNES divergence test.
3418: Logically Collective on SNES
3420: Input Parameters:
3421: + snes - the SNES context
3422: - divtol - the divergence tolerance. Use -1 to deactivate the test.
3424: Options Database Keys:
3425: + -snes_divergence_tolerance <divtol> - Sets divtol
3427: Notes:
3428: The default divergence tolerance is 1e4.
3430: Level: intermediate
3432: .keywords: SNES, nonlinear, set, divergence, tolerance
3434: .seealso: SNESSetTolerances(), SNESGetDivergenceTolerance
3435: @*/
3436: PetscErrorCode SNESSetDivergenceTolerance(SNES snes,PetscReal divtol)
3437: {
3442: if (divtol != PETSC_DEFAULT) {
3443: snes->divtol = divtol;
3444: }
3445: else {
3446: snes->divtol = 1.0e4;
3447: }
3448: return(0);
3449: }
3451: /*@
3452: SNESGetTolerances - Gets various parameters used in convergence tests.
3454: Not Collective
3456: Input Parameters:
3457: + snes - the SNES context
3458: . atol - absolute convergence tolerance
3459: . rtol - relative convergence tolerance
3460: . stol - convergence tolerance in terms of the norm
3461: of the change in the solution between steps
3462: . maxit - maximum number of iterations
3463: - maxf - maximum number of function evaluations
3465: Notes:
3466: The user can specify NULL for any parameter that is not needed.
3468: Level: intermediate
3470: .keywords: SNES, nonlinear, get, convergence, tolerances
3472: .seealso: SNESSetTolerances()
3473: @*/
3474: PetscErrorCode SNESGetTolerances(SNES snes,PetscReal *atol,PetscReal *rtol,PetscReal *stol,PetscInt *maxit,PetscInt *maxf)
3475: {
3478: if (atol) *atol = snes->abstol;
3479: if (rtol) *rtol = snes->rtol;
3480: if (stol) *stol = snes->stol;
3481: if (maxit) *maxit = snes->max_its;
3482: if (maxf) *maxf = snes->max_funcs;
3483: return(0);
3484: }
3486: /*@
3487: SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3489: Not Collective
3491: Input Parameters:
3492: + snes - the SNES context
3493: - divtol - divergence tolerance
3495: Level: intermediate
3497: .keywords: SNES, nonlinear, get, divergence, tolerance
3499: .seealso: SNESSetDivergenceTolerance()
3500: @*/
3501: PetscErrorCode SNESGetDivergenceTolerance(SNES snes,PetscReal *divtol)
3502: {
3505: if (divtol) *divtol = snes->divtol;
3506: return(0);
3507: }
3509: /*@
3510: SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
3512: Logically Collective on SNES
3514: Input Parameters:
3515: + snes - the SNES context
3516: - tol - tolerance
3518: Options Database Key:
3519: . -snes_trtol <tol> - Sets tol
3521: Level: intermediate
3523: .keywords: SNES, nonlinear, set, trust region, tolerance
3525: .seealso: SNESSetTolerances()
3526: @*/
3527: PetscErrorCode SNESSetTrustRegionTolerance(SNES snes,PetscReal tol)
3528: {
3532: snes->deltatol = tol;
3533: return(0);
3534: }
3536: /*
3537: Duplicate the lg monitors for SNES from KSP; for some reason with
3538: dynamic libraries things don't work under Sun4 if we just use
3539: macros instead of functions
3540: */
3541: PetscErrorCode SNESMonitorLGResidualNorm(SNES snes,PetscInt it,PetscReal norm,void *ctx)
3542: {
3547: KSPMonitorLGResidualNorm((KSP)snes,it,norm,ctx);
3548: return(0);
3549: }
3551: PetscErrorCode SNESMonitorLGCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *lgctx)
3552: {
3556: KSPMonitorLGResidualNormCreate(comm,host,label,x,y,m,n,lgctx);
3557: return(0);
3558: }
3560: PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES,PetscInt,PetscReal*);
3562: PetscErrorCode SNESMonitorLGRange(SNES snes,PetscInt n,PetscReal rnorm,void *monctx)
3563: {
3564: PetscDrawLG lg;
3565: PetscErrorCode ierr;
3566: PetscReal x,y,per;
3567: PetscViewer v = (PetscViewer)monctx;
3568: static PetscReal prev; /* should be in the context */
3569: PetscDraw draw;
3573: PetscViewerDrawGetDrawLG(v,0,&lg);
3574: if (!n) {PetscDrawLGReset(lg);}
3575: PetscDrawLGGetDraw(lg,&draw);
3576: PetscDrawSetTitle(draw,"Residual norm");
3577: x = (PetscReal)n;
3578: if (rnorm > 0.0) y = PetscLog10Real(rnorm);
3579: else y = -15.0;
3580: PetscDrawLGAddPoint(lg,&x,&y);
3581: if (n < 20 || !(n % 5) || snes->reason) {
3582: PetscDrawLGDraw(lg);
3583: PetscDrawLGSave(lg);
3584: }
3586: PetscViewerDrawGetDrawLG(v,1,&lg);
3587: if (!n) {PetscDrawLGReset(lg);}
3588: PetscDrawLGGetDraw(lg,&draw);
3589: PetscDrawSetTitle(draw,"% elemts > .2*max elemt");
3590: SNESMonitorRange_Private(snes,n,&per);
3591: x = (PetscReal)n;
3592: y = 100.0*per;
3593: PetscDrawLGAddPoint(lg,&x,&y);
3594: if (n < 20 || !(n % 5) || snes->reason) {
3595: PetscDrawLGDraw(lg);
3596: PetscDrawLGSave(lg);
3597: }
3599: PetscViewerDrawGetDrawLG(v,2,&lg);
3600: if (!n) {prev = rnorm;PetscDrawLGReset(lg);}
3601: PetscDrawLGGetDraw(lg,&draw);
3602: PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm");
3603: x = (PetscReal)n;
3604: y = (prev - rnorm)/prev;
3605: PetscDrawLGAddPoint(lg,&x,&y);
3606: if (n < 20 || !(n % 5) || snes->reason) {
3607: PetscDrawLGDraw(lg);
3608: PetscDrawLGSave(lg);
3609: }
3611: PetscViewerDrawGetDrawLG(v,3,&lg);
3612: if (!n) {PetscDrawLGReset(lg);}
3613: PetscDrawLGGetDraw(lg,&draw);
3614: PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm*(% > .2 max)");
3615: x = (PetscReal)n;
3616: y = (prev - rnorm)/(prev*per);
3617: if (n > 2) { /*skip initial crazy value */
3618: PetscDrawLGAddPoint(lg,&x,&y);
3619: }
3620: if (n < 20 || !(n % 5) || snes->reason) {
3621: PetscDrawLGDraw(lg);
3622: PetscDrawLGSave(lg);
3623: }
3624: prev = rnorm;
3625: return(0);
3626: }
3628: /*@
3629: SNESMonitor - runs the user provided monitor routines, if they exist
3631: Collective on SNES
3633: Input Parameters:
3634: + snes - nonlinear solver context obtained from SNESCreate()
3635: . iter - iteration number
3636: - rnorm - relative norm of the residual
3638: Notes:
3639: This routine is called by the SNES implementations.
3640: It does not typically need to be called by the user.
3642: Level: developer
3644: .seealso: SNESMonitorSet()
3645: @*/
3646: PetscErrorCode SNESMonitor(SNES snes,PetscInt iter,PetscReal rnorm)
3647: {
3649: PetscInt i,n = snes->numbermonitors;
3652: VecLockPush(snes->vec_sol);
3653: for (i=0; i<n; i++) {
3654: (*snes->monitor[i])(snes,iter,rnorm,snes->monitorcontext[i]);
3655: }
3656: VecLockPop(snes->vec_sol);
3657: return(0);
3658: }
3660: /* ------------ Routines to set performance monitoring options ----------- */
3662: /*MC
3663: SNESMonitorFunction - functional form passed to SNESMonitorSet() to monitor convergence of nonlinear solver
3665: Synopsis:
3666: #include <petscsnes.h>
3667: $ PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx)
3669: + snes - the SNES context
3670: . its - iteration number
3671: . norm - 2-norm function value (may be estimated)
3672: - mctx - [optional] monitoring context
3674: Level: advanced
3676: .seealso: SNESMonitorSet(), SNESMonitorGet()
3677: M*/
3679: /*@C
3680: SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
3681: iteration of the nonlinear solver to display the iteration's
3682: progress.
3684: Logically Collective on SNES
3686: Input Parameters:
3687: + snes - the SNES context
3688: . f - the monitor function, see SNESMonitorFunction for the calling sequence
3689: . mctx - [optional] user-defined context for private data for the
3690: monitor routine (use NULL if no context is desired)
3691: - monitordestroy - [optional] routine that frees monitor context
3692: (may be NULL)
3694: Options Database Keys:
3695: + -snes_monitor - sets SNESMonitorDefault()
3696: . -snes_monitor_lg_residualnorm - sets line graph monitor,
3697: uses SNESMonitorLGCreate()
3698: - -snes_monitor_cancel - cancels all monitors that have
3699: been hardwired into a code by
3700: calls to SNESMonitorSet(), but
3701: does not cancel those set via
3702: the options database.
3704: Notes:
3705: Several different monitoring routines may be set by calling
3706: SNESMonitorSet() multiple times; all will be called in the
3707: order in which they were set.
3709: Fortran notes: Only a single monitor function can be set for each SNES object
3711: Level: intermediate
3713: .keywords: SNES, nonlinear, set, monitor
3715: .seealso: SNESMonitorDefault(), SNESMonitorCancel(), SNESMonitorFunction
3716: @*/
3717: PetscErrorCode SNESMonitorSet(SNES snes,PetscErrorCode (*f)(SNES,PetscInt,PetscReal,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
3718: {
3719: PetscInt i;
3721: PetscBool identical;
3725: for (i=0; i<snes->numbermonitors;i++) {
3726: PetscMonitorCompare((PetscErrorCode (*)(void))f,mctx,monitordestroy,(PetscErrorCode (*)(void))snes->monitor[i],snes->monitorcontext[i],snes->monitordestroy[i],&identical);
3727: if (identical) return(0);
3728: }
3729: if (snes->numbermonitors >= MAXSNESMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
3730: snes->monitor[snes->numbermonitors] = f;
3731: snes->monitordestroy[snes->numbermonitors] = monitordestroy;
3732: snes->monitorcontext[snes->numbermonitors++] = (void*)mctx;
3733: return(0);
3734: }
3736: /*@
3737: SNESMonitorCancel - Clears all the monitor functions for a SNES object.
3739: Logically Collective on SNES
3741: Input Parameters:
3742: . snes - the SNES context
3744: Options Database Key:
3745: . -snes_monitor_cancel - cancels all monitors that have been hardwired
3746: into a code by calls to SNESMonitorSet(), but does not cancel those
3747: set via the options database
3749: Notes:
3750: There is no way to clear one specific monitor from a SNES object.
3752: Level: intermediate
3754: .keywords: SNES, nonlinear, set, monitor
3756: .seealso: SNESMonitorDefault(), SNESMonitorSet()
3757: @*/
3758: PetscErrorCode SNESMonitorCancel(SNES snes)
3759: {
3761: PetscInt i;
3765: for (i=0; i<snes->numbermonitors; i++) {
3766: if (snes->monitordestroy[i]) {
3767: (*snes->monitordestroy[i])(&snes->monitorcontext[i]);
3768: }
3769: }
3770: snes->numbermonitors = 0;
3771: return(0);
3772: }
3774: /*MC
3775: SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
3777: Synopsis:
3778: #include <petscsnes.h>
3779: $ PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx)
3781: + snes - the SNES context
3782: . it - current iteration (0 is the first and is before any Newton step)
3783: . cctx - [optional] convergence context
3784: . reason - reason for convergence/divergence
3785: . xnorm - 2-norm of current iterate
3786: . gnorm - 2-norm of current step
3787: - f - 2-norm of function
3789: Level: intermediate
3791: .seealso: SNESSetConvergenceTest(), SNESGetConvergenceTest()
3792: M*/
3794: /*@C
3795: SNESSetConvergenceTest - Sets the function that is to be used
3796: to test for convergence of the nonlinear iterative solution.
3798: Logically Collective on SNES
3800: Input Parameters:
3801: + snes - the SNES context
3802: . SNESConvergenceTestFunction - routine to test for convergence
3803: . cctx - [optional] context for private data for the convergence routine (may be NULL)
3804: - destroy - [optional] destructor for the context (may be NULL; NULL_FUNCTION in Fortran)
3806: Level: advanced
3808: .keywords: SNES, nonlinear, set, convergence, test
3810: .seealso: SNESConvergedDefault(), SNESConvergedSkip(), SNESConvergenceTestFunction
3811: @*/
3812: PetscErrorCode SNESSetConvergenceTest(SNES snes,PetscErrorCode (*SNESConvergenceTestFunction)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void *cctx,PetscErrorCode (*destroy)(void*))
3813: {
3818: if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
3819: if (snes->ops->convergeddestroy) {
3820: (*snes->ops->convergeddestroy)(snes->cnvP);
3821: }
3822: snes->ops->converged = SNESConvergenceTestFunction;
3823: snes->ops->convergeddestroy = destroy;
3824: snes->cnvP = cctx;
3825: return(0);
3826: }
3828: /*@
3829: SNESGetConvergedReason - Gets the reason the SNES iteration was stopped.
3831: Not Collective
3833: Input Parameter:
3834: . snes - the SNES context
3836: Output Parameter:
3837: . reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the
3838: manual pages for the individual convergence tests for complete lists
3840: Options Database:
3841: . -snes_converged_reason - prints the reason to standard out
3843: Level: intermediate
3845: Notes: Should only be called after the call the SNESSolve() is complete, if it is called earlier it returns the value SNES__CONVERGED_ITERATING.
3847: .keywords: SNES, nonlinear, set, convergence, test
3849: .seealso: SNESSetConvergenceTest(), SNESSetConvergedReason(), SNESConvergedReason
3850: @*/
3851: PetscErrorCode SNESGetConvergedReason(SNES snes,SNESConvergedReason *reason)
3852: {
3856: *reason = snes->reason;
3857: return(0);
3858: }
3860: /*@
3861: SNESSetConvergedReason - Sets the reason the SNES iteration was stopped.
3863: Not Collective
3865: Input Parameters:
3866: + snes - the SNES context
3867: - reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the
3868: manual pages for the individual convergence tests for complete lists
3870: Level: intermediate
3872: .keywords: SNES, nonlinear, set, convergence, test
3873: .seealso: SNESGetConvergedReason(), SNESSetConvergenceTest(), SNESConvergedReason
3874: @*/
3875: PetscErrorCode SNESSetConvergedReason(SNES snes,SNESConvergedReason reason)
3876: {
3879: snes->reason = reason;
3880: return(0);
3881: }
3883: /*@
3884: SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
3886: Logically Collective on SNES
3888: Input Parameters:
3889: + snes - iterative context obtained from SNESCreate()
3890: . a - array to hold history, this array will contain the function norms computed at each step
3891: . its - integer array holds the number of linear iterations for each solve.
3892: . na - size of a and its
3893: - reset - PETSC_TRUE indicates each new nonlinear solve resets the history counter to zero,
3894: else it continues storing new values for new nonlinear solves after the old ones
3896: Notes:
3897: If 'a' and 'its' are NULL then space is allocated for the history. If 'na' PETSC_DECIDE or PETSC_DEFAULT then a
3898: default array of length 10000 is allocated.
3900: This routine is useful, e.g., when running a code for purposes
3901: of accurate performance monitoring, when no I/O should be done
3902: during the section of code that is being timed.
3904: Level: intermediate
3906: .keywords: SNES, set, convergence, history
3908: .seealso: SNESGetConvergenceHistory()
3910: @*/
3911: PetscErrorCode SNESSetConvergenceHistory(SNES snes,PetscReal a[],PetscInt its[],PetscInt na,PetscBool reset)
3912: {
3919: if (!a) {
3920: if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
3921: PetscCalloc1(na,&a);
3922: PetscCalloc1(na,&its);
3924: snes->conv_malloc = PETSC_TRUE;
3925: }
3926: snes->conv_hist = a;
3927: snes->conv_hist_its = its;
3928: snes->conv_hist_max = na;
3929: snes->conv_hist_len = 0;
3930: snes->conv_hist_reset = reset;
3931: return(0);
3932: }
3934: #if defined(PETSC_HAVE_MATLAB_ENGINE)
3935: #include <engine.h> /* MATLAB include file */
3936: #include <mex.h> /* MATLAB include file */
3938: PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
3939: {
3940: mxArray *mat;
3941: PetscInt i;
3942: PetscReal *ar;
3945: mat = mxCreateDoubleMatrix(snes->conv_hist_len,1,mxREAL);
3946: ar = (PetscReal*) mxGetData(mat);
3947: for (i=0; i<snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
3948: PetscFunctionReturn(mat);
3949: }
3950: #endif
3952: /*@C
3953: SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
3955: Not Collective
3957: Input Parameter:
3958: . snes - iterative context obtained from SNESCreate()
3960: Output Parameters:
3961: . a - array to hold history
3962: . its - integer array holds the number of linear iterations (or
3963: negative if not converged) for each solve.
3964: - na - size of a and its
3966: Notes:
3967: The calling sequence for this routine in Fortran is
3968: $ call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
3970: This routine is useful, e.g., when running a code for purposes
3971: of accurate performance monitoring, when no I/O should be done
3972: during the section of code that is being timed.
3974: Level: intermediate
3976: .keywords: SNES, get, convergence, history
3978: .seealso: SNESSetConvergencHistory()
3980: @*/
3981: PetscErrorCode SNESGetConvergenceHistory(SNES snes,PetscReal *a[],PetscInt *its[],PetscInt *na)
3982: {
3985: if (a) *a = snes->conv_hist;
3986: if (its) *its = snes->conv_hist_its;
3987: if (na) *na = snes->conv_hist_len;
3988: return(0);
3989: }
3991: /*@C
3992: SNESSetUpdate - Sets the general-purpose update function called
3993: at the beginning of every iteration of the nonlinear solve. Specifically
3994: it is called just before the Jacobian is "evaluated".
3996: Logically Collective on SNES
3998: Input Parameters:
3999: . snes - The nonlinear solver context
4000: . func - The function
4002: Calling sequence of func:
4003: . func (SNES snes, PetscInt step);
4005: . step - The current step of the iteration
4007: Level: advanced
4009: 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()
4010: This is not used by most users.
4012: .keywords: SNES, update
4014: .seealso SNESSetJacobian(), SNESSolve()
4015: @*/
4016: PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
4017: {
4020: snes->ops->update = func;
4021: return(0);
4022: }
4024: /*
4025: SNESScaleStep_Private - Scales a step so that its length is less than the
4026: positive parameter delta.
4028: Input Parameters:
4029: + snes - the SNES context
4030: . y - approximate solution of linear system
4031: . fnorm - 2-norm of current function
4032: - delta - trust region size
4034: Output Parameters:
4035: + gpnorm - predicted function norm at the new point, assuming local
4036: linearization. The value is zero if the step lies within the trust
4037: region, and exceeds zero otherwise.
4038: - ynorm - 2-norm of the step
4040: Note:
4041: For non-trust region methods such as SNESNEWTONLS, the parameter delta
4042: is set to be the maximum allowable step size.
4044: .keywords: SNES, nonlinear, scale, step
4045: */
4046: PetscErrorCode SNESScaleStep_Private(SNES snes,Vec y,PetscReal *fnorm,PetscReal *delta,PetscReal *gpnorm,PetscReal *ynorm)
4047: {
4048: PetscReal nrm;
4049: PetscScalar cnorm;
4057: VecNorm(y,NORM_2,&nrm);
4058: if (nrm > *delta) {
4059: nrm = *delta/nrm;
4060: *gpnorm = (1.0 - nrm)*(*fnorm);
4061: cnorm = nrm;
4062: VecScale(y,cnorm);
4063: *ynorm = *delta;
4064: } else {
4065: *gpnorm = 0.0;
4066: *ynorm = nrm;
4067: }
4068: return(0);
4069: }
4071: /*@
4072: SNESReasonView - Displays the reason a SNES solve converged or diverged to a viewer
4074: Collective on SNES
4076: Parameter:
4077: + snes - iterative context obtained from SNESCreate()
4078: - viewer - the viewer to display the reason
4081: Options Database Keys:
4082: . -snes_converged_reason - print reason for converged or diverged, also prints number of iterations
4084: Level: beginner
4086: .keywords: SNES, solve, linear system
4088: .seealso: SNESCreate(), SNESSetUp(), SNESDestroy(), SNESSetTolerances(), SNESConvergedDefault()
4090: @*/
4091: PetscErrorCode SNESReasonView(SNES snes,PetscViewer viewer)
4092: {
4093: PetscViewerFormat format;
4094: PetscBool isAscii;
4095: PetscErrorCode ierr;
4098: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii);
4099: if (isAscii) {
4100: PetscViewerGetFormat(viewer, &format);
4101: PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
4102: if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
4103: DM dm;
4104: Vec u;
4105: PetscDS prob;
4106: PetscInt Nf, f;
4107: PetscErrorCode (**exactFuncs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
4108: PetscReal error;
4110: SNESGetDM(snes, &dm);
4111: SNESGetSolution(snes, &u);
4112: DMGetDS(dm, &prob);
4113: PetscDSGetNumFields(prob, &Nf);
4114: PetscMalloc1(Nf, &exactFuncs);
4115: for (f = 0; f < Nf; ++f) {PetscDSGetExactSolution(prob, f, &exactFuncs[f]);}
4116: DMComputeL2Diff(dm, 0.0, exactFuncs, NULL, u, &error);
4117: PetscFree(exactFuncs);
4118: if (error < 1.0e-11) {PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n");}
4119: else {PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", error);}
4120: }
4121: if (snes->reason > 0) {
4122: if (((PetscObject) snes)->prefix) {
4123: PetscViewerASCIIPrintf(viewer,"Nonlinear %s solve converged due to %s iterations %D\n",((PetscObject) snes)->prefix,SNESConvergedReasons[snes->reason],snes->iter);
4124: } else {
4125: PetscViewerASCIIPrintf(viewer,"Nonlinear solve converged due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);
4126: }
4127: } else {
4128: if (((PetscObject) snes)->prefix) {
4129: PetscViewerASCIIPrintf(viewer,"Nonlinear %s solve did not converge due to %s iterations %D\n",((PetscObject) snes)->prefix,SNESConvergedReasons[snes->reason],snes->iter);
4130: } else {
4131: PetscViewerASCIIPrintf(viewer,"Nonlinear solve did not converge due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);
4132: }
4133: }
4134: PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
4135: }
4136: return(0);
4137: }
4139: /*@C
4140: SNESReasonViewFromOptions - Processes command line options to determine if/how a SNESReason is to be viewed.
4142: Collective on SNES
4144: Input Parameters:
4145: . snes - the SNES object
4147: Level: intermediate
4149: @*/
4150: PetscErrorCode SNESReasonViewFromOptions(SNES snes)
4151: {
4152: PetscErrorCode ierr;
4153: PetscViewer viewer;
4154: PetscBool flg;
4155: static PetscBool incall = PETSC_FALSE;
4156: PetscViewerFormat format;
4159: if (incall) return(0);
4160: incall = PETSC_TRUE;
4161: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_converged_reason",&viewer,&format,&flg);
4162: if (flg) {
4163: PetscViewerPushFormat(viewer,format);
4164: SNESReasonView(snes,viewer);
4165: PetscViewerPopFormat(viewer);
4166: PetscViewerDestroy(&viewer);
4167: }
4168: incall = PETSC_FALSE;
4169: return(0);
4170: }
4172: /*@C
4173: SNESSolve - Solves a nonlinear system F(x) = b.
4174: Call SNESSolve() after calling SNESCreate() and optional routines of the form SNESSetXXX().
4176: Collective on SNES
4178: Input Parameters:
4179: + snes - the SNES context
4180: . b - the constant part of the equation F(x) = b, or NULL to use zero.
4181: - x - the solution vector.
4183: Notes:
4184: The user should initialize the vector,x, with the initial guess
4185: for the nonlinear solve prior to calling SNESSolve. In particular,
4186: to employ an initial guess of zero, the user should explicitly set
4187: this vector to zero by calling VecSet().
4189: Level: beginner
4191: .keywords: SNES, nonlinear, solve
4193: .seealso: SNESCreate(), SNESDestroy(), SNESSetFunction(), SNESSetJacobian(), SNESSetGridSequence(), SNESGetSolution()
4194: @*/
4195: PetscErrorCode SNESSolve(SNES snes,Vec b,Vec x)
4196: {
4197: PetscErrorCode ierr;
4198: PetscBool flg;
4199: PetscInt grid;
4200: Vec xcreated = NULL;
4201: DM dm;
4210: /* High level operations using the nonlinear solver */
4211: {
4212: PetscViewer viewer;
4213: PetscViewerFormat format;
4214: PetscInt num;
4215: PetscBool flg;
4216: static PetscBool incall = PETSC_FALSE;
4218: if (!incall) {
4219: /* Estimate the convergence rate of the discretization */
4220: PetscOptionsGetViewer(PetscObjectComm((PetscObject) snes), ((PetscObject) snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg);
4221: if (flg) {
4222: PetscConvEst conv;
4223: PetscReal alpha; /* Convergence rate of the solution error in the L_2 norm */
4225: incall = PETSC_TRUE;
4226: PetscConvEstCreate(PetscObjectComm((PetscObject) snes), &conv);
4227: PetscConvEstSetSolver(conv, snes);
4228: PetscConvEstSetFromOptions(conv);
4229: PetscConvEstSetUp(conv);
4230: PetscConvEstGetConvRate(conv, &alpha);
4231: PetscViewerPushFormat(viewer, format);
4232: PetscConvEstRateView(conv, alpha, viewer);
4233: PetscViewerPopFormat(viewer);
4234: PetscViewerDestroy(&viewer);
4235: PetscConvEstDestroy(&conv);
4236: incall = PETSC_FALSE;
4237: }
4238: /* Adaptively refine the initial grid */
4239: num = 1;
4240: PetscOptionsGetInt(NULL, ((PetscObject) snes)->prefix, "-snes_adapt_initial", &num, &flg);
4241: if (flg) {
4242: DMAdaptor adaptor;
4244: incall = PETSC_TRUE;
4245: DMAdaptorCreate(PETSC_COMM_WORLD, &adaptor);
4246: DMAdaptorSetSolver(adaptor, snes);
4247: DMAdaptorSetSequenceLength(adaptor, num);
4248: DMAdaptorSetFromOptions(adaptor);
4249: DMAdaptorSetUp(adaptor);
4250: DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x);
4251: DMAdaptorDestroy(&adaptor);
4252: incall = PETSC_FALSE;
4253: }
4254: /* Use grid sequencing to adapt */
4255: num = 0;
4256: PetscOptionsGetInt(NULL, ((PetscObject) snes)->prefix, "-snes_adapt_sequence", &num, NULL);
4257: if (num) {
4258: DMAdaptor adaptor;
4260: incall = PETSC_TRUE;
4261: DMAdaptorCreate(PETSC_COMM_WORLD, &adaptor);
4262: DMAdaptorSetSolver(adaptor, snes);
4263: DMAdaptorSetSequenceLength(adaptor, num);
4264: DMAdaptorSetFromOptions(adaptor);
4265: DMAdaptorSetUp(adaptor);
4266: DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x);
4267: DMAdaptorDestroy(&adaptor);
4268: incall = PETSC_FALSE;
4269: }
4270: }
4271: }
4272: if (!x) {
4273: SNESGetDM(snes,&dm);
4274: DMCreateGlobalVector(dm,&xcreated);
4275: x = xcreated;
4276: }
4277: SNESViewFromOptions(snes,NULL,"-snes_view_pre");
4279: for (grid=0; grid<snes->gridsequence; grid++) {PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));}
4280: for (grid=0; grid<snes->gridsequence+1; grid++) {
4282: /* set solution vector */
4283: if (!grid) {PetscObjectReference((PetscObject)x);}
4284: VecDestroy(&snes->vec_sol);
4285: snes->vec_sol = x;
4286: SNESGetDM(snes,&dm);
4288: /* set affine vector if provided */
4289: if (b) { PetscObjectReference((PetscObject)b); }
4290: VecDestroy(&snes->vec_rhs);
4291: snes->vec_rhs = b;
4293: if (snes->vec_func == snes->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"Solution vector cannot be function vector");
4294: if (snes->vec_rhs == snes->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"Solution vector cannot be right hand side vector");
4295: if (!snes->vec_sol_update /* && snes->vec_sol */) {
4296: VecDuplicate(snes->vec_sol,&snes->vec_sol_update);
4297: PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->vec_sol_update);
4298: }
4299: DMShellSetGlobalVector(dm,snes->vec_sol);
4300: SNESSetUp(snes);
4302: if (!grid) {
4303: if (snes->ops->computeinitialguess) {
4304: (*snes->ops->computeinitialguess)(snes,snes->vec_sol,snes->initialguessP);
4305: }
4306: }
4308: if (snes->conv_hist_reset) snes->conv_hist_len = 0;
4309: if (snes->counters_reset) {snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;}
4311: PetscLogEventBegin(SNES_Solve,snes,0,0,0);
4312: (*snes->ops->solve)(snes);
4313: PetscLogEventEnd(SNES_Solve,snes,0,0,0);
4314: if (!snes->reason) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");
4315: snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
4317: if (snes->lagjac_persist) snes->jac_iter += snes->iter;
4318: if (snes->lagpre_persist) snes->pre_iter += snes->iter;
4320: PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->prefix,"-snes_test_local_min",NULL,NULL,&flg);
4321: if (flg && !PetscPreLoadingOn) { SNESTestLocalMin(snes); }
4322: SNESReasonViewFromOptions(snes);
4324: if (snes->errorifnotconverged && snes->reason < 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_NOT_CONVERGED,"SNESSolve has not converged");
4325: if (snes->reason < 0) break;
4326: if (grid < snes->gridsequence) {
4327: DM fine;
4328: Vec xnew;
4329: Mat interp;
4331: DMRefine(snes->dm,PetscObjectComm((PetscObject)snes),&fine);
4332: if (!fine) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"DMRefine() did not perform any refinement, cannot continue grid sequencing");
4333: DMCreateInterpolation(snes->dm,fine,&interp,NULL);
4334: DMCreateGlobalVector(fine,&xnew);
4335: MatInterpolate(interp,x,xnew);
4336: DMInterpolate(snes->dm,interp,fine);
4337: MatDestroy(&interp);
4338: x = xnew;
4340: SNESReset(snes);
4341: SNESSetDM(snes,fine);
4342: DMDestroy(&fine);
4343: PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));
4344: }
4345: }
4346: SNESViewFromOptions(snes,NULL,"-snes_view");
4347: VecViewFromOptions(snes->vec_sol,(PetscObject)snes,"-snes_view_solution");
4349: VecDestroy(&xcreated);
4350: PetscObjectSAWsBlock((PetscObject)snes);
4351: return(0);
4352: }
4354: /* --------- Internal routines for SNES Package --------- */
4356: /*@C
4357: SNESSetType - Sets the method for the nonlinear solver.
4359: Collective on SNES
4361: Input Parameters:
4362: + snes - the SNES context
4363: - type - a known method
4365: Options Database Key:
4366: . -snes_type <type> - Sets the method; use -help for a list
4367: of available methods (for instance, newtonls or newtontr)
4369: Notes:
4370: See "petsc/include/petscsnes.h" for available methods (for instance)
4371: + SNESNEWTONLS - Newton's method with line search
4372: (systems of nonlinear equations)
4373: . SNESNEWTONTR - Newton's method with trust region
4374: (systems of nonlinear equations)
4376: Normally, it is best to use the SNESSetFromOptions() command and then
4377: set the SNES solver type from the options database rather than by using
4378: this routine. Using the options database provides the user with
4379: maximum flexibility in evaluating the many nonlinear solvers.
4380: The SNESSetType() routine is provided for those situations where it
4381: is necessary to set the nonlinear solver independently of the command
4382: line or options database. This might be the case, for example, when
4383: the choice of solver changes during the execution of the program,
4384: and the user's application is taking responsibility for choosing the
4385: appropriate method.
4387: Developer Notes: SNESRegister() adds a constructor for a new SNESType to SNESList, SNESSetType() locates
4388: the constructor in that list and calls it to create the spexific object.
4390: Level: intermediate
4392: .keywords: SNES, set, type
4394: .seealso: SNESType, SNESCreate(), SNESDestroy(), SNESGetType(), SNESSetFromOptions()
4396: @*/
4397: PetscErrorCode SNESSetType(SNES snes,SNESType type)
4398: {
4399: PetscErrorCode ierr,(*r)(SNES);
4400: PetscBool match;
4406: PetscObjectTypeCompare((PetscObject)snes,type,&match);
4407: if (match) return(0);
4409: PetscFunctionListFind(SNESList,type,&r);
4410: if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested SNES type %s",type);
4411: /* Destroy the previous private SNES context */
4412: if (snes->ops->destroy) {
4413: (*(snes)->ops->destroy)(snes);
4414: snes->ops->destroy = NULL;
4415: }
4416: /* Reinitialize function pointers in SNESOps structure */
4417: snes->ops->setup = 0;
4418: snes->ops->solve = 0;
4419: snes->ops->view = 0;
4420: snes->ops->setfromoptions = 0;
4421: snes->ops->destroy = 0;
4422: /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
4423: snes->setupcalled = PETSC_FALSE;
4425: PetscObjectChangeTypeName((PetscObject)snes,type);
4426: (*r)(snes);
4427: return(0);
4428: }
4430: /*@C
4431: SNESGetType - Gets the SNES method type and name (as a string).
4433: Not Collective
4435: Input Parameter:
4436: . snes - nonlinear solver context
4438: Output Parameter:
4439: . type - SNES method (a character string)
4441: Level: intermediate
4443: .keywords: SNES, nonlinear, get, type, name
4444: @*/
4445: PetscErrorCode SNESGetType(SNES snes,SNESType *type)
4446: {
4450: *type = ((PetscObject)snes)->type_name;
4451: return(0);
4452: }
4454: /*@
4455: SNESSetSolution - Sets the solution vector for use by the SNES routines.
4457: Logically Collective on SNES and Vec
4459: Input Parameters:
4460: + snes - the SNES context obtained from SNESCreate()
4461: - u - the solution vector
4463: Level: beginner
4465: .keywords: SNES, set, solution
4466: @*/
4467: PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4468: {
4469: DM dm;
4475: PetscObjectReference((PetscObject) u);
4476: VecDestroy(&snes->vec_sol);
4478: snes->vec_sol = u;
4480: SNESGetDM(snes, &dm);
4481: DMShellSetGlobalVector(dm, u);
4482: return(0);
4483: }
4485: /*@
4486: SNESGetSolution - Returns the vector where the approximate solution is
4487: stored. This is the fine grid solution when using SNESSetGridSequence().
4489: Not Collective, but Vec is parallel if SNES is parallel
4491: Input Parameter:
4492: . snes - the SNES context
4494: Output Parameter:
4495: . x - the solution
4497: Level: intermediate
4499: .keywords: SNES, nonlinear, get, solution
4501: .seealso: SNESGetSolutionUpdate(), SNESGetFunction()
4502: @*/
4503: PetscErrorCode SNESGetSolution(SNES snes,Vec *x)
4504: {
4508: *x = snes->vec_sol;
4509: return(0);
4510: }
4512: /*@
4513: SNESGetSolutionUpdate - Returns the vector where the solution update is
4514: stored.
4516: Not Collective, but Vec is parallel if SNES is parallel
4518: Input Parameter:
4519: . snes - the SNES context
4521: Output Parameter:
4522: . x - the solution update
4524: Level: advanced
4526: .keywords: SNES, nonlinear, get, solution, update
4528: .seealso: SNESGetSolution(), SNESGetFunction()
4529: @*/
4530: PetscErrorCode SNESGetSolutionUpdate(SNES snes,Vec *x)
4531: {
4535: *x = snes->vec_sol_update;
4536: return(0);
4537: }
4539: /*@C
4540: SNESGetFunction - Returns the vector where the function is stored.
4542: Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet.
4544: Input Parameter:
4545: . snes - the SNES context
4547: Output Parameter:
4548: + r - the vector that is used to store residuals (or NULL if you don't want it)
4549: . f - the function (or NULL if you don't want it); see SNESFunction for calling sequence details
4550: - ctx - the function context (or NULL if you don't want it)
4552: Level: advanced
4554: .keywords: SNES, nonlinear, get, function
4556: .seealso: SNESSetFunction(), SNESGetSolution(), SNESFunction
4557: @*/
4558: PetscErrorCode SNESGetFunction(SNES snes,Vec *r,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx)
4559: {
4561: DM dm;
4565: if (r) {
4566: if (!snes->vec_func) {
4567: if (snes->vec_rhs) {
4568: VecDuplicate(snes->vec_rhs,&snes->vec_func);
4569: } else if (snes->vec_sol) {
4570: VecDuplicate(snes->vec_sol,&snes->vec_func);
4571: } else if (snes->dm) {
4572: DMCreateGlobalVector(snes->dm,&snes->vec_func);
4573: }
4574: }
4575: *r = snes->vec_func;
4576: }
4577: SNESGetDM(snes,&dm);
4578: DMSNESGetFunction(dm,f,ctx);
4579: return(0);
4580: }
4582: /*@C
4583: SNESGetNGS - Returns the NGS function and context.
4585: Input Parameter:
4586: . snes - the SNES context
4588: Output Parameter:
4589: + f - the function (or NULL) see SNESNGSFunction for details
4590: - ctx - the function context (or NULL)
4592: Level: advanced
4594: .keywords: SNES, nonlinear, get, function
4596: .seealso: SNESSetNGS(), SNESGetFunction()
4597: @*/
4599: PetscErrorCode SNESGetNGS (SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void*), void ** ctx)
4600: {
4602: DM dm;
4606: SNESGetDM(snes,&dm);
4607: DMSNESGetNGS(dm,f,ctx);
4608: return(0);
4609: }
4611: /*@C
4612: SNESSetOptionsPrefix - Sets the prefix used for searching for all
4613: SNES options in the database.
4615: Logically Collective on SNES
4617: Input Parameter:
4618: + snes - the SNES context
4619: - prefix - the prefix to prepend to all option names
4621: Notes:
4622: A hyphen (-) must NOT be given at the beginning of the prefix name.
4623: The first character of all runtime options is AUTOMATICALLY the hyphen.
4625: Level: advanced
4627: .keywords: SNES, set, options, prefix, database
4629: .seealso: SNESSetFromOptions()
4630: @*/
4631: PetscErrorCode SNESSetOptionsPrefix(SNES snes,const char prefix[])
4632: {
4637: PetscObjectSetOptionsPrefix((PetscObject)snes,prefix);
4638: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
4639: if (snes->linesearch) {
4640: SNESGetLineSearch(snes,&snes->linesearch);
4641: PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch,prefix);
4642: }
4643: KSPSetOptionsPrefix(snes->ksp,prefix);
4644: return(0);
4645: }
4647: /*@C
4648: SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
4649: SNES options in the database.
4651: Logically Collective on SNES
4653: Input Parameters:
4654: + snes - the SNES context
4655: - prefix - the prefix to prepend to all option names
4657: Notes:
4658: A hyphen (-) must NOT be given at the beginning of the prefix name.
4659: The first character of all runtime options is AUTOMATICALLY the hyphen.
4661: Level: advanced
4663: .keywords: SNES, append, options, prefix, database
4665: .seealso: SNESGetOptionsPrefix()
4666: @*/
4667: PetscErrorCode SNESAppendOptionsPrefix(SNES snes,const char prefix[])
4668: {
4673: PetscObjectAppendOptionsPrefix((PetscObject)snes,prefix);
4674: if (!snes->ksp) {SNESGetKSP(snes,&snes->ksp);}
4675: if (snes->linesearch) {
4676: SNESGetLineSearch(snes,&snes->linesearch);
4677: PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch,prefix);
4678: }
4679: KSPAppendOptionsPrefix(snes->ksp,prefix);
4680: return(0);
4681: }
4683: /*@C
4684: SNESGetOptionsPrefix - Sets the prefix used for searching for all
4685: SNES options in the database.
4687: Not Collective
4689: Input Parameter:
4690: . snes - the SNES context
4692: Output Parameter:
4693: . prefix - pointer to the prefix string used
4695: Notes: On the fortran side, the user should pass in a string 'prefix' of
4696: sufficient length to hold the prefix.
4698: Level: advanced
4700: .keywords: SNES, get, options, prefix, database
4702: .seealso: SNESAppendOptionsPrefix()
4703: @*/
4704: PetscErrorCode SNESGetOptionsPrefix(SNES snes,const char *prefix[])
4705: {
4710: PetscObjectGetOptionsPrefix((PetscObject)snes,prefix);
4711: return(0);
4712: }
4715: /*@C
4716: SNESRegister - Adds a method to the nonlinear solver package.
4718: Not collective
4720: Input Parameters:
4721: + name_solver - name of a new user-defined solver
4722: - routine_create - routine to create method context
4724: Notes:
4725: SNESRegister() may be called multiple times to add several user-defined solvers.
4727: Sample usage:
4728: .vb
4729: SNESRegister("my_solver",MySolverCreate);
4730: .ve
4732: Then, your solver can be chosen with the procedural interface via
4733: $ SNESSetType(snes,"my_solver")
4734: or at runtime via the option
4735: $ -snes_type my_solver
4737: Level: advanced
4739: Note: If your function is not being put into a shared library then use SNESRegister() instead
4741: .keywords: SNES, nonlinear, register
4743: .seealso: SNESRegisterAll(), SNESRegisterDestroy()
4745: Level: advanced
4746: @*/
4747: PetscErrorCode SNESRegister(const char sname[],PetscErrorCode (*function)(SNES))
4748: {
4752: PetscFunctionListAdd(&SNESList,sname,function);
4753: return(0);
4754: }
4756: PetscErrorCode SNESTestLocalMin(SNES snes)
4757: {
4759: PetscInt N,i,j;
4760: Vec u,uh,fh;
4761: PetscScalar value;
4762: PetscReal norm;
4765: SNESGetSolution(snes,&u);
4766: VecDuplicate(u,&uh);
4767: VecDuplicate(u,&fh);
4769: /* currently only works for sequential */
4770: PetscPrintf(PETSC_COMM_WORLD,"Testing FormFunction() for local min\n");
4771: VecGetSize(u,&N);
4772: for (i=0; i<N; i++) {
4773: VecCopy(u,uh);
4774: PetscPrintf(PETSC_COMM_WORLD,"i = %D\n",i);
4775: for (j=-10; j<11; j++) {
4776: value = PetscSign(j)*PetscExpReal(PetscAbs(j)-10.0);
4777: VecSetValue(uh,i,value,ADD_VALUES);
4778: SNESComputeFunction(snes,uh,fh);
4779: VecNorm(fh,NORM_2,&norm);
4780: PetscPrintf(PETSC_COMM_WORLD," j norm %D %18.16e\n",j,norm);
4781: value = -value;
4782: VecSetValue(uh,i,value,ADD_VALUES);
4783: }
4784: }
4785: VecDestroy(&uh);
4786: VecDestroy(&fh);
4787: return(0);
4788: }
4790: /*@
4791: SNESKSPSetUseEW - Sets SNES use Eisenstat-Walker method for
4792: computing relative tolerance for linear solvers within an inexact
4793: Newton method.
4795: Logically Collective on SNES
4797: Input Parameters:
4798: + snes - SNES context
4799: - flag - PETSC_TRUE or PETSC_FALSE
4801: Options Database:
4802: + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
4803: . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
4804: . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
4805: . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
4806: . -snes_ksp_ew_gamma <gamma> - Sets gamma
4807: . -snes_ksp_ew_alpha <alpha> - Sets alpha
4808: . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
4809: - -snes_ksp_ew_threshold <threshold> - Sets threshold
4811: Notes:
4812: Currently, the default is to use a constant relative tolerance for
4813: the inner linear solvers. Alternatively, one can use the
4814: Eisenstat-Walker method, where the relative convergence tolerance
4815: is reset at each Newton iteration according progress of the nonlinear
4816: solver.
4818: Level: advanced
4820: Reference:
4821: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
4822: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
4824: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
4826: .seealso: SNESKSPGetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
4827: @*/
4828: PetscErrorCode SNESKSPSetUseEW(SNES snes,PetscBool flag)
4829: {
4833: snes->ksp_ewconv = flag;
4834: return(0);
4835: }
4837: /*@
4838: SNESKSPGetUseEW - Gets if SNES is using Eisenstat-Walker method
4839: for computing relative tolerance for linear solvers within an
4840: inexact Newton method.
4842: Not Collective
4844: Input Parameter:
4845: . snes - SNES context
4847: Output Parameter:
4848: . flag - PETSC_TRUE or PETSC_FALSE
4850: Notes:
4851: Currently, the default is to use a constant relative tolerance for
4852: the inner linear solvers. Alternatively, one can use the
4853: Eisenstat-Walker method, where the relative convergence tolerance
4854: is reset at each Newton iteration according progress of the nonlinear
4855: solver.
4857: Level: advanced
4859: Reference:
4860: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
4861: inexact Newton method", SISC 17 (1), pp.16-32, 1996.
4863: .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
4865: .seealso: SNESKSPSetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW()
4866: @*/
4867: PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
4868: {
4872: *flag = snes->ksp_ewconv;
4873: return(0);
4874: }
4876: /*@
4877: SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
4878: convergence criteria for the linear solvers within an inexact
4879: Newton method.
4881: Logically Collective on SNES
4883: Input Parameters:
4884: + snes - SNES context
4885: . version - version 1, 2 (default is 2) or 3
4886: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
4887: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
4888: . gamma - multiplicative factor for version 2 rtol computation
4889: (0 <= gamma2 <= 1)
4890: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
4891: . alpha2 - power for safeguard
4892: - threshold - threshold for imposing safeguard (0 < threshold < 1)
4894: Note:
4895: Version 3 was contributed by Luis Chacon, June 2006.
4897: Use PETSC_DEFAULT to retain the default for any of the parameters.
4899: Level: advanced
4901: Reference:
4902: S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
4903: inexact Newton method", Utah State University Math. Stat. Dept. Res.
4904: Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
4906: .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
4908: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPGetParametersEW()
4909: @*/
4910: PetscErrorCode SNESKSPSetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,PetscReal gamma,PetscReal alpha,PetscReal alpha2,PetscReal threshold)
4911: {
4912: SNESKSPEW *kctx;
4916: kctx = (SNESKSPEW*)snes->kspconvctx;
4917: if (!kctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
4926: if (version != PETSC_DEFAULT) kctx->version = version;
4927: if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
4928: if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max;
4929: if (gamma != PETSC_DEFAULT) kctx->gamma = gamma;
4930: if (alpha != PETSC_DEFAULT) kctx->alpha = alpha;
4931: if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2;
4932: if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
4934: 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);
4935: 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",(double)kctx->rtol_0);
4936: 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",(double)kctx->rtol_max);
4937: if (kctx->gamma < 0.0 || kctx->gamma > 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%g) <= 1.0\n",(double)kctx->gamma);
4938: if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%g) <= 2.0\n",(double)kctx->alpha);
4939: if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%g) < 1.0\n",(double)kctx->threshold);
4940: return(0);
4941: }
4943: /*@
4944: SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
4945: convergence criteria for the linear solvers within an inexact
4946: Newton method.
4948: Not Collective
4950: Input Parameters:
4951: snes - SNES context
4953: Output Parameters:
4954: + version - version 1, 2 (default is 2) or 3
4955: . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
4956: . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
4957: . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
4958: . alpha - power for version 2 rtol computation (1 < alpha <= 2)
4959: . alpha2 - power for safeguard
4960: - threshold - threshold for imposing safeguard (0 < threshold < 1)
4962: Level: advanced
4964: .keywords: SNES, KSP, Eisenstat, Walker, get, parameters
4966: .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPSetParametersEW()
4967: @*/
4968: PetscErrorCode SNESKSPGetParametersEW(SNES snes,PetscInt *version,PetscReal *rtol_0,PetscReal *rtol_max,PetscReal *gamma,PetscReal *alpha,PetscReal *alpha2,PetscReal *threshold)
4969: {
4970: SNESKSPEW *kctx;
4974: kctx = (SNESKSPEW*)snes->kspconvctx;
4975: if (!kctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
4976: if (version) *version = kctx->version;
4977: if (rtol_0) *rtol_0 = kctx->rtol_0;
4978: if (rtol_max) *rtol_max = kctx->rtol_max;
4979: if (gamma) *gamma = kctx->gamma;
4980: if (alpha) *alpha = kctx->alpha;
4981: if (alpha2) *alpha2 = kctx->alpha2;
4982: if (threshold) *threshold = kctx->threshold;
4983: return(0);
4984: }
4986: PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
4987: {
4989: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
4990: PetscReal rtol = PETSC_DEFAULT,stol;
4993: if (!snes->ksp_ewconv) return(0);
4994: if (!snes->iter) {
4995: rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
4996: VecNorm(snes->vec_func,NORM_2,&kctx->norm_first);
4997: }
4998: else {
4999: if (kctx->version == 1) {
5000: rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
5001: if (rtol < 0.0) rtol = -rtol;
5002: stol = PetscPowReal(kctx->rtol_last,kctx->alpha2);
5003: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
5004: } else if (kctx->version == 2) {
5005: rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha);
5006: stol = kctx->gamma * PetscPowReal(kctx->rtol_last,kctx->alpha);
5007: if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
5008: } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
5009: rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha);
5010: /* safeguard: avoid sharp decrease of rtol */
5011: stol = kctx->gamma*PetscPowReal(kctx->rtol_last,kctx->alpha);
5012: stol = PetscMax(rtol,stol);
5013: rtol = PetscMin(kctx->rtol_0,stol);
5014: /* safeguard: avoid oversolving */
5015: stol = kctx->gamma*(kctx->norm_first*snes->rtol)/snes->norm;
5016: stol = PetscMax(rtol,stol);
5017: rtol = PetscMin(kctx->rtol_0,stol);
5018: } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 or 3 are supported: %D",kctx->version);
5019: }
5020: /* safeguard: avoid rtol greater than one */
5021: rtol = PetscMin(rtol,kctx->rtol_max);
5022: KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
5023: PetscInfo3(snes,"iter %D, Eisenstat-Walker (version %D) KSP rtol=%g\n",snes->iter,kctx->version,(double)rtol);
5024: return(0);
5025: }
5027: PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5028: {
5030: SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx;
5031: PCSide pcside;
5032: Vec lres;
5035: if (!snes->ksp_ewconv) return(0);
5036: KSPGetTolerances(ksp,&kctx->rtol_last,0,0,0);
5037: kctx->norm_last = snes->norm;
5038: if (kctx->version == 1) {
5039: PC pc;
5040: PetscBool isNone;
5042: KSPGetPC(ksp, &pc);
5043: PetscObjectTypeCompare((PetscObject) pc, PCNONE, &isNone);
5044: KSPGetPCSide(ksp,&pcside);
5045: if (pcside == PC_RIGHT || isNone) { /* XXX Should we also test KSP_UNPRECONDITIONED_NORM ? */
5046: /* KSP residual is true linear residual */
5047: KSPGetResidualNorm(ksp,&kctx->lresid_last);
5048: } else {
5049: /* KSP residual is preconditioned residual */
5050: /* compute true linear residual norm */
5051: VecDuplicate(b,&lres);
5052: MatMult(snes->jacobian,x,lres);
5053: VecAYPX(lres,-1.0,b);
5054: VecNorm(lres,NORM_2,&kctx->lresid_last);
5055: VecDestroy(&lres);
5056: }
5057: }
5058: return(0);
5059: }
5061: /*@
5062: SNESGetKSP - Returns the KSP context for a SNES solver.
5064: Not Collective, but if SNES object is parallel, then KSP object is parallel
5066: Input Parameter:
5067: . snes - the SNES context
5069: Output Parameter:
5070: . ksp - the KSP context
5072: Notes:
5073: The user can then directly manipulate the KSP context to set various
5074: options, etc. Likewise, the user can then extract and manipulate the
5075: PC contexts as well.
5077: Level: beginner
5079: .keywords: SNES, nonlinear, get, KSP, context
5081: .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP()
5082: @*/
5083: PetscErrorCode SNESGetKSP(SNES snes,KSP *ksp)
5084: {
5091: if (!snes->ksp) {
5092: PetscBool monitor = PETSC_FALSE;
5094: KSPCreate(PetscObjectComm((PetscObject)snes),&snes->ksp);
5095: PetscObjectIncrementTabLevel((PetscObject)snes->ksp,(PetscObject)snes,1);
5096: PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->ksp);
5098: KSPSetPreSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))KSPPreSolve_SNESEW,snes);
5099: KSPSetPostSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))KSPPostSolve_SNESEW,snes);
5101: PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-ksp_monitor_snes",&monitor,NULL);
5102: if (monitor) {
5103: KSPMonitorSet(snes->ksp,KSPMonitorSNES,snes,NULL);
5104: }
5105: monitor = PETSC_FALSE;
5106: PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-ksp_monitor_snes_lg",&monitor,NULL);
5107: if (monitor) {
5108: PetscObject *objs;
5109: KSPMonitorSNESLGResidualNormCreate(PetscObjectComm((PetscObject)snes),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,600,&objs);
5110: objs[0] = (PetscObject) snes;
5111: KSPMonitorSet(snes->ksp,(PetscErrorCode (*)(KSP,PetscInt,PetscReal,void*))KSPMonitorSNESLGResidualNorm,objs,(PetscErrorCode (*)(void**))KSPMonitorSNESLGResidualNormDestroy);
5112: }
5113: }
5114: *ksp = snes->ksp;
5115: return(0);
5116: }
5119: #include <petsc/private/dmimpl.h>
5120: /*@
5121: SNESSetDM - Sets the DM that may be used by some nonlinear solvers or their underlying preconditioners
5123: Logically Collective on SNES
5125: Input Parameters:
5126: + snes - the nonlinear solver context
5127: - dm - the dm, cannot be NULL
5129: Level: intermediate
5131: .seealso: SNESGetDM(), KSPSetDM(), KSPGetDM()
5132: @*/
5133: PetscErrorCode SNESSetDM(SNES snes,DM dm)
5134: {
5136: KSP ksp;
5137: DMSNES sdm;
5142: PetscObjectReference((PetscObject)dm);
5143: if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
5144: if (snes->dm->dmsnes && !dm->dmsnes) {
5145: DMCopyDMSNES(snes->dm,dm);
5146: DMGetDMSNES(snes->dm,&sdm);
5147: if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
5148: }
5149: DMCoarsenHookRemove(snes->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,snes);
5150: DMDestroy(&snes->dm);
5151: }
5152: snes->dm = dm;
5153: snes->dmAuto = PETSC_FALSE;
5155: SNESGetKSP(snes,&ksp);
5156: KSPSetDM(ksp,dm);
5157: KSPSetDMActive(ksp,PETSC_FALSE);
5158: if (snes->npc) {
5159: SNESSetDM(snes->npc, snes->dm);
5160: SNESSetNPCSide(snes,snes->npcside);
5161: }
5162: return(0);
5163: }
5165: /*@
5166: SNESGetDM - Gets the DM that may be used by some preconditioners
5168: Not Collective but DM obtained is parallel on SNES
5170: Input Parameter:
5171: . snes - the preconditioner context
5173: Output Parameter:
5174: . dm - the dm
5176: Level: intermediate
5178: .seealso: SNESSetDM(), KSPSetDM(), KSPGetDM()
5179: @*/
5180: PetscErrorCode SNESGetDM(SNES snes,DM *dm)
5181: {
5186: if (!snes->dm) {
5187: DMShellCreate(PetscObjectComm((PetscObject)snes),&snes->dm);
5188: snes->dmAuto = PETSC_TRUE;
5189: }
5190: *dm = snes->dm;
5191: return(0);
5192: }
5194: /*@
5195: SNESSetNPC - Sets the nonlinear preconditioner to be used.
5197: Collective on SNES
5199: Input Parameters:
5200: + snes - iterative context obtained from SNESCreate()
5201: - pc - the preconditioner object
5203: Notes:
5204: Use SNESGetNPC() to retrieve the preconditioner context (for example,
5205: to configure it using the API).
5207: Level: developer
5209: .keywords: SNES, set, precondition
5210: .seealso: SNESGetNPC(), SNESHasNPC()
5211: @*/
5212: PetscErrorCode SNESSetNPC(SNES snes, SNES pc)
5213: {
5220: PetscObjectReference((PetscObject) pc);
5221: SNESDestroy(&snes->npc);
5222: snes->npc = pc;
5223: PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->npc);
5224: return(0);
5225: }
5227: /*@
5228: SNESGetNPC - Creates a nonlinear preconditioning solver (SNES) to be used to precondition the nonlinear solver.
5230: Not Collective
5232: Input Parameter:
5233: . snes - iterative context obtained from SNESCreate()
5235: Output Parameter:
5236: . pc - preconditioner context
5238: Notes: If a SNES was previously set with SNESSetNPC() then that SNES is returned.
5240: Level: developer
5242: .keywords: SNES, get, preconditioner
5243: .seealso: SNESSetNPC(), SNESHasNPC()
5244: @*/
5245: PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5246: {
5248: const char *optionsprefix;
5253: if (!snes->npc) {
5254: SNESCreate(PetscObjectComm((PetscObject)snes),&snes->npc);
5255: PetscObjectIncrementTabLevel((PetscObject)snes->npc,(PetscObject)snes,1);
5256: PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->npc);
5257: SNESGetOptionsPrefix(snes,&optionsprefix);
5258: SNESSetOptionsPrefix(snes->npc,optionsprefix);
5259: SNESAppendOptionsPrefix(snes->npc,"npc_");
5260: SNESSetCountersReset(snes->npc,PETSC_FALSE);
5261: }
5262: *pc = snes->npc;
5263: return(0);
5264: }
5266: /*@
5267: SNESHasNPC - Returns whether a nonlinear preconditioner exists
5269: Not Collective
5271: Input Parameter:
5272: . snes - iterative context obtained from SNESCreate()
5274: Output Parameter:
5275: . has_npc - whether the SNES has an NPC or not
5277: Level: developer
5279: .keywords: SNES, has, preconditioner
5280: .seealso: SNESSetNPC(), SNESGetNPC()
5281: @*/
5282: PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5283: {
5286: *has_npc = (PetscBool) (snes->npc ? PETSC_TRUE : PETSC_FALSE);
5287: return(0);
5288: }
5290: /*@
5291: SNESSetNPCSide - Sets the preconditioning side.
5293: Logically Collective on SNES
5295: Input Parameter:
5296: . snes - iterative context obtained from SNESCreate()
5298: Output Parameter:
5299: . side - the preconditioning side, where side is one of
5300: .vb
5301: PC_LEFT - left preconditioning
5302: PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5303: .ve
5305: Options Database Keys:
5306: . -snes_pc_side <right,left>
5308: Notes: SNESNRICHARDSON and SNESNCG only support left preconditioning.
5310: Level: intermediate
5312: .keywords: SNES, set, right, left, side, preconditioner, flag
5314: .seealso: SNESGetNPCSide(), KSPSetPCSide()
5315: @*/
5316: PetscErrorCode SNESSetNPCSide(SNES snes,PCSide side)
5317: {
5321: snes->npcside= side;
5322: return(0);
5323: }
5325: /*@
5326: SNESGetNPCSide - Gets the preconditioning side.
5328: Not Collective
5330: Input Parameter:
5331: . snes - iterative context obtained from SNESCreate()
5333: Output Parameter:
5334: . side - the preconditioning side, where side is one of
5335: .vb
5336: PC_LEFT - left preconditioning
5337: PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5338: .ve
5340: Level: intermediate
5342: .keywords: SNES, get, right, left, side, preconditioner, flag
5344: .seealso: SNESSetNPCSide(), KSPGetPCSide()
5345: @*/
5346: PetscErrorCode SNESGetNPCSide(SNES snes,PCSide *side)
5347: {
5351: *side = snes->npcside;
5352: return(0);
5353: }
5355: /*@
5356: SNESSetLineSearch - Sets the linesearch on the SNES instance.
5358: Collective on SNES
5360: Input Parameters:
5361: + snes - iterative context obtained from SNESCreate()
5362: - linesearch - the linesearch object
5364: Notes:
5365: Use SNESGetLineSearch() to retrieve the preconditioner context (for example,
5366: to configure it using the API).
5368: Level: developer
5370: .keywords: SNES, set, linesearch
5371: .seealso: SNESGetLineSearch()
5372: @*/
5373: PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5374: {
5381: PetscObjectReference((PetscObject) linesearch);
5382: SNESLineSearchDestroy(&snes->linesearch);
5384: snes->linesearch = linesearch;
5386: PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->linesearch);
5387: return(0);
5388: }
5390: /*@
5391: SNESGetLineSearch - Returns a pointer to the line search context set with SNESSetLineSearch()
5392: or creates a default line search instance associated with the SNES and returns it.
5394: Not Collective
5396: Input Parameter:
5397: . snes - iterative context obtained from SNESCreate()
5399: Output Parameter:
5400: . linesearch - linesearch context
5402: Level: beginner
5404: .keywords: SNES, get, linesearch
5405: .seealso: SNESSetLineSearch(), SNESLineSearchCreate()
5406: @*/
5407: PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5408: {
5410: const char *optionsprefix;
5415: if (!snes->linesearch) {
5416: SNESGetOptionsPrefix(snes, &optionsprefix);
5417: SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch);
5418: SNESLineSearchSetSNES(snes->linesearch, snes);
5419: SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix);
5420: PetscObjectIncrementTabLevel((PetscObject) snes->linesearch, (PetscObject) snes, 1);
5421: PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->linesearch);
5422: }
5423: *linesearch = snes->linesearch;
5424: return(0);
5425: }
5427: #if defined(PETSC_HAVE_MATLAB_ENGINE)
5428: #include <mex.h>
5430: typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
5432: /*
5433: SNESComputeFunction_Matlab - Calls the function that has been set with SNESSetFunctionMatlab().
5435: Collective on SNES
5437: Input Parameters:
5438: + snes - the SNES context
5439: - x - input vector
5441: Output Parameter:
5442: . y - function vector, as set by SNESSetFunction()
5444: Notes:
5445: SNESComputeFunction() is typically used within nonlinear solvers
5446: implementations, so most users would not generally call this routine
5447: themselves.
5449: Level: developer
5451: .keywords: SNES, nonlinear, compute, function
5453: .seealso: SNESSetFunction(), SNESGetFunction()
5454: */
5455: PetscErrorCode SNESComputeFunction_Matlab(SNES snes,Vec x,Vec y, void *ctx)
5456: {
5457: PetscErrorCode ierr;
5458: SNESMatlabContext *sctx = (SNESMatlabContext*)ctx;
5459: int nlhs = 1,nrhs = 5;
5460: mxArray *plhs[1],*prhs[5];
5461: long long int lx = 0,ly = 0,ls = 0;
5470: /* call Matlab function in ctx with arguments x and y */
5472: PetscMemcpy(&ls,&snes,sizeof(snes));
5473: PetscMemcpy(&lx,&x,sizeof(x));
5474: PetscMemcpy(&ly,&y,sizeof(x));
5475: prhs[0] = mxCreateDoubleScalar((double)ls);
5476: prhs[1] = mxCreateDoubleScalar((double)lx);
5477: prhs[2] = mxCreateDoubleScalar((double)ly);
5478: prhs[3] = mxCreateString(sctx->funcname);
5479: prhs[4] = sctx->ctx;
5480: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESComputeFunctionInternal");
5481: mxGetScalar(plhs[0]);
5482: mxDestroyArray(prhs[0]);
5483: mxDestroyArray(prhs[1]);
5484: mxDestroyArray(prhs[2]);
5485: mxDestroyArray(prhs[3]);
5486: mxDestroyArray(plhs[0]);
5487: return(0);
5488: }
5490: /*
5491: SNESSetFunctionMatlab - Sets the function evaluation routine and function
5492: vector for use by the SNES routines in solving systems of nonlinear
5493: equations from MATLAB. Here the function is a string containing the name of a MATLAB function
5495: Logically Collective on SNES
5497: Input Parameters:
5498: + snes - the SNES context
5499: . r - vector to store function value
5500: - f - function evaluation routine
5502: Notes:
5503: The Newton-like methods typically solve linear systems of the form
5504: $ f'(x) x = -f(x),
5505: where f'(x) denotes the Jacobian matrix and f(x) is the function.
5507: Level: beginner
5509: Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx;
5511: .keywords: SNES, nonlinear, set, function
5513: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
5514: */
5515: PetscErrorCode SNESSetFunctionMatlab(SNES snes,Vec r,const char *f,mxArray *ctx)
5516: {
5517: PetscErrorCode ierr;
5518: SNESMatlabContext *sctx;
5521: /* currently sctx is memory bleed */
5522: PetscNew(&sctx);
5523: PetscStrallocpy(f,&sctx->funcname);
5524: /*
5525: This should work, but it doesn't
5526: sctx->ctx = ctx;
5527: mexMakeArrayPersistent(sctx->ctx);
5528: */
5529: sctx->ctx = mxDuplicateArray(ctx);
5530: SNESSetFunction(snes,r,SNESComputeFunction_Matlab,sctx);
5531: return(0);
5532: }
5534: /*
5535: SNESComputeJacobian_Matlab - Calls the function that has been set with SNESSetJacobianMatlab().
5537: Collective on SNES
5539: Input Parameters:
5540: + snes - the SNES context
5541: . x - input vector
5542: . A, B - the matrices
5543: - ctx - user context
5545: Level: developer
5547: .keywords: SNES, nonlinear, compute, function
5549: .seealso: SNESSetFunction(), SNESGetFunction()
5550: @*/
5551: PetscErrorCode SNESComputeJacobian_Matlab(SNES snes,Vec x,Mat A,Mat B,void *ctx)
5552: {
5553: PetscErrorCode ierr;
5554: SNESMatlabContext *sctx = (SNESMatlabContext*)ctx;
5555: int nlhs = 2,nrhs = 6;
5556: mxArray *plhs[2],*prhs[6];
5557: long long int lx = 0,lA = 0,ls = 0, lB = 0;
5563: /* call Matlab function in ctx with arguments x and y */
5565: PetscMemcpy(&ls,&snes,sizeof(snes));
5566: PetscMemcpy(&lx,&x,sizeof(x));
5567: PetscMemcpy(&lA,A,sizeof(x));
5568: PetscMemcpy(&lB,B,sizeof(x));
5569: prhs[0] = mxCreateDoubleScalar((double)ls);
5570: prhs[1] = mxCreateDoubleScalar((double)lx);
5571: prhs[2] = mxCreateDoubleScalar((double)lA);
5572: prhs[3] = mxCreateDoubleScalar((double)lB);
5573: prhs[4] = mxCreateString(sctx->funcname);
5574: prhs[5] = sctx->ctx;
5575: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESComputeJacobianInternal");
5576: mxGetScalar(plhs[0]);
5577: mxDestroyArray(prhs[0]);
5578: mxDestroyArray(prhs[1]);
5579: mxDestroyArray(prhs[2]);
5580: mxDestroyArray(prhs[3]);
5581: mxDestroyArray(prhs[4]);
5582: mxDestroyArray(plhs[0]);
5583: mxDestroyArray(plhs[1]);
5584: return(0);
5585: }
5587: /*
5588: SNESSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
5589: vector for use by the SNES routines in solving systems of nonlinear
5590: equations from MATLAB. Here the function is a string containing the name of a MATLAB function
5592: Logically Collective on SNES
5594: Input Parameters:
5595: + snes - the SNES context
5596: . A,B - Jacobian matrices
5597: . J - function evaluation routine
5598: - ctx - user context
5600: Level: developer
5602: Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx;
5604: .keywords: SNES, nonlinear, set, function
5606: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction(), J
5607: */
5608: PetscErrorCode SNESSetJacobianMatlab(SNES snes,Mat A,Mat B,const char *J,mxArray *ctx)
5609: {
5610: PetscErrorCode ierr;
5611: SNESMatlabContext *sctx;
5614: /* currently sctx is memory bleed */
5615: PetscNew(&sctx);
5616: PetscStrallocpy(J,&sctx->funcname);
5617: /*
5618: This should work, but it doesn't
5619: sctx->ctx = ctx;
5620: mexMakeArrayPersistent(sctx->ctx);
5621: */
5622: sctx->ctx = mxDuplicateArray(ctx);
5623: SNESSetJacobian(snes,A,B,SNESComputeJacobian_Matlab,sctx);
5624: return(0);
5625: }
5627: /*
5628: SNESMonitor_Matlab - Calls the function that has been set with SNESMonitorSetMatlab().
5630: Collective on SNES
5632: .seealso: SNESSetFunction(), SNESGetFunction()
5633: @*/
5634: PetscErrorCode SNESMonitor_Matlab(SNES snes,PetscInt it, PetscReal fnorm, void *ctx)
5635: {
5636: PetscErrorCode ierr;
5637: SNESMatlabContext *sctx = (SNESMatlabContext*)ctx;
5638: int nlhs = 1,nrhs = 6;
5639: mxArray *plhs[1],*prhs[6];
5640: long long int lx = 0,ls = 0;
5641: Vec x = snes->vec_sol;
5646: PetscMemcpy(&ls,&snes,sizeof(snes));
5647: PetscMemcpy(&lx,&x,sizeof(x));
5648: prhs[0] = mxCreateDoubleScalar((double)ls);
5649: prhs[1] = mxCreateDoubleScalar((double)it);
5650: prhs[2] = mxCreateDoubleScalar((double)fnorm);
5651: prhs[3] = mxCreateDoubleScalar((double)lx);
5652: prhs[4] = mxCreateString(sctx->funcname);
5653: prhs[5] = sctx->ctx;
5654: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESMonitorInternal");
5655: mxGetScalar(plhs[0]);
5656: mxDestroyArray(prhs[0]);
5657: mxDestroyArray(prhs[1]);
5658: mxDestroyArray(prhs[2]);
5659: mxDestroyArray(prhs[3]);
5660: mxDestroyArray(prhs[4]);
5661: mxDestroyArray(plhs[0]);
5662: return(0);
5663: }
5665: /*
5666: SNESMonitorSetMatlab - Sets the monitor function from MATLAB
5668: Level: developer
5670: Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx;
5672: .keywords: SNES, nonlinear, set, function
5674: .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction()
5675: */
5676: PetscErrorCode SNESMonitorSetMatlab(SNES snes,const char *f,mxArray *ctx)
5677: {
5678: PetscErrorCode ierr;
5679: SNESMatlabContext *sctx;
5682: /* currently sctx is memory bleed */
5683: PetscNew(&sctx);
5684: PetscStrallocpy(f,&sctx->funcname);
5685: /*
5686: This should work, but it doesn't
5687: sctx->ctx = ctx;
5688: mexMakeArrayPersistent(sctx->ctx);
5689: */
5690: sctx->ctx = mxDuplicateArray(ctx);
5691: SNESMonitorSet(snes,SNESMonitor_Matlab,sctx,NULL);
5692: return(0);
5693: }
5695: #endif