Actual source code: snesut.c

petsc-dev 2014-02-02
Report Typos and Errors
  2: #include <petsc-private/snesimpl.h>       /*I   "petsc-private/snesimpl.h"   I*/
  3: #include <petscdm.h>
  4: #include <petscblaslapack.h>

  8: /*@C
  9:    SNESMonitorSolution - Monitors progress of the SNES solvers by calling
 10:    VecView() for the approximate solution at each iteration.

 12:    Collective on SNES

 14:    Input Parameters:
 15: +  snes - the SNES context
 16: .  its - iteration number
 17: .  fgnorm - 2-norm of residual
 18: -  dummy - either a viewer or NULL

 20:    Level: intermediate

 22: .keywords: SNES, nonlinear, vector, monitor, view

 24: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
 25: @*/
 26: PetscErrorCode  SNESMonitorSolution(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
 27: {
 29:   Vec            x;
 30:   PetscViewer    viewer = (PetscViewer) dummy;

 33:   SNESGetSolution(snes,&x);
 34:   if (!viewer) {
 35:     MPI_Comm comm;
 36:     PetscObjectGetComm((PetscObject)snes,&comm);
 37:     viewer = PETSC_VIEWER_DRAW_(comm);
 38:   }
 39:   VecView(x,viewer);
 40:   return(0);
 41: }

 45: /*@C
 46:    SNESMonitorResidual - Monitors progress of the SNES solvers by calling
 47:    VecView() for the residual at each iteration.

 49:    Collective on SNES

 51:    Input Parameters:
 52: +  snes - the SNES context
 53: .  its - iteration number
 54: .  fgnorm - 2-norm of residual
 55: -  dummy - either a viewer or NULL

 57:    Level: intermediate

 59: .keywords: SNES, nonlinear, vector, monitor, view

 61: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
 62: @*/
 63: PetscErrorCode  SNESMonitorResidual(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
 64: {
 66:   Vec            x;
 67:   PetscViewer    viewer = (PetscViewer) dummy;

 70:   SNESGetFunction(snes,&x,0,0);
 71:   if (!viewer) {
 72:     MPI_Comm comm;
 73:     PetscObjectGetComm((PetscObject)snes,&comm);
 74:     viewer = PETSC_VIEWER_DRAW_(comm);
 75:   }
 76:   VecView(x,viewer);
 77:   return(0);
 78: }

 82: /*@C
 83:    SNESMonitorSolutionUpdate - Monitors progress of the SNES solvers by calling
 84:    VecView() for the UPDATE to the solution at each iteration.

 86:    Collective on SNES

 88:    Input Parameters:
 89: +  snes - the SNES context
 90: .  its - iteration number
 91: .  fgnorm - 2-norm of residual
 92: -  dummy - either a viewer or NULL

 94:    Level: intermediate

 96: .keywords: SNES, nonlinear, vector, monitor, view

 98: .seealso: SNESMonitorSet(), SNESMonitorDefault(), VecView()
 99: @*/
100: PetscErrorCode  SNESMonitorSolutionUpdate(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
101: {
103:   Vec            x;
104:   PetscViewer    viewer = (PetscViewer) dummy;

107:   SNESGetSolutionUpdate(snes,&x);
108:   if (!viewer) {
109:     MPI_Comm comm;
110:     PetscObjectGetComm((PetscObject)snes,&comm);
111:     viewer = PETSC_VIEWER_DRAW_(comm);
112:   }
113:   VecView(x,viewer);
114:   return(0);
115: }

119: /*@C
120:    SNESMonitorDefault - Monitors progress of the SNES solvers (default).

122:    Collective on SNES

124:    Input Parameters:
125: +  snes - the SNES context
126: .  its - iteration number
127: .  fgnorm - 2-norm of residual
128: -  dummy - unused context

130:    Notes:
131:    This routine prints the residual norm at each iteration.

133:    Level: intermediate

135: .keywords: SNES, nonlinear, default, monitor, norm

137: .seealso: SNESMonitorSet(), SNESMonitorSolution()
138: @*/
139: PetscErrorCode  SNESMonitorDefault(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
140: {
142:   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));

145:   PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
146:   PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);
147:   PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
148:   return(0);
149: }

153: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes,PetscInt it,PetscReal fnorm,void *ctx)
154: {
155: #if defined(PETSC_MISSING_LAPACK_GEEV)
156:   SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - Lapack routine is unavailable\nNot able to provide eigen values.");
157: #elif defined(PETSC_HAVE_ESSL)
158:   SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_SUP,"GEEV - No support for ESSL Lapack Routines");
159: #else
160:   Vec            X;
161:   Mat            J,dJ,dJdense;
163:   PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
164:   PetscInt       n,i;
165:   PetscBLASInt   nb,lwork;
166:   PetscReal      *eigr,*eigi;
167:   MatStructure   flg = DIFFERENT_NONZERO_PATTERN;
168:   PetscScalar    *work;
169:   PetscScalar    *a;

172:   if (it == 0) return(0);
173:   /* create the difference between the current update and the current jacobian */
174:   SNESGetSolution(snes,&X);
175:   SNESGetJacobian(snes,&J,NULL,&func,NULL);
176:   MatDuplicate(J,MAT_COPY_VALUES,&dJ);
177:   SNESComputeJacobian(snes,X,&dJ,&dJ,&flg);
178:   MatAXPY(dJ,-1.0,J,SAME_NONZERO_PATTERN);

180:   /* compute the spectrum directly */
181:   MatConvert(dJ,MATSEQDENSE,MAT_INITIAL_MATRIX,&dJdense);
182:   MatGetSize(dJ,&n,NULL);
183:   PetscBLASIntCast(n,&nb);
184:   lwork = 3*nb;
185:   PetscMalloc1(n,&eigr);
186:   PetscMalloc1(n,&eigi);
187:   PetscMalloc1(lwork,&work);
188:   MatDenseGetArray(dJdense,&a);
189: #if !defined(PETSC_USE_COMPLEX)
190:   {
191:     PetscBLASInt lierr;
192:     PetscFPTrapPush(PETSC_FP_TRAP_OFF);
193:     PetscStackCallBLAS("LAPACKgeev",LAPACKgeev_("N","N",&nb,a,&nb,eigr,eigi,NULL,&nb,NULL,&nb,work,&lwork,&lierr));
194:     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"geev() error %d",lierr);
195:     PetscFPTrapPop();
196:   }
197: #else
198:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded for complex");
199: #endif
200:   PetscPrintf(PetscObjectComm((PetscObject)snes),"Eigenvalues of J_%d - J_%d:\n",it,it-1);
201:   for (i=0;i<n;i++) {
202:     PetscPrintf(PetscObjectComm((PetscObject)snes),"%5d: %20.5g + %20.5gi\n",i,(double)eigr[i],(double)eigi[i]);
203:   }
204:   MatDenseRestoreArray(dJdense,&a);
205:   MatDestroy(&dJ);
206:   MatDestroy(&dJdense);
207:   PetscFree(eigr);
208:   PetscFree(eigi);
209:   PetscFree(work);
210:   return(0);
211: #endif
212: }

216: PetscErrorCode  SNESMonitorRange_Private(SNES snes,PetscInt it,PetscReal *per)
217: {
219:   Vec            resid;
220:   PetscReal      rmax,pwork;
221:   PetscInt       i,n,N;
222:   PetscScalar    *r;

225:   SNESGetFunction(snes,&resid,0,0);
226:   VecNorm(resid,NORM_INFINITY,&rmax);
227:   VecGetLocalSize(resid,&n);
228:   VecGetSize(resid,&N);
229:   VecGetArray(resid,&r);
230:   pwork = 0.0;
231:   for (i=0; i<n; i++) {
232:     pwork += (PetscAbsScalar(r[i]) > .20*rmax);
233:   }
234:   MPI_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));
235:   VecRestoreArray(resid,&r);
236:   *per = *per/N;
237:   return(0);
238: }

242: /*@C
243:    SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value.

245:    Collective on SNES

247:    Input Parameters:
248: +  snes   - iterative context
249: .  it    - iteration number
250: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).
251: -  dummy - unused monitor context

253:    Options Database Key:
254: .  -snes_monitor_range - Activates SNESMonitorRange()

256:    Level: intermediate

258: .keywords: SNES, default, monitor, residual

260: .seealso: SNESMonitorSet(), SNESMonitorDefault(), SNESMonitorLGCreate()
261: @*/
262: PetscErrorCode  SNESMonitorRange(SNES snes,PetscInt it,PetscReal rnorm,void *dummy)
263: {
265:   PetscReal      perc,rel;
266:   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
267:   /* should be in a MonitorRangeContext */
268:   static PetscReal prev;

271:   if (!it) prev = rnorm;
272:   SNESMonitorRange_Private(snes,it,&perc);

274:   rel  = (prev - rnorm)/prev;
275:   prev = rnorm;
276:   PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
277:   PetscViewerASCIIPrintf(viewer,"%3D SNES preconditioned resid norm %14.12e Percent values above 20 percent of maximum %5.2f relative decrease %5.2e ratio %5.2e \n",it,(double)rnorm,(double)(100.0*perc),(double)rel,(double)(rel/perc));
278:   PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
279:   return(0);
280: }

282: typedef struct {
283:   PetscViewer viewer;
284:   PetscReal   *history;
285: } SNESMonitorRatioContext;

289: /*@C
290:    SNESMonitorRatio - Monitors progress of the SNES solvers by printing the ratio
291:    of residual norm at each iteration to the previous.

293:    Collective on SNES

295:    Input Parameters:
296: +  snes - the SNES context
297: .  its - iteration number
298: .  fgnorm - 2-norm of residual (or gradient)
299: -  dummy -  context of monitor

301:    Level: intermediate

303: .keywords: SNES, nonlinear, monitor, norm

305: .seealso: SNESMonitorSet(), SNESMonitorSolution()
306: @*/
307: PetscErrorCode  SNESMonitorRatio(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
308: {
309:   PetscErrorCode          ierr;
310:   PetscInt                len;
311:   PetscReal               *history;
312:   SNESMonitorRatioContext *ctx = (SNESMonitorRatioContext*)dummy;

315:   SNESGetConvergenceHistory(snes,&history,NULL,&len);
316:   PetscViewerASCIIAddTab(ctx->viewer,((PetscObject)snes)->tablevel);
317:   if (!its || !history || its > len) {
318:     PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e \n",its,(double)fgnorm);
319:   } else {
320:     PetscReal ratio = fgnorm/history[its-1];
321:     PetscViewerASCIIPrintf(ctx->viewer,"%3D SNES Function norm %14.12e %14.12e \n",its,(double)fgnorm,(double)ratio);
322:   }
323:   PetscViewerASCIISubtractTab(ctx->viewer,((PetscObject)snes)->tablevel);
324:   return(0);
325: }

327: /*
328:    If the we set the history monitor space then we must destroy it
329: */
332: PetscErrorCode SNESMonitorRatioDestroy(void **ct)
333: {
334:   PetscErrorCode          ierr;
335:   SNESMonitorRatioContext *ctx = *(SNESMonitorRatioContext**)ct;

338:   PetscFree(ctx->history);
339:   PetscViewerDestroy(&ctx->viewer);
340:   PetscFree(ctx);
341:   return(0);
342: }

346: /*@C
347:    SNESMonitorSetRatio - Sets SNES to use a monitor that prints the
348:    ratio of the function norm at each iteration.

350:    Collective on SNES

352:    Input Parameters:
353: +   snes - the SNES context
354: -   viewer - ASCII viewer to print output

356:    Level: intermediate

358: .keywords: SNES, nonlinear, monitor, norm

360: .seealso: SNESMonitorSet(), SNESMonitorSolution(), SNESMonitorDefault()
361: @*/
362: PetscErrorCode  SNESMonitorSetRatio(SNES snes,PetscViewer viewer)
363: {
364:   PetscErrorCode          ierr;
365:   SNESMonitorRatioContext *ctx;
366:   PetscReal               *history;

369:   if (!viewer) {
370:     PetscViewerASCIIOpen(PetscObjectComm((PetscObject)snes),"stdout",&viewer);
371:     PetscObjectReference((PetscObject)viewer);
372:   }
373:   PetscNewLog(snes,&ctx);
374:   SNESGetConvergenceHistory(snes,&history,NULL,NULL);
375:   if (!history) {
376:     PetscMalloc1(100,&ctx->history);
377:     SNESSetConvergenceHistory(snes,ctx->history,0,100,PETSC_TRUE);
378:   }
379:   ctx->viewer = viewer;

381:   SNESMonitorSet(snes,SNESMonitorRatio,ctx,SNESMonitorRatioDestroy);
382:   return(0);
383: }

385: /* ---------------------------------------------------------------- */
388: /*
389:      Default (short) SNES Monitor, same as SNESMonitorDefault() except
390:   it prints fewer digits of the residual as the residual gets smaller.
391:   This is because the later digits are meaningless and are often
392:   different on different machines; by using this routine different
393:   machines will usually generate the same output.
394: */
395: PetscErrorCode  SNESMonitorDefaultShort(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
396: {
398:   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));

401:   PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);
402:   if (fgnorm > 1.e-9) {
403:     PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %g \n",its,(double)fgnorm);
404:   } else if (fgnorm > 1.e-11) {
405:     PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm %5.3e \n",its,(double)fgnorm);
406:   } else {
407:     PetscViewerASCIIPrintf(viewer,"%3D SNES Function norm < 1.e-11\n",its);
408:   }
409:   PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);
410:   return(0);
411: }
412: /* ---------------------------------------------------------------- */
415: /*@C
416:    SNESConvergedDefault - Convergence test of the solvers for
417:    systems of nonlinear equations (default).

419:    Collective on SNES

421:    Input Parameters:
422: +  snes - the SNES context
423: .  it - the iteration (0 indicates before any Newton steps)
424: .  xnorm - 2-norm of current iterate
425: .  snorm - 2-norm of current step
426: .  fnorm - 2-norm of function at current iterate
427: -  dummy - unused context

429:    Output Parameter:
430: .   reason  - one of
431: $  SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
432: $  SNES_CONVERGED_SNORM_RELATIVE  - (snorm < stol*xnorm),
433: $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
434: $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
435: $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
436: $  SNES_CONVERGED_ITERATING       - (otherwise),

438:    where
439: +    maxf - maximum number of function evaluations,
440:             set with SNESSetTolerances()
441: .    nfct - number of function evaluations,
442: .    abstol - absolute function norm tolerance,
443:             set with SNESSetTolerances()
444: -    rtol - relative function norm tolerance, set with SNESSetTolerances()

446:    Level: intermediate

448: .keywords: SNES, nonlinear, default, converged, convergence

450: .seealso: SNESSetConvergenceTest()
451: @*/
452: PetscErrorCode  SNESConvergedDefault(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
453: {


460:   *reason = SNES_CONVERGED_ITERATING;

462:   if (!it) {
463:     /* set parameter for default relative tolerance convergence test */
464:     snes->ttol = fnorm*snes->rtol;
465:   }
466:   if (PetscIsInfOrNanReal(fnorm)) {
467:     PetscInfo(snes,"Failed to converged, function norm is NaN\n");
468:     *reason = SNES_DIVERGED_FNORM_NAN;
469:   } else if (fnorm < snes->abstol) {
470:     PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e\n",(double)fnorm,(double)snes->abstol);
471:     *reason = SNES_CONVERGED_FNORM_ABS;
472:   } else if (snes->nfuncs >= snes->max_funcs) {
473:     PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);
474:     *reason = SNES_DIVERGED_FUNCTION_COUNT;
475:   }

477:   if (it && !*reason) {
478:     if (fnorm <= snes->ttol) {
479:       PetscInfo2(snes,"Converged due to function norm %14.12e < %14.12e (relative tolerance)\n",(double)fnorm,(double)snes->ttol);
480:       *reason = SNES_CONVERGED_FNORM_RELATIVE;
481:     } else if (snorm < snes->stol*xnorm) {
482:       PetscInfo3(snes,"Converged due to small update length: %14.12e < %14.12e * %14.12e\n",(double)snorm,(double)snes->stol,(double)xnorm);
483:       *reason = SNES_CONVERGED_SNORM_RELATIVE;
484:     }
485:   }
486:   return(0);
487: }

491: /*@C
492:    SNESConvergedSkip - Convergence test for SNES that NEVER returns as
493:    converged, UNLESS the maximum number of iteration have been reached.

495:    Logically Collective on SNES

497:    Input Parameters:
498: +  snes - the SNES context
499: .  it - the iteration (0 indicates before any Newton steps)
500: .  xnorm - 2-norm of current iterate
501: .  snorm - 2-norm of current step
502: .  fnorm - 2-norm of function at current iterate
503: -  dummy - unused context

505:    Output Parameter:
506: .   reason  - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN

508:    Notes:
509:    Convergence is then declared after a fixed number of iterations have been used.

511:    Level: advanced

513: .keywords: SNES, nonlinear, skip, converged, convergence

515: .seealso: SNESSetConvergenceTest()
516: @*/
517: PetscErrorCode  SNESConvergedSkip(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
518: {


525:   *reason = SNES_CONVERGED_ITERATING;

527:   if (fnorm != fnorm) {
528:     PetscInfo(snes,"Failed to converged, function norm is NaN\n");
529:     *reason = SNES_DIVERGED_FNORM_NAN;
530:   } else if (it == snes->max_its) {
531:     *reason = SNES_CONVERGED_ITS;
532:   }
533:   return(0);
534: }

538: /*@C
539:   SNESSetWorkVecs - Gets a number of work vectors.

541:   Input Parameters:
542: . snes  - the SNES context
543: . nw - number of work vectors to allocate

545:    Level: developer

547:    Developers Note: This is PETSC_EXTERN because it may be used by user written plugin SNES implementations

549: @*/
550: PetscErrorCode SNESSetWorkVecs(SNES snes,PetscInt nw)
551: {
552:   DM             dm;
553:   Vec            v;

557:   if (snes->work) {VecDestroyVecs(snes->nwork,&snes->work);}
558:   snes->nwork = nw;

560:   SNESGetDM(snes, &dm);
561:   DMGetGlobalVector(dm, &v);
562:   VecDuplicateVecs(v,snes->nwork,&snes->work);
563:   DMRestoreGlobalVector(dm, &v);
564:   PetscLogObjectParents(snes,nw,snes->work);
565:   return(0);
566: }