Actual source code: picard.c

  1: #define PETSCSNES_DLL

 3:  #include src/snes/impls/picard/picard.h

  5: /*
  6:   SNESDestroy_Picard - Destroys the private SNES_Picard context that was created with SNESCreate_Picard().

  8:   Input Parameter:
  9: . snes - the SNES context

 11:   Application Interface Routine: SNESDestroy()
 12: */
 15: PetscErrorCode SNESDestroy_Picard(SNES snes)
 16: {

 20:   if (snes->vec_sol_update) {
 21:     VecDestroy(snes->vec_sol_update);
 22:   }
 23:   PetscFree(snes->data);
 24:   return(0);
 25: }

 27: /*
 28:    SNESSetUp_Picard - Sets up the internal data structures for the later use
 29:    of the SNESPICARD nonlinear solver.

 31:    Input Parameters:
 32: +  snes - the SNES context
 33: -  x - the solution vector

 35:    Application Interface Routine: SNESSetUp()
 36:  */
 39: PetscErrorCode SNESSetUp_Picard(SNES snes)
 40: {

 44:   VecDuplicate(snes->vec_sol, &snes->vec_sol_update);
 45:   return(0);
 46: }

 48: /*
 49:   SNESSetFromOptions_Picard - Sets various parameters for the SNESLS method.

 51:   Input Parameter:
 52: . snes - the SNES context

 54:   Application Interface Routine: SNESSetFromOptions()
 55: */
 58: static PetscErrorCode SNESSetFromOptions_Picard(SNES snes)
 59: {
 60:   SNES_Picard   *ls = (SNES_Picard *)snes->data;
 61:   const char    *types[] = {"basic"};
 62:   PetscInt       indx;
 63:   PetscTruth     flg;

 67:   PetscOptionsHead("SNES Picard options");
 68:     PetscOptionsEList("-snes_picard","Picard Type","SNESLineSearchSet",types,1,"basic",&indx,&flg);
 69:     if (flg) {
 70:       ls->type = indx;
 71:     }
 72:   PetscOptionsTail();
 73:   return(0);
 74: }

 76: /*
 77:   SNESView_Picard - Prints info from the SNESPICARD data structure.

 79:   Input Parameters:
 80: + SNES - the SNES context
 81: - viewer - visualization context

 83:   Application Interface Routine: SNESView()
 84: */
 87: static PetscErrorCode SNESView_Picard(SNES snes, PetscViewer viewer)
 88: {
 89:   SNES_Picard   *ls = (SNES_Picard *)snes->data;
 90:   const char    *cstr;
 91:   PetscTruth     iascii;

 95:   PetscTypeCompare((PetscObject) viewer, PETSC_VIEWER_ASCII, &iascii);
 96:   if (iascii) {
 97:     switch(ls->type) {
 98:     case 0:
 99:       cstr = "basic";
100:       break;
101:     default:
102:       cstr = "unknown";
103:     }
104:     PetscViewerASCIIPrintf(viewer,"  picard variant: %s\n", cstr);
105:   } else {
106:     SETERRQ1(PETSC_ERR_SUP, "Viewer type %s not supported for SNES Picard", ((PetscObject)viewer)->type_name);
107:   }
108:   return(0);
109: }

111: /*
112:   SNESSolve_Picard - Solves a nonlinear system with the Picard method.

114:   Input Parameters:
115: . snes - the SNES context

117:   Output Parameter:
118: . outits - number of iterations until termination

120:   Application Interface Routine: SNESSolve()
121: */
124: PetscErrorCode SNESSolve_Picard(SNES snes)
125: {
126:   SNES_Picard   *neP = (SNES_Picard *) snes->data;
127:   Vec            X, Y, F;
128:   PetscReal      alpha = 1.0;
129:   PetscReal      fnorm;
130:   PetscInt       maxits, i;

134:   snes->reason = SNES_CONVERGED_ITERATING;

136:   maxits = snes->max_its;             /* maximum number of iterations */
137:   X      = snes->vec_sol;             /* X^n */
138:   Y      = snes->vec_sol_update; /* \tilde X */
139:   F      = snes->vec_func;       /* residual vector */

141:   PetscObjectTakeAccess(snes);
142:   snes->iter = 0;
143:   snes->norm = 0;
144:   PetscObjectGrantAccess(snes);
145:   SNESComputeFunction(snes,X,F);
146:   if (snes->domainerror) {
147:     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
148:     return(0);
149:   }
150:   VecNorm(F, NORM_2, &fnorm);CHKFPQ(fnorm); /* fnorm <- ||F||  */
151:   PetscObjectTakeAccess(snes);
152:   snes->norm = fnorm;
153:   PetscObjectGrantAccess(snes);
154:   SNESLogConvHistory(snes,fnorm,0);
155:   SNESMonitor(snes,0,fnorm);

157:   /* set parameter for default relative tolerance convergence test */
158:   snes->ttol = fnorm*snes->rtol;
159:   /* test convergence */
160:   (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);
161:   if (snes->reason) return(0);

163:   for(i = 0; i < maxits; i++) {
164:     PetscTruth lsSuccess = PETSC_TRUE;
165:     PetscReal  dummyNorm;

167:     if (0) {
168:       /* Update guess Y = X^n - F(X^n) */
169:       VecWAXPY(Y, -1.0, F, X);
170:       /* X^{n+1} = (1 - \alpha) X^n + \alpha Y */
171:       VecAXPBY(X, alpha, 1 - alpha, Y);
172:       /* Compute F(X^{new}) */
173:       SNESComputeFunction(snes, X, F);
174:       VecNorm(F, NORM_2, &fnorm);CHKFPQ(fnorm);
175:     } else {
176:       (*neP->LineSearch)(snes, PETSC_NULL/*neP->lsP*/,  X,  F,  F,  F,  X,  fnorm,  &dummyNorm,  &fnorm,  &lsSuccess);
177:     }
178:     if (!lsSuccess) {
179:       if (++snes->numFailures >= snes->maxFailures) {
180:         snes->reason = SNES_DIVERGED_LS_FAILURE;
181:         break;
182:       }
183:     }
184:     if (snes->nfuncs >= snes->max_funcs) {
185:       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
186:       break;
187:     }
188:     if (snes->domainerror) {
189:       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
190:       return(0);
191:     }
192:     /* Monitor convergence */
193:     PetscObjectTakeAccess(snes);
194:     snes->iter = i+1;
195:     snes->norm = fnorm;
196:     PetscObjectGrantAccess(snes);
197:     SNESLogConvHistory(snes,snes->norm,0);
198:     SNESMonitor(snes,snes->iter,snes->norm);
199:     /* Test for convergence */
200:     (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);
201:     if (snes->reason) break;
202:   }
203:   if (i == maxits) {
204:     PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);
205:     if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
206:   }
207:   return(0);
208: }

214: PetscErrorCode  SNESLineSearchSetPreCheck_Picard(SNES snes, FCN1 func, void *checkctx)
215: {
217:   ((SNES_Picard *)(snes->data))->precheckstep = func;
218:   ((SNES_Picard *)(snes->data))->precheck     = checkctx;
219:   return(0);
220: }

227: PetscErrorCode  SNESLineSearchSet_Picard(SNES snes, FCN2 func, void *lsctx)
228: {
230:   ((SNES_Picard *)(snes->data))->LineSearch = func;
231:   ((SNES_Picard *)(snes->data))->lsP        = lsctx;
232:   return(0);
233: }

240: PetscErrorCode  SNESLineSearchSetPostCheck_Picard(SNES snes, FCN3 func, void *checkctx)
241: {
243:   ((SNES_Picard *)(snes->data))->postcheckstep = func;
244:   ((SNES_Picard *)(snes->data))->postcheck     = checkctx;
245:   return(0);
246: }

249: /*MC
250:   SNESPICARD - Picard nonlinear solver that uses successive substitutions

252:   Level: beginner

254: .seealso:  SNESCreate(), SNES, SNESSetType(), SNESLS, SNESTR
255: M*/
259: PetscErrorCode  SNESCreate_Picard(SNES snes)
260: {
261:   SNES_Picard   *neP;

265:   snes->ops->destroy            = SNESDestroy_Picard;
266:   snes->ops->setup                = SNESSetUp_Picard;
267:   snes->ops->setfromoptions = SNESSetFromOptions_Picard;
268:   snes->ops->view           = SNESView_Picard;
269:   snes->ops->solve                = SNESSolve_Picard;

271:   PetscNewLog(snes, SNES_Picard, &neP);
272:   snes->data = (void*) neP;
273:   neP->type  = 0;
274:   neP->alpha                 = 1.e-4;
275:   neP->maxstep                 = 1.e8;
276:   neP->steptol       = 1.e-12;
277:   neP->LineSearch    = SNESLineSearchNo;
278:   neP->lsP           = PETSC_NULL;
279:   neP->postcheckstep = PETSC_NULL;
280:   neP->postcheck     = PETSC_NULL;
281:   neP->precheckstep  = PETSC_NULL;
282:   neP->precheck      = PETSC_NULL;

284:   PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C",
285:                                            "SNESLineSearchSet_Picard",
286:                                            SNESLineSearchSet_Picard);
287:   PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetPostCheck_C",
288:                                            "SNESLineSearchSetPostCheck_Picard",
289:                                            SNESLineSearchSetPostCheck_Picard);
290:   PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetPreCheck_C",
291:                                            "SNESLineSearchSetPreCheck_Picard",
292:                                            SNESLineSearchSetPreCheck_Picard);
293:   return(0);
294: }