Actual source code: snesimpl.h
petsc-3.6.1 2015-08-06
2: #ifndef __SNESIMPL_H
5: #include <petscsnes.h>
6: #include <petsc/private/petscimpl.h>
8: PETSC_EXTERN PetscBool SNESRegisterAllCalled;
9: PETSC_EXTERN PetscErrorCode SNESRegisterAll(void);
11: typedef struct _SNESOps *SNESOps;
13: struct _SNESOps {
14: PetscErrorCode (*computeinitialguess)(SNES,Vec,void*);
15: PetscErrorCode (*computescaling)(Vec,Vec,void*);
16: PetscErrorCode (*update)(SNES, PetscInt); /* General purpose function for update */
17: PetscErrorCode (*converged)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*);
18: PetscErrorCode (*convergeddestroy)(void*);
19: PetscErrorCode (*setup)(SNES); /* routine to set up the nonlinear solver */
20: PetscErrorCode (*solve)(SNES); /* actual nonlinear solver */
21: PetscErrorCode (*view)(SNES,PetscViewer);
22: PetscErrorCode (*setfromoptions)(PetscOptions*,SNES); /* sets options from database */
23: PetscErrorCode (*destroy)(SNES);
24: PetscErrorCode (*reset)(SNES);
25: PetscErrorCode (*usercompute)(SNES,void**);
26: PetscErrorCode (*userdestroy)(void**);
27: PetscErrorCode (*computevariablebounds)(SNES,Vec,Vec); /* user provided routine to set box constrained variable bounds */
28: PetscErrorCode (*computepfunction)(SNES,Vec,Vec,void*);
29: PetscErrorCode (*computepjacobian)(SNES,Vec,Mat,Mat,void*);
30: PetscErrorCode (*load)(SNES,PetscViewer);
31: };
33: /*
34: Nonlinear solver context
35: */
36: #define MAXSNESMONITORS 5
38: struct _p_SNES {
39: PETSCHEADER(struct _SNESOps);
40: DM dm;
41: PetscBool dmAuto; /* SNES created currently used DM automatically */
42: SNES pc;
43: PCSide pcside;
44: PetscBool usespc;
46: /* ------------------------ User-provided stuff -------------------------------*/
47: void *user; /* user-defined context */
49: Vec vec_rhs; /* If non-null, solve F(x) = rhs */
50: Vec vec_sol; /* pointer to solution */
52: Vec vec_func; /* pointer to function */
54: Mat jacobian; /* Jacobian matrix */
55: Mat jacobian_pre; /* preconditioner matrix */
56: void *initialguessP; /* user-defined initial guess context */
57: KSP ksp; /* linear solver context */
58: SNESLineSearch linesearch; /* line search context */
59: PetscBool usesksp;
60: MatStructure matstruct; /* Used by Picard solver */
62: Vec vec_sol_update; /* pointer to solution update */
64: Vec scaling; /* scaling vector */
65: void *scaP; /* scaling context */
67: PetscReal precheck_picard_angle; /* For use with SNESLineSearchPreCheckPicard */
69: /* ------------------------Time stepping hooks-----------------------------------*/
71: /* ---------------- PETSc-provided (or user-provided) stuff ---------------------*/
73: PetscErrorCode (*monitor[MAXSNESMONITORS])(SNES,PetscInt,PetscReal,void*); /* monitor routine */
74: PetscErrorCode (*monitordestroy[MAXSNESMONITORS])(void**); /* monitor context destroy routine */
75: void *monitorcontext[MAXSNESMONITORS]; /* monitor context */
76: PetscInt numbermonitors; /* number of monitors */
77: void *cnvP; /* convergence context */
78: SNESConvergedReason reason;
79: PetscBool errorifnotconverged;
81: /* --- Routines and data that are unique to each particular solver --- */
83: PetscBool setupcalled; /* true if setup has been called */
84: void *data; /* implementation-specific data */
86: /* -------------------------- Parameters -------------------------------------- */
88: PetscInt max_its; /* max number of iterations */
89: PetscInt max_funcs; /* max number of function evals */
90: PetscInt nfuncs; /* number of function evaluations */
91: PetscInt iter; /* global iteration number */
92: PetscInt linear_its; /* total number of linear solver iterations */
93: PetscReal norm; /* residual norm of current iterate */
94: PetscReal rtol; /* relative tolerance */
95: PetscReal abstol; /* absolute tolerance */
96: PetscReal stol; /* step length tolerance*/
97: PetscReal deltatol; /* trust region convergence tolerance */
98: PetscInt lagpreconditioner; /* SNESSetLagPreconditioner() */
99: PetscInt lagjacobian; /* SNESSetLagJacobian() */
100: PetscInt jac_iter; /* The present iteration of the Jacobian lagging */
101: PetscBool lagjac_persist; /* The jac_iter persists until reset */
102: PetscInt pre_iter; /* The present iteration of the Preconditioner lagging */
103: PetscBool lagpre_persist; /* The pre_iter persists until reset */
104: PetscInt gridsequence; /* number of grid sequence steps to take; defaults to zero */
106: PetscBool tolerancesset; /* SNESSetTolerances() called and tolerances should persist through SNESCreate_XXX()*/
108: PetscBool vec_func_init_set; /* the initial function has been set */
110: SNESNormSchedule normschedule; /* Norm computation type for SNES instance */
111: SNESFunctionType functype; /* Function type for the SNES instance */
113: /* ------------------------ Default work-area management ---------------------- */
115: PetscInt nwork;
116: Vec *work;
118: /* ------------------------- Miscellaneous Information ------------------------ */
120: PetscReal *conv_hist; /* If !0, stores function norm (or
121: gradient norm) at each iteration */
122: PetscInt *conv_hist_its; /* linear iterations for each Newton step */
123: PetscInt conv_hist_len; /* size of convergence history array */
124: PetscInt conv_hist_max; /* actual amount of data in conv_history */
125: PetscBool conv_hist_reset; /* reset counter for each new SNES solve */
126: PetscBool conv_malloc;
128: PetscBool counters_reset; /* reset counter for each new SNES solve */
130: /* the next two are used for failures in the line search; they should be put elsewhere */
131: PetscInt numFailures; /* number of unsuccessful step attempts */
132: PetscInt maxFailures; /* maximum number of unsuccessful step attempts */
134: PetscInt numLinearSolveFailures;
135: PetscInt maxLinearSolveFailures;
137: PetscBool domainerror; /* set with SNESSetFunctionDomainError() */
139: PetscBool ksp_ewconv; /* flag indicating use of Eisenstat-Walker KSP convergence criteria */
140: void *kspconvctx; /* Eisenstat-Walker KSP convergence context */
142: /* SNESConvergedDefault context: split it off into a separate var/struct to be passed as context to SNESConvergedDefault? */
143: PetscReal ttol; /* rtol*initial_residual_norm */
145: Vec *vwork; /* more work vectors for Jacobian approx */
146: PetscInt nvwork;
148: PetscBool mf; /* -snes_mf was used on this snes */
149: PetscBool mf_operator; /* -snes_mf_operator was used on this snes */
150: PetscInt mf_version; /* The version of snes_mf used */
152: PetscReal vizerotolerance; /* tolerance for considering an x[] value to be on the bound */
153: Vec xl,xu; /* upper and lower bounds for box constrained VI problems */
154: PetscInt ntruebounds; /* number of non-infinite bounds set for VI box constraints */
155: PetscBool usersetbounds; /* bounds have been set via SNESVISetVariableBounds(), rather than via computevariablebounds() callback. */
157: };
159: typedef struct _p_DMSNES *DMSNES;
160: typedef struct _DMSNESOps *DMSNESOps;
161: struct _DMSNESOps {
162: PetscErrorCode (*computefunction)(SNES,Vec,Vec,void*);
163: PetscErrorCode (*computejacobian)(SNES,Vec,Mat,Mat,void*);
165: /* objective */
166: PetscErrorCode (*computeobjective)(SNES,Vec,PetscReal*,void*);
168: /* Picard iteration functions */
169: PetscErrorCode (*computepfunction)(SNES,Vec,Vec,void*);
170: PetscErrorCode (*computepjacobian)(SNES,Vec,Mat,Mat,void*);
172: /* User-defined smoother */
173: PetscErrorCode (*computegs)(SNES,Vec,Vec,void*);
175: PetscErrorCode (*destroy)(DMSNES);
176: PetscErrorCode (*duplicate)(DMSNES,DMSNES);
177: };
179: struct _p_DMSNES {
180: PETSCHEADER(struct _DMSNESOps);
181: void *functionctx;
182: void *gsctx;
183: void *pctx;
184: void *jacobianctx;
185: void *objectivectx;
187: void *data;
189: /* This is NOT reference counted. The DM on which this context was first created is cached here to implement one-way
190: * copy-on-write. When DMGetDMSNESWrite() sees a request using a different DM, it makes a copy. Thus, if a user
191: * only interacts directly with one level, e.g., using SNESSetFunction(), then SNESSetUp_FAS() is called to build
192: * coarse levels, then the user changes the routine with another call to SNESSetFunction(), it automatically
193: * propagates to all the levels. If instead, they get out a specific level and set the function on that level,
194: * subsequent changes to the original level will no longer propagate to that level.
195: */
196: DM originaldm;
197: };
198: PETSC_EXTERN PetscErrorCode DMGetDMSNES(DM,DMSNES*);
199: PETSC_EXTERN PetscErrorCode DMSNESView(DMSNES,PetscViewer);
200: PETSC_EXTERN PetscErrorCode DMSNESLoad(DMSNES,PetscViewer);
201: PETSC_EXTERN PetscErrorCode DMGetDMSNESWrite(DM,DMSNES*);
202: PETSC_EXTERN PetscErrorCode DMCopyDMSNES(DM,DM);
205: /* Context for Eisenstat-Walker convergence criteria for KSP solvers */
206: typedef struct {
207: PetscInt version; /* flag indicating version 1 or 2 of test */
208: PetscReal rtol_0; /* initial rtol */
209: PetscReal rtol_last; /* last rtol */
210: PetscReal rtol_max; /* maximum rtol */
211: PetscReal gamma; /* mult. factor for version 2 rtol computation */
212: PetscReal alpha; /* power for version 2 rtol computation */
213: PetscReal alpha2; /* power for safeguard */
214: PetscReal threshold; /* threshold for imposing safeguard */
215: PetscReal lresid_last; /* linear residual from last iteration */
216: PetscReal norm_last; /* function norm from last iteration */
217: PetscReal norm_first; /* function norm from the beginning of the first iteration. */
218: } SNESKSPEW;
222: PETSC_STATIC_INLINE PetscErrorCode SNESLogConvergenceHistory(SNES snes,PetscReal res,PetscInt its)
223: {
227: PetscObjectSAWsTakeAccess((PetscObject)snes);
228: if (snes->conv_hist && snes->conv_hist_max > snes->conv_hist_len) {
229: if (snes->conv_hist) snes->conv_hist[snes->conv_hist_len] = res;
230: if (snes->conv_hist_its) snes->conv_hist_its[snes->conv_hist_len] = its;
231: snes->conv_hist_len++;
232: }
233: PetscObjectSAWsGrantAccess((PetscObject)snes);
234: return(0);
235: }
237: PETSC_EXTERN PetscErrorCode SNESVIProjectOntoBounds(SNES,Vec);
238: PETSC_INTERN PetscErrorCode SNESVICheckLocalMin_Private(SNES,Mat,Vec,Vec,PetscReal,PetscBool*);
239: PETSC_INTERN PetscErrorCode SNESReset_VI(SNES);
240: PETSC_INTERN PetscErrorCode SNESDestroy_VI(SNES);
241: PETSC_INTERN PetscErrorCode SNESView_VI(SNES,PetscViewer);
242: PETSC_INTERN PetscErrorCode SNESSetFromOptions_VI(PetscOptions*,SNES);
243: PETSC_INTERN PetscErrorCode SNESSetUp_VI(SNES);
244: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*SNESVIComputeVariableBoundsFunction)(SNES,Vec,Vec);
245: PETSC_INTERN PetscErrorCode SNESVISetComputeVariableBounds_VI(SNES,SNESVIComputeVariableBoundsFunction);
246: PETSC_INTERN PetscErrorCode SNESVISetVariableBounds_VI(SNES,Vec,Vec);
247: PETSC_INTERN PetscErrorCode SNESConvergedDefault_VI(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*);
249: PetscErrorCode SNESScaleStep_Private(SNES,Vec,PetscReal*,PetscReal*,PetscReal*,PetscReal*);
250: PetscErrorCode DMSNESCheckFromOptions_Internal(SNES,DM,Vec,Vec,PetscErrorCode (**)(PetscInt,const PetscReal[],PetscInt,PetscScalar*,void*),void**);
252: PETSC_EXTERN PetscLogEvent SNES_Solve, SNES_LineSearch, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve;
254: extern PetscBool SNEScite;
255: extern const char SNESCitation[];
257: /*
258: Either generate an error or mark as diverged when a real from a SNES function norm is Nan or Inf
259: */
260: #define SNESCheckFunctionNorm(snes,beta) \
261: if (PetscIsInfOrNanReal(beta)) { \
262: if (snes->errorifnotconverged) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_NOT_CONVERGED,"SNESSolve has not converged due to Nan or Inf norm");\
263: else {\
264: PetscBool domainerror;\
265: PetscErrorCode MPI_Allreduce((int*)&snes->domainerror,(int*)&domainerror,1,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)snes)); \
266: if (domainerror) snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;\
267: else snes->reason = SNES_DIVERGED_FNORM_NAN; \
268: return(0);\
269: }\
270: }
273: #define SNESCheckKSPSolve(snes)\
274: {\
275: KSPConvergedReason kspreason; \
276: PetscErrorCode KSPGetConvergedReason(snes->ksp,&kspreason);\
277: if (kspreason < 0) {\
278: if (kspreason == KSP_DIVERGED_NANORINF) {\
279: PetscBool domainerror;\
280: MPI_Allreduce((int*)&snes->domainerror,(int*)&domainerror,1,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)snes)); \
281: if (domainerror) snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;\
282: else snes->reason = SNES_DIVERGED_LINEAR_SOLVE; \
283: return(0);\
284: } else {\
285: if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {\
286: PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);\
287: snes->reason = SNES_DIVERGED_LINEAR_SOLVE;\
288: return(0);\
289: }\
290: }\
291: }\
292: }
294: #endif