Actual source code: snesmfj.c

  1: /*$Id: snesmfj.c,v 1.119 2001/04/10 19:36:54 bsmith Exp $*/

  3: #include "src/snes/snesimpl.h"
  4: #include "src/snes/mf/snesmfj.h"   /*I  "petscsnes.h"   I*/

  6: PetscFList      MatSNESMPetscFList              = 0;
  7: PetscTruth MatSNESMFRegisterAllCalled = PETSC_FALSE;

  9: /*@C
 10:     MatSNESMFSetType - Sets the method that is used to compute the 
 11:     differencing parameter for finite differene matrix-free formulations. 

 13:     Input Parameters:
 14: +   mat - the "matrix-free" matrix created via MatCreateSNESMF()
 15: -   ftype - the type requested

 17:     Level: advanced

 19:     Notes:
 20:     For example, such routines can compute h for use in
 21:     Jacobian-vector products of the form

 23:                         F(x+ha) - F(x)
 24:           F'(u)a  ~=  ----------------
 25:                               h

 27: .seealso: MatCreateSNESMF(), MatSNESMFRegisterDynamic)
 28: @*/
 29: int MatSNESMFSetType(Mat mat,MatSNESMFType ftype)
 30: {
 31:   int          ierr,(*r)(MatSNESMFCtx);
 32:   MatSNESMFCtx ctx;
 33:   PetscTruth   match;
 34: 

 39:   MatShellGetContext(mat,(void **)&ctx);

 41:   /* already set, so just return */
 42:   PetscTypeCompare((PetscObject)ctx,ftype,&match);
 43:   if (match) return(0);

 45:   /* destroy the old one if it exists */
 46:   if (ctx->ops->destroy) {
 47:     (*ctx->ops->destroy)(ctx);
 48:   }

 50:   /* Get the function pointers for the requrested method */
 51:   if (!MatSNESMFRegisterAllCalled) {MatSNESMFRegisterAll(PETSC_NULL);}

 53:    PetscFListFind(ctx->comm,MatSNESMPetscFList,ftype,(void (**)(void)) &r);

 55:   if (!r) SETERRQ(1,"Unknown MatSNESMF type given");

 57:   (*r)(ctx);

 59:   PetscObjectChangeTypeName((PetscObject)ctx,ftype);

 61:   return(0);
 62: }

 64: /*MC
 65:    MatSNESMFRegisterDynamic - Adds a method to the MatSNESMF registry.

 67:    Synopsis:
 68:    MatSNESMFRegisterDynamicchar *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESMF))

 70:    Not Collective

 72:    Input Parameters:
 73: +  name_solver - name of a new user-defined compute-h module
 74: .  path - path (either absolute or relative) the library containing this solver
 75: .  name_create - name of routine to create method context
 76: -  routine_create - routine to create method context

 78:    Level: developer

 80:    Notes:
 81:    MatSNESMFRegisterDynamic) may be called multiple times to add several user-defined solvers.

 83:    If dynamic libraries are used, then the fourth input argument (routine_create)
 84:    is ignored.

 86:    Sample usage:
 87: .vb
 88:    MatSNESMFRegisterDynamic"my_h",/home/username/my_lib/lib/libO/solaris/mylib.a,
 89:                "MyHCreate",MyHCreate);
 90: .ve

 92:    Then, your solver can be chosen with the procedural interface via
 93: $     MatSNESMFSetType(mfctx,"my_h")
 94:    or at runtime via the option
 95: $     -snes_mf_type my_h

 97: .keywords: MatSNESMF, register

 99: .seealso: MatSNESMFRegisterAll(), MatSNESMFRegisterDestroy()
100: M*/

102: int MatSNESMFRegister(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx))
103: {
105:   char fullname[256];

108:   PetscFListConcat(path,name,fullname);
109:   PetscFListAdd(&MatSNESMPetscFList,sname,fullname,(void (*)())function);
110:   return(0);
111: }


114: /*@C
115:    MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were
116:    registered by MatSNESMFRegisterDynamic).

118:    Not Collective

120:    Level: developer

122: .keywords: MatSNESMF, register, destroy

124: .seealso: MatSNESMFRegisterDynamic), MatSNESMFRegisterAll()
125: @*/
126: int MatSNESMFRegisterDestroy(void)
127: {

131:   if (MatSNESMPetscFList) {
132:     PetscFListDestroy(&MatSNESMPetscFList);
133:     MatSNESMPetscFList = 0;
134:   }
135:   MatSNESMFRegisterAllCalled = PETSC_FALSE;
136:   return(0);
137: }

139: /* ----------------------------------------------------------------------------------------*/
140: int MatSNESMFDestroy_Private(Mat mat)
141: {
142:   int          ierr;
143:   MatSNESMFCtx ctx;

146:   MatShellGetContext(mat,(void **)&ctx);
147:   VecDestroy(ctx->w);
148:   if (ctx->ops->destroy) {(*ctx->ops->destroy)(ctx);}
149:   if (ctx->sp) {MatNullSpaceDestroy(ctx->sp);}
150:   PetscHeaderDestroy(ctx);
151:   return(0);
152: }

154: /*
155:    MatSNESMFView_Private - Views matrix-free parameters.

157: */
158: int MatSNESMFView_Private(Mat J,PetscViewer viewer)
159: {
160:   int          ierr;
161:   MatSNESMFCtx ctx;
162:   PetscTruth   isascii;

165:   MatShellGetContext(J,(void **)&ctx);
166:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
167:   if (isascii) {
168:      PetscViewerASCIIPrintf(viewer,"  SNES matrix-free approximation:n");
169:      PetscViewerASCIIPrintf(viewer,"    err=%g (relative error in function evaluation)n",ctx->error_rel);
170:      if (!ctx->type_name) {
171:        PetscViewerASCIIPrintf(viewer,"    The compute h routine has not yet been setn");
172:      } else {
173:        PetscViewerASCIIPrintf(viewer,"    Using %s compute h routinen",ctx->type_name);
174:      }
175:      if (ctx->ops->view) {
176:        (*ctx->ops->view)(ctx,viewer);
177:      }
178:   } else {
179:     SETERRQ1(1,"Viewer type %s not supported for SNES matrix free matrix",((PetscObject)viewer)->type_name);
180:   }
181:   return(0);
182: }

184: /*
185:    MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This 
186:    allows the user to indicate the beginning of a new linear solve by calling
187:    MatAssemblyXXX() on the matrix free matrix. This then allows the 
188:    MatSNESMFCreate_WP() to properly compute ||U|| only the first time
189:    in the linear solver rather than every time.
190: */
191: int MatSNESMFAssemblyEnd_Private(Mat J)
192: {
193:   int          ierr;
194:   MatSNESMFCtx j;

197:   MatSNESMFResetHHistory(J);
198:   MatShellGetContext(J,(void **)&j);
199:   if (j->usesnes) {
200:     SNESGetSolution(j->snes,&j->current_u);
201:     if (j->snes->method_class == SNES_NONLINEAR_EQUATIONS) {
202:       SNESGetFunction(j->snes,&j->current_f,PETSC_NULL,PETSC_NULL);
203:     } else if (j->snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
204:       SNESGetGradient(j->snes,&j->current_f,PETSC_NULL);
205:     } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class");
206:   }
207:   return(0);
208: }


211: /*
212:   MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector
213:   product, y = F'(u)*a:

215:         y ~= (F(u + ha) - F(u))/h, 
216:   where F = nonlinear function, as set by SNESSetFunction()
217:         u = current iterate
218:         h = difference interval
219: */
220: int MatSNESMFMult_Private(Mat mat,Vec a,Vec y)
221: {
222:   MatSNESMFCtx ctx;
223:   SNES         snes;
224:   Scalar       h,mone = -1.0;
225:   Vec          w,U,F;
226:   int          ierr,(*eval_fct)(SNES,Vec,Vec)=0;

229:   /* We log matrix-free matrix-vector products separately, so that we can
230:      separate the performance monitoring from the cases that use conventional
231:      storage.  We may eventually modify event logging to associate events
232:      with particular objects, hence alleviating the more general problem. */
233:   PetscLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);

235:   MatShellGetContext(mat,(void **)&ctx);
236:   snes = ctx->snes;
237:   w    = ctx->w;
238:   U    = ctx->current_u;

240:   /* 
241:       Compute differencing parameter 
242:   */
243:   if (!ctx->ops->compute) {
244:     MatSNESMFSetType(mat,MATSNESMF_DEFAULT);
245:     MatSNESMFSetFromOptions(mat);
246:   }
247:   (*ctx->ops->compute)(ctx,U,a,&h);

249:   /* keep a record of the current differencing parameter h */
250:   ctx->currenth = h;
251: #if defined(PETSC_USE_COMPLEX)
252:   PetscLogInfo(mat,"MatSNESMFMult_Private:Current differencing parameter: %g + %g in",PetscRealPart(h),PetscImaginaryPart(h));
253: #else
254:   PetscLogInfo(mat,"MatSNESMFMult_Private:Current differencing parameter: %15.12en",h);
255: #endif
256:   if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) {
257:     ctx->historyh[ctx->ncurrenth] = h;
258:   }
259:   ctx->ncurrenth++;

261:   /* w = u + ha */
262:   VecWAXPY(&h,a,U,w);

264:   if (ctx->usesnes) {
265:     if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
266:       eval_fct = SNESComputeFunction;
267:     } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
268:       eval_fct = SNESComputeGradient;
269:     } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class");
270:     F    = ctx->current_f;
271:     if (!F) SETERRQ(1,"You must call MatAssembly() even on matrix-free matrices");
272:     (*eval_fct)(snes,w,y);
273:   } else {
274:     F = ctx->funcvec;
275:     /* compute func(U) as base for differencing */
276:     if (ctx->ncurrenth == 1) {
277:       (*ctx->func)(snes,U,F,ctx->funcctx);
278:     }
279:     (*ctx->func)(snes,w,y,ctx->funcctx);
280:   }

282:   VecAXPY(&mone,F,y);
283:   h    = 1.0/h;
284:   VecScale(&h,y);
285:   if (ctx->sp) {MatNullSpaceRemove(ctx->sp,y,PETSC_NULL);}

287:   PetscLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);
288:   return(0);
289: }

291: /*@C
292:    MatCreateSNESMF - Creates a matrix-free matrix context for use with
293:    a SNES solver.  This matrix can be used as the Jacobian argument for
294:    the routine SNESSetJacobian().

296:    Collective on SNES and Vec

298:    Input Parameters:
299: +  snes - the SNES context
300: -  x - vector where SNES solution is to be stored.

302:    Output Parameter:
303: .  J - the matrix-free matrix

305:    Level: advanced

307:    Notes:
308:    The matrix-free matrix context merely contains the function pointers
309:    and work space for performing finite difference approximations of
310:    Jacobian-vector products, F'(u)*a, 

312:    The default code uses the following approach to compute h

314: .vb
315:      F'(u)*a = [F(u+h*a) - F(u)]/h where
316:      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
317:        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
318:  where
319:      error_rel = square root of relative error in function evaluation
320:      umin = minimum iterate parameter
321: .ve

323:    The user can set the error_rel via MatSNESMFSetFunctionError() and 
324:    umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
325:    of the users manual for details.

327:    The user should call MatDestroy() when finished with the matrix-free
328:    matrix context.

330:    Options Database Keys:
331: +  -snes_mf_err <error_rel> - Sets error_rel
332: .  -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
333: -  -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h

335: .keywords: SNES, default, matrix-free, create, matrix

337: .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
338:           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateMF(),
339:           MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic), MatSNESMFFormJacobian()
340:  
341: @*/
342: int MatCreateSNESMF(SNES snes,Vec x,Mat *J)
343: {
344:   MatSNESMFCtx mfctx;
345:   int          ierr;

348:   MatCreateMF(x,J);
349:   MatShellGetContext(*J,(void **)&mfctx);
350:   mfctx->snes    = snes;
351:   mfctx->usesnes = PETSC_TRUE;
352:   PetscLogObjectParent(snes,*J);
353:   return(0);
354: }

356: /*@C
357:    MatCreateMF - Creates a matrix-free matrix. See also MatCreateSNESMF() 

359:    Collective on Vec

361:    Input Parameters:
362: .  x - vector that defines layout of the vectors and matrices

364:    Output Parameter:
365: .  J - the matrix-free matrix

367:    Level: advanced

369:    Notes:
370:    The matrix-free matrix context merely contains the function pointers
371:    and work space for performing finite difference approximations of
372:    Jacobian-vector products, F'(u)*a, 

374:    The default code uses the following approach to compute h

376: .vb
377:      F'(u)*a = [F(u+h*a) - F(u)]/h where
378:      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
379:        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
380:  where
381:      error_rel = square root of relative error in function evaluation
382:      umin = minimum iterate parameter
383: .ve

385:    The user can set the error_rel via MatSNESMFSetFunctionError() and 
386:    umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
387:    of the users manual for details.

389:    The user should call MatDestroy() when finished with the matrix-free
390:    matrix context.

392:    Options Database Keys:
393: +  -snes_mf_err <error_rel> - Sets error_rel
394: .  -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
395: -  -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h

397: .keywords: default, matrix-free, create, matrix

399: .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
400:           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateSNESMF(),
401:           MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic),, MatSNESMFFormJacobian()
402:  
403: @*/
404: int MatCreateMF(Vec x,Mat *J)
405: {
406:   MPI_Comm     comm;
407:   MatSNESMFCtx mfctx;
408:   int          n,nloc,ierr;

411:   PetscObjectGetComm((PetscObject)x,&comm);
412:   PetscHeaderCreate(mfctx,_p_MatSNESMFCtx,struct _MFOps,MATSNESMFCTX_COOKIE,0,"SNESMF",comm,MatSNESMFDestroy_Private,MatSNESMFView_Private);
413:   PetscLogObjectCreate(mfctx);
414:   mfctx->sp              = 0;
415:   mfctx->snes            = 0;
416:   mfctx->error_rel       = 1.e-8; /* assumes PetscReal precision */
417:   mfctx->recomputeperiod = 1;
418:   mfctx->count           = 0;
419:   mfctx->currenth        = 0.0;
420:   mfctx->historyh        = PETSC_NULL;
421:   mfctx->ncurrenth       = 0;
422:   mfctx->maxcurrenth     = 0;
423:   mfctx->type_name       = 0;
424:   mfctx->usesnes         = PETSC_FALSE;

426:   /* 
427:      Create the empty data structure to contain compute-h routines.
428:      These will be filled in below from the command line options or 
429:      a later call with MatSNESMFSetType() or if that is not called 
430:      then it will default in the first use of MatSNESMFMult_private()
431:   */
432:   mfctx->ops->compute        = 0;
433:   mfctx->ops->destroy        = 0;
434:   mfctx->ops->view           = 0;
435:   mfctx->ops->setfromoptions = 0;
436:   mfctx->hctx                = 0;

438:   mfctx->func                = 0;
439:   mfctx->funcctx             = 0;
440:   mfctx->funcvec             = 0;

442:   VecDuplicate(x,&mfctx->w);
443:   VecGetSize(mfctx->w,&n);
444:   VecGetLocalSize(mfctx->w,&nloc);
445:   MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);
446:   MatShellSetOperation(*J,MATOP_MULT,(void(*)())MatSNESMFMult_Private);
447:   MatShellSetOperation(*J,MATOP_DESTROY,(void(*)())MatSNESMFDestroy_Private);
448:   MatShellSetOperation(*J,MATOP_VIEW,(void(*)())MatSNESMFView_Private);
449:   MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void(*)())MatSNESMFAssemblyEnd_Private);
450:   PetscLogObjectParent(*J,mfctx->w);

452:   mfctx->mat = *J;
453:   return(0);
454: }

456: /*@
457:    MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line
458:    parameter.

460:    Collective on Mat

462:    Input Parameters:
463: .  mat - the matrix obtained with MatCreateSNESMF()

465:    Options Database Keys:
466: +  -snes_mf_type - <default,wp>
467: -  -snes_mf_err - square root of estimated relative error in function evaluation
468: -  -snes_mf_period - how often h is recomputed, defaults to 1, everytime

470:    Level: advanced

472: .keywords: SNES, matrix-free, parameters

474: .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 
475:           MatSNESMFResetHHistory(), MatSNESMFKSPMonitor()
476: @*/
477: int MatSNESMFSetFromOptions(Mat mat)
478: {
479:   MatSNESMFCtx mfctx;
480:   int          ierr;
481:   PetscTruth   flg;
482:   char         ftype[256];

485:   MatShellGetContext(mat,(void **)&mfctx);
486:   if (mfctx) {
487:     if (!MatSNESMFRegisterAllCalled) {MatSNESMFRegisterAll(PETSC_NULL);}
488: 
489:     PetscOptionsBegin(mfctx->comm,mfctx->prefix,"Set matrix free computation parameters","MatSNESMF");
490:       PetscOptionsList("-snes_mf_type","Matrix free type","MatSNESMFSetType",MatSNESMPetscFList,mfctx->type_name,ftype,256,&flg);
491:       if (flg) {
492:         MatSNESMFSetType(mat,ftype);
493:       }

495:       PetscOptionsDouble("-snes_mf_err","set sqrt relative error in function","MatSNESMFSetFunctionError",mfctx->error_rel,&mfctx->error_rel,0);
496:       PetscOptionsInt("-snes_mf_period","how often h is recomputed","MatSNESMFSetPeriod",mfctx->recomputeperiod,&mfctx->recomputeperiod,0);
497:       if (mfctx->snes) {
498:         PetscOptionsName("-snes_mf_ksp_monitor","Monitor matrix-free parameters","MatSNESMFKSPMonitor",&flg);
499:         if (flg) {
500:           SLES sles;
501:           KSP  ksp;
502:           SNESGetSLES(mfctx->snes,&sles);
503:           SLESGetKSP(sles,&ksp);
504:           KSPSetMonitor(ksp,MatSNESMFKSPMonitor,PETSC_NULL,0);
505:         }
506:       }
507:       if (mfctx->ops->setfromoptions) {
508:         (*mfctx->ops->setfromoptions)(mfctx);
509:       }
510:     PetscOptionsEnd();

512:   }
513:   return(0);
514: }

516: /*@
517:    MatSNESMFGetH - Gets the last value that was used as the differencing 
518:    parameter.

520:    Not Collective

522:    Input Parameters:
523: .  mat - the matrix obtained with MatCreateSNESMF()

525:    Output Paramter:
526: .  h - the differencing step size

528:    Level: advanced

530: .keywords: SNES, matrix-free, parameters

532: .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 
533:           MatSNESMFResetHHistory(),MatSNESMFKSPMonitor()
534: @*/
535: int MatSNESMFGetH(Mat mat,Scalar *h)
536: {
537:   MatSNESMFCtx ctx;
538:   int          ierr;

541:   MatShellGetContext(mat,(void **)&ctx);
542:   if (ctx) {
543:     *h = ctx->currenth;
544:   }
545:   return(0);
546: }

548: /*
549:    MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc
550:    SNES matrix free routines. Prints the differencing parameter used at 
551:    each step.
552: */
553: int MatSNESMFKSPMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
554: {
555:   PC             pc;
556:   MatSNESMFCtx   ctx;
557:   int            ierr;
558:   Mat            mat;
559:   MPI_Comm       comm;
560:   PetscTruth     nonzeroinitialguess;

563:   PetscObjectGetComm((PetscObject)ksp,&comm);
564:   KSPGetPC(ksp,&pc);
565:   KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);
566:   PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);
567:   MatShellGetContext(mat,(void **)&ctx);
568:   if (!ctx) {
569:     SETERRQ(1,"Matrix is not a matrix free shell matrix");
570:   }
571:   if (n > 0 || nonzeroinitialguess) {
572: #if defined(PETSC_USE_COMPLEX)
573:     PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g in",n,rnorm,
574:                 PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));
575: #else
576:     PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g n",n,rnorm,ctx->currenth);
577: #endif
578:   } else {
579:     PetscPrintf(comm,"%d KSP Residual norm %14.12en",n,rnorm);
580:   }
581:   return(0);
582: }

584: /*@C
585:    MatSNESMFSetFunction - Sets the function used in applying the matrix free.

587:    Collective on Mat

589:    Input Parameters:
590: +  mat - the matrix free matrix created via MatCreateSNESMF()
591: .  v   - workspace vector
592: .  func - the function to use
593: -  funcctx - optional function context passed to function

595:    Level: advanced

597:    Notes:
598:     If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free
599:     matrix inside your compute Jacobian routine

601:     If this is not set then it will use the function set with SNESSetFunction()

603: .keywords: SNES, matrix-free, function

605: .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
606:           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
607:           MatSNESMFKSPMonitor(), SNESetFunction()
608: @*/
609: int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx)
610: {
611:   MatSNESMFCtx ctx;
612:   int          ierr;

615:   MatShellGetContext(mat,(void **)&ctx);
616:   if (ctx) {
617:     ctx->func    = func;
618:     ctx->funcctx = funcctx;
619:     ctx->funcvec = v;
620:   }
621:   return(0);
622: }


625: /*@
626:    MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime

628:    Collective on Mat

630:    Input Parameters:
631: +  mat - the matrix free matrix created via MatCreateSNESMF()
632: -  period - 1 for everytime, 2 for every second etc

634:    Options Database Keys:
635: +  -snes_mf_period <period>

637:    Level: advanced


640: .keywords: SNES, matrix-free, parameters

642: .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
643:           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
644:           MatSNESMFKSPMonitor()
645: @*/
646: int MatSNESMFSetPeriod(Mat mat,int period)
647: {
648:   MatSNESMFCtx ctx;
649:   int          ierr;

652:   MatShellGetContext(mat,(void **)&ctx);
653:   if (ctx) {
654:     ctx->recomputeperiod = period;
655:   }
656:   return(0);
657: }

659: /*@
660:    MatSNESMFSetFunctionError - Sets the error_rel for the approximation of
661:    matrix-vector products using finite differences.

663:    Collective on Mat

665:    Input Parameters:
666: +  mat - the matrix free matrix created via MatCreateSNESMF()
667: -  error_rel - relative error (should be set to the square root of
668:                the relative error in the function evaluations)

670:    Options Database Keys:
671: +  -snes_mf_err <error_rel> - Sets error_rel

673:    Level: advanced

675:    Notes:
676:    The default matrix-free matrix-vector product routine computes
677: .vb
678:      F'(u)*a = [F(u+h*a) - F(u)]/h where
679:      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
680:        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   else
681: .ve

683: .keywords: SNES, matrix-free, parameters

685: .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
686:           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
687:           MatSNESMFKSPMonitor()
688: @*/
689: int MatSNESMFSetFunctionError(Mat mat,PetscReal error)
690: {
691:   MatSNESMFCtx ctx;
692:   int          ierr;

695:   MatShellGetContext(mat,(void **)&ctx);
696:   if (ctx) {
697:     if (error != PETSC_DEFAULT) ctx->error_rel = error;
698:   }
699:   return(0);
700: }

702: /*@
703:    MatSNESMFAddNullSpace - Provides a null space that an operator is
704:    supposed to have.  Since roundoff will create a small component in
705:    the null space, if you know the null space you may have it
706:    automatically removed.

708:    Collective on Mat 

710:    Input Parameters:
711: +  J - the matrix-free matrix context
712: -  nullsp - object created with MatNullSpaceCreate()

714:    Level: advanced

716: .keywords: SNES, matrix-free, null space

718: .seealso: MatNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(),
719:           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
720:           MatSNESMFKSPMonitor(), MatSNESMFErrorRel()
721: @*/
722: int MatSNESMFAddNullSpace(Mat J,MatNullSpace nullsp)
723: {
724:   int          ierr;
725:   MatSNESMFCtx ctx;
726:   MPI_Comm     comm;

729:   PetscObjectGetComm((PetscObject)J,&comm);

731:   MatShellGetContext(J,(void **)&ctx);
732:   /* no context indicates that it is not the "matrix free" matrix type */
733:   if (!ctx) return(0);
734:   ctx->sp = nullsp;
735:   PetscObjectReference((PetscObject)nullsp);
736:   return(0);
737: }

739: /*@
740:    MatSNESMFSetHHistory - Sets an array to collect a history of the
741:    differencing values (h) computed for the matrix-free product.

743:    Collective on Mat 

745:    Input Parameters:
746: +  J - the matrix-free matrix context
747: .  histroy - space to hold the history
748: -  nhistory - number of entries in history, if more entries are generated than
749:               nhistory, then the later ones are discarded

751:    Level: advanced

753:    Notes:
754:    Use MatSNESMFResetHHistory() to reset the history counter and collect
755:    a new batch of differencing parameters, h.

757: .keywords: SNES, matrix-free, h history, differencing history

759: .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
760:           MatSNESMFResetHHistory(),
761:           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()

763: @*/
764: int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory)
765: {
766:   int          ierr;
767:   MatSNESMFCtx ctx;


771:   MatShellGetContext(J,(void **)&ctx);
772:   /* no context indicates that it is not the "matrix free" matrix type */
773:   if (!ctx) return(0);
774:   ctx->historyh    = history;
775:   ctx->maxcurrenth = nhistory;
776:   ctx->currenth    = 0;

778:   return(0);
779: }

781: /*@
782:    MatSNESMFResetHHistory - Resets the counter to zero to begin 
783:    collecting a new set of differencing histories.

785:    Collective on Mat 

787:    Input Parameters:
788: .  J - the matrix-free matrix context

790:    Level: advanced

792:    Notes:
793:    Use MatSNESMFSetHHistory() to create the original history counter.

795: .keywords: SNES, matrix-free, h history, differencing history

797: .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
798:           MatSNESMFSetHHistory(),
799:           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()

801: @*/
802: int MatSNESMFResetHHistory(Mat J)
803: {
804:   int          ierr;
805:   MatSNESMFCtx ctx;


809:   MatShellGetContext(J,(void **)&ctx);
810:   /* no context indicates that it is not the "matrix free" matrix type */
811:   if (!ctx) return(0);
812:   ctx->ncurrenth    = 0;

814:   return(0);
815: }

817: int MatSNESMFFormJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy)
818: {
821:   MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);
822:   MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);
823:   return(0);
824: }

826: int MatSNESMFSetBase(Mat J,Vec U)
827: {
828:   int          ierr;
829:   MatSNESMFCtx ctx;


835:   MatShellGetContext(J,(void **)&ctx);
836:   ctx->current_u = U;
837:   ctx->usesnes   = PETSC_FALSE;
838:   return(0);
839: }