Actual source code: snesimpl.h

petsc-3.6.1 2015-08-06
Report Typos and Errors
  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