Date: 2015-10-02T22:23:13+00:00

Actual source code: snesimpl.h
petsc-3.6.2 2015-10-02
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