xref: /petsc/src/snes/mf/snesmfj.c (revision 6831982abb6453c2f3e25efecb5d0951d333371e)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: snesmfj.c,v 1.96 1999/10/13 20:38:27 bsmith Exp bsmith $";
3 #endif
4 
5 #include "src/snes/snesimpl.h"
6 #include "src/snes/mf/snesmfj.h"   /*I  "snes.h"   I*/
7 
8 FList MatSNESMFList              = 0;
9 int   MatSNESMFRegisterAllCalled = 0;
10 
11 #undef __FUNC__
12 #define __FUNC__ "MatSNESMFSetType"
13 /*@C
14     MatSNESMFSetType - Sets the method that is used to compute the
15     differencing parameter for finite difference matrix-free formulations.
16 
17     Input Parameters:
18 +   mat - the "matrix-free" matrix created via MatCreateSNESMF()
19 -   ftype - the type requested
20 
21     Level: advanced
22 
23     Notes:
24     For example, such routines can compute h for use in
25     Jacobian-vector products of the form
26 
27                         F(x+ha) - F(x)
28           F'(u)a  ~=  ----------------
29                               h
30 
31 .seealso: MatCreateSNESMF(), MatSNESMFRegister()
32 @*/
33 int MatSNESMFSetType(Mat mat,char *ftype)
34 {
35   int          ierr, (*r)(MatSNESMFCtx);
36   MatSNESMFCtx ctx;
37   PetscTruth   match;
38 
39   PetscFunctionBegin;
40   PetscValidHeaderSpecific(mat,MAT_COOKIE);
41   PetscValidCharPointer(ftype);
42 
43   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
44 
45   /* already set, so just return */
46   ierr = PetscTypeCompare((PetscObject)ctx,ftype,&match);CHKERRQ(ierr);
47   if (match) PetscFunctionReturn(0);
48 
49   /* destroy the old one if it exists */
50   if (ctx->ops->destroy) {
51     ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);
52   }
53 
54   /* Get the function pointers for the requrested method */
55   if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
56 
57   ierr =  FListFind(ctx->comm, MatSNESMFList, ftype,(int (**)(void *)) &r );CHKERRQ(ierr);
58 
59   if (!r) SETERRQ(1,1,"Unknown MatSNESMF type given");
60 
61   ierr = (*r)(ctx);CHKERRQ(ierr);
62 
63   ierr = PetscObjectChangeTypeName((PetscObject)ctx,ftype);CHKERRQ(ierr);
64 
65   PetscFunctionReturn(0);
66 }
67 
68 /*MC
69    MatSNESMFRegister - Adds a method to the MatSNESMF registry.
70 
71    Synopsis:
72    MatSNESMFRegister(char *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESMF))
73 
74    Not Collective
75 
76    Input Parameters:
77 +  name_solver - name of a new user-defined compute-h module
78 .  path - path (either absolute or relative) the library containing this solver
79 .  name_create - name of routine to create method context
80 -  routine_create - routine to create method context
81 
82    Level: developer
83 
84    Notes:
85    MatSNESMFRegister() may be called multiple times to add several user-defined solvers.
86 
87    If dynamic libraries are used, then the fourth input argument (routine_create)
88    is ignored.
89 
90    Sample usage:
91 .vb
92    MatSNESMFRegister("my_h",/home/username/my_lib/lib/libO/solaris/mylib.a,
93                "MyHCreate",MyHCreate);
94 .ve
95 
96    Then, your solver can be chosen with the procedural interface via
97 $     MatSNESMFSetType(mfctx,"my_h")
98    or at runtime via the option
99 $     -snes_mf_type my_h
100 
101 .keywords: MatSNESMF, register
102 
103 .seealso: MatSNESMFRegisterAll(), MatSNESMFRegisterDestroy()
104 M*/
105 
106 #undef __FUNC__
107 #define __FUNC__ "MatSNESMFRegister_Private"
108 int MatSNESMFRegister_Private(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx))
109 {
110   int ierr;
111   char fullname[256];
112 
113   PetscFunctionBegin;
114   ierr = FListConcat_Private(path,name,fullname); CHKERRQ(ierr);
115   ierr = FListAdd_Private(&MatSNESMFList,sname,fullname,(int (*)(void*))function);CHKERRQ(ierr);
116   PetscFunctionReturn(0);
117 }
118 
119 
120 #undef __FUNC__
121 #define __FUNC__ "MatSNESMFRegisterDestroy"
122 /*@C
123    MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were
124    registered by MatSNESMFRegister().
125 
126    Not Collective
127 
128    Level: developer
129 
130 .keywords: MatSNESMF, register, destroy
131 
132 .seealso: MatSNESMFRegister(), MatSNESMFRegisterAll()
133 @*/
134 int MatSNESMFRegisterDestroy(void)
135 {
136   int ierr;
137 
138   PetscFunctionBegin;
139   if (MatSNESMFList) {
140     ierr = FListDestroy( MatSNESMFList );CHKERRQ(ierr);
141     MatSNESMFList = 0;
142   }
143   MatSNESMFRegisterAllCalled = 0;
144   PetscFunctionReturn(0);
145 }
146 
147 /* ----------------------------------------------------------------------------------------*/
148 #undef __FUNC__
149 #define __FUNC__ "MatSNESMFDestroy_Private"
150 int MatSNESMFDestroy_Private(Mat mat)
151 {
152   int          ierr;
153   MatSNESMFCtx ctx;
154 
155   PetscFunctionBegin;
156   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
157   ierr = VecDestroy(ctx->w);CHKERRQ(ierr);
158   if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);}
159   if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);}
160   PetscHeaderDestroy(ctx);
161   PetscFunctionReturn(0);
162 }
163 
164 #undef __FUNC__
165 #define __FUNC__ "MatSNESMFView_Private"
166 /*
167    MatSNESMFView_Private - Views matrix-free parameters.
168 
169 */
170 int MatSNESMFView_Private(Mat J,Viewer viewer)
171 {
172   int          ierr;
173   MatSNESMFCtx ctx;
174   PetscTruth   isascii;
175 
176   PetscFunctionBegin;
177   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
178   ierr = PetscTypeCompare((PetscObject)viewer,ASCII_VIEWER,&isascii);CHKERRQ(ierr);
179   if (isascii) {
180      ierr = ViewerASCIIPrintf(viewer,"  SNES matrix-free approximation:\n");CHKERRQ(ierr);
181      ierr = ViewerASCIIPrintf(viewer,"    err=%g (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr);
182      ierr = ViewerASCIIPrintf(viewer,"    Using %s compute h routine\n",ctx->type_name);CHKERRQ(ierr);
183      if (ctx->ops->view) {
184        ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr);
185      }
186   } else {
187     SETERRQ1(1,1,"Viewer type %s not supported for SNES matrix free matrix",((PetscObject)viewer)->type_name);
188   }
189   PetscFunctionReturn(0);
190 }
191 
192 #undef __FUNC__
193 #define __FUNC__ "MatSNESMFAssemblyEnd_Private"
194 /*
195    MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This
196    allows the user to indicate the beginning of a new linear solve by calling
197    MatAssemblyXXX() on the matrix free matrix. This then allows the
198    MatSNESMFCreate_WP() to properly compute ||U|| only the first time
199    in the linear solver rather than every time.
200 */
201 int MatSNESMFAssemblyEnd_Private(Mat J)
202 {
203   int            ierr;
204 
205   PetscFunctionBegin;
206   ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr);
207   PetscFunctionReturn(0);
208 }
209 
210 
211 #undef __FUNC__
212 #define __FUNC__ "MatSNESMFMult_Private"
213 /*
214   MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector
215   product, y = F'(u)*a:
216 
217         y ~= ( F(u + ha) - F(u) )/h,
218   where F = nonlinear function, as set by SNESSetFunction()
219         u = current iterate
220         h = difference interval
221 */
222 int MatSNESMFMult_Private(Mat mat,Vec a,Vec y)
223 {
224   MatSNESMFCtx ctx;
225   SNES           snes;
226   Scalar         h, mone = -1.0;
227   Vec            w,U,F;
228   int            ierr, (*eval_fct)(SNES,Vec,Vec)=0;
229 
230   PetscFunctionBegin;
231   /* We log matrix-free matrix-vector products separately, so that we can
232      separate the performance monitoring from the cases that use conventional
233      storage.  We may eventually modify event logging to associate events
234      with particular objects, hence alleviating the more general problem. */
235   PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);
236 
237   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
238   snes = ctx->snes;
239   w    = ctx->w;
240   ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr);
241 
242   /*
243       Compute differencing parameter
244   */
245   if (!ctx->ops->compute) {
246     ierr = MatSNESMFSetType(mat,"default");CHKERRQ(ierr);
247     ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr);
248   }
249   ierr = (*ctx->ops->compute)(ctx,U,a,&h);CHKERRQ(ierr);
250 
251   /* keep a record of the current differencing parameter h */
252   ctx->currenth = h;
253 #if defined(PETSC_USE_COMPLEX)
254   PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscReal(h),PetscImaginary(h));
255 #else
256   PLogInfo(mat,"Current differencing parameter: %g\n",h);
257 #endif
258   if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) {
259     ctx->historyh[ctx->ncurrenth] = h;
260   }
261   ctx->ncurrenth++;
262 
263   /* w = u + ha */
264   ierr = VecWAXPY(&h,a,U,w);CHKERRQ(ierr);
265 
266 
267   if (!ctx->func) {
268     if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
269       eval_fct = SNESComputeFunction;
270       ierr     = SNESGetFunction(snes,&F,PETSC_NULL);CHKERRQ(ierr);
271     } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
272       eval_fct = SNESComputeGradient;
273       ierr     = SNESGetGradient(snes,&F,PETSC_NULL);CHKERRQ(ierr);
274     } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class");
275     ierr = eval_fct(snes,w,y);CHKERRQ(ierr);
276   } else {
277     F = ctx->funcvec;
278     /* compute func(U) as base for differencing */
279     if (ctx->ncurrenth == 1) {
280       ierr = (*ctx->func)(snes,U,F,ctx->funcctx);CHKERRQ(ierr);
281     }
282     ierr = (*ctx->func)(snes,w,y,ctx->funcctx);CHKERRQ(ierr);
283   }
284 
285   ierr = VecAXPY(&mone,F,y);CHKERRQ(ierr);
286   h    = 1.0/h;
287   ierr = VecScale(&h,y);CHKERRQ(ierr);
288   if (ctx->sp) {ierr = PCNullSpaceRemove(ctx->sp,y);CHKERRQ(ierr);}
289 
290   PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);
291   PetscFunctionReturn(0);
292 }
293 
294 #undef __FUNC__
295 #define __FUNC__ "MatCreateSNESMF"
296 /*@C
297    MatCreateSNESMF - Creates a matrix-free matrix context for use with
298    a SNES solver.  This matrix can be used as the Jacobian argument for
299    the routine SNESSetJacobian().
300 
301    Collective on SNES and Vec
302 
303    Input Parameters:
304 +  snes - the SNES context
305 -  x - vector where SNES solution is to be stored.
306 
307    Output Parameter:
308 .  J - the matrix-free matrix
309 
310    Level: advanced
311 
312    Notes:
313    The matrix-free matrix context merely contains the function pointers
314    and work space for performing finite difference approximations of
315    Jacobian-vector products, F'(u)*a,
316 
317    The default code uses the following approach to compute h
318 
319 .vb
320      F'(u)*a = [F(u+h*a) - F(u)]/h where
321      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
322        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
323  where
324      error_rel = square root of relative error in function evaluation
325      umin = minimum iterate parameter
326 .ve
327 
328    The user can set the error_rel via MatSNESMFSetFunctionError() and
329    umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
330    of the users manual for details.
331 
332    The user should call MatDestroy() when finished with the matrix-free
333    matrix context.
334 
335    Options Database Keys:
336 +  -snes_mf_err <error_rel> - Sets error_rel
337 .  -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
338 -  -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h
339 
340 .keywords: SNES, default, matrix-free, create, matrix
341 
342 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
343           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
344           MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegister()
345 
346 @*/
347 int MatCreateSNESMF(SNES snes,Vec x, Mat *J)
348 {
349   MPI_Comm     comm;
350   MatSNESMFCtx mfctx;
351   int          n, nloc, ierr;
352 
353   PetscFunctionBegin;
354   PetscHeaderCreate(mfctx,_p_MatSNESMFCtx,struct _MFOps,MATSNESMFCTX_COOKIE,0,"SNESMF",snes->comm,MatSNESMFDestroy_Private,MatSNESMFView_Private);
355   PLogObjectCreate(mfctx);
356   mfctx->sp           = 0;
357   mfctx->snes         = snes;
358   mfctx->error_rel    = 1.e-8; /* assumes double precision */
359   mfctx->currenth     = 0.0;
360   mfctx->historyh     = PETSC_NULL;
361   mfctx->ncurrenth    = 0;
362   mfctx->maxcurrenth  = 0;
363   mfctx->type_name    = 0;
364 
365   /*
366      Create the empty data structure to contain compute-h routines.
367      These will be filled in below from the command line options or
368      a later call with MatSNESMFSetType() or if that is not called
369      then it will default in the first use of MatSNESMFMult_private()
370   */
371   mfctx->ops->compute        = 0;
372   mfctx->ops->destroy        = 0;
373   mfctx->ops->view           = 0;
374   mfctx->ops->printhelp      = 0;
375   mfctx->ops->setfromoptions = 0;
376   mfctx->hctx                = 0;
377 
378   mfctx->func                = 0;
379   mfctx->funcctx             = 0;
380   mfctx->funcvec             = 0;
381 
382   ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr);
383   ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr);
384   ierr = VecGetSize(x,&n);CHKERRQ(ierr);
385   ierr = VecGetLocalSize(x,&nloc);CHKERRQ(ierr);
386   ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr);
387   ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr);
388   ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr);
389   ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr);
390   ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr);
391   PLogObjectParent(*J,mfctx->w);
392   PLogObjectParent(snes,*J);
393 
394   mfctx->mat = *J;
395 
396 
397   PetscFunctionReturn(0);
398 }
399 
400 #undef __FUNC__
401 #define __FUNC__ "MatSNESMFSetFromOptions"
402 /*@
403    MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line
404    parameter.
405 
406    Collective on Mat
407 
408    Input Parameters:
409 .  mat - the matrix obtained with MatCreateSNESMF()
410 
411    Options Database Keys:
412 +  -snes_mf_type - <default,wp>
413 -  -snes_mf_err - square root of estimated relative error in function evaluation
414 
415    Level: advanced
416 
417 .keywords: SNES, matrix-free, parameters
418 
419 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
420           MatSNESMFResetHHistory(), MatSNESMFKSPMonitor()
421 @*/
422 int MatSNESMFSetFromOptions(Mat mat)
423 {
424   MatSNESMFCtx mfctx;
425   int          ierr,flg;
426   char         ftype[256],p[64];
427 
428   PetscFunctionBegin;
429   ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr);
430   if (mfctx) {
431     /* allow user to set the type */
432     ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr);
433     if (flg) {
434       ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr);
435     }
436 
437     ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg);CHKERRQ(ierr);
438     if (mfctx->ops->setfromoptions) {
439       ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr);
440     }
441 
442     ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr);
443     ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
444     if (mfctx->snes->prefix) {ierr = PetscStrcat(p,mfctx->snes->prefix);CHKERRQ(ierr);}
445     if (flg) {
446       ierr = (*PetscHelpPrintf)(mfctx->snes->comm,"   %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);CHKERRQ(ierr);
447       if (mfctx->ops->printhelp) {
448         ierr = (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr);
449       }
450     }
451   }
452   PetscFunctionReturn(0);
453 }
454 
455 #undef __FUNC__
456 #define __FUNC__ "MatSNESMFGetH"
457 /*@
458    MatSNESMFGetH - Gets the last value that was used as the differencing
459    parameter.
460 
461    Not Collective
462 
463    Input Parameters:
464 .  mat - the matrix obtained with MatCreateSNESMF()
465 
466    Output Paramter:
467 .  h - the differencing step size
468 
469    Level: advanced
470 
471 .keywords: SNES, matrix-free, parameters
472 
473 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
474           MatSNESMFResetHHistory(),MatSNESMFKSPMonitor()
475 @*/
476 int MatSNESMFGetH(Mat mat,Scalar *h)
477 {
478   MatSNESMFCtx ctx;
479   int          ierr;
480 
481   PetscFunctionBegin;
482   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
483   if (ctx) {
484     *h = ctx->currenth;
485   }
486   PetscFunctionReturn(0);
487 }
488 
489 #undef __FUNC__
490 #define __FUNC__ "MatSNESMFKSPMonitor"
491 /*
492    MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc
493    SNES matrix free routines. Prints the differencing parameter used at
494    each step.
495 */
496 int MatSNESMFKSPMonitor(KSP ksp,int n,double rnorm,void *dummy)
497 {
498   PC             pc;
499   MatSNESMFCtx   ctx;
500   int            ierr;
501   Mat            mat;
502   MPI_Comm       comm;
503   PetscTruth     nonzeroinitialguess;
504 
505   PetscFunctionBegin;
506   ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr);
507   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
508   ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr);
509   ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
510   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
511   if (!ctx) {
512     SETERRQ(1,1,"Matrix is not a matrix free shell matrix");
513   }
514   if (n > 0 || nonzeroinitialguess) {
515 #if defined(PETSC_USE_COMPLEX)
516     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm,
517                 PetscReal(ctx->currenth),PetscImaginary(ctx->currenth));CHKERRQ(ierr);
518 #else
519     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr);
520 #endif
521   } else {
522     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr);
523   }
524   PetscFunctionReturn(0);
525 }
526 
527 #undef __FUNC__
528 #define __FUNC__ "MatSNESMFSetFunction"
529 /*@C
530    MatSNESMFSetFunction - Sets the function used in applying the matrix free.
531 
532    Collective on Mat
533 
534    Input Parameters:
535 +  mat - the matrix free matrix created via MatCreateSNESMF()
536 .  v   - workspace vector
537 .  func - the function to use
538 -  funcctx - optional function context passed to function
539 
540    Level: advanced
541 
542    Notes:
543     If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free
544     matrix inside your compute Jacobian routine
545 
546     If this is not set then it will use the function set with SNESSetFunction()
547 
548 .keywords: SNES, matrix-free, function
549 
550 .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
551           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
552           MatSNESMFKSPMonitor(), SNESetFunction()
553 @*/
554 int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx)
555 {
556   MatSNESMFCtx ctx;
557   int          ierr;
558 
559   PetscFunctionBegin;
560   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
561   if (ctx) {
562     ctx->func    = func;
563     ctx->funcctx = funcctx;
564     ctx->funcvec = v;
565   }
566   PetscFunctionReturn(0);
567 }
568 
569 
570 #undef __FUNC__
571 #define __FUNC__ "MatSNESMFSetFunctionError"
572 /*@
573    MatSNESMFSetFunctionError - Sets the error_rel for the approximation of
574    matrix-vector products using finite differences.
575 
576    Collective on Mat
577 
578    Input Parameters:
579 +  mat - the matrix free matrix created via MatCreateSNESMF()
580 -  error_rel - relative error (should be set to the square root of
581                the relative error in the function evaluations)
582 
583    Options Database Keys:
584 +  -snes_mf_err <error_rel> - Sets error_rel
585 
586    Level: advanced
587 
588    Notes:
589    The default matrix-free matrix-vector product routine computes
590 .vb
591      F'(u)*a = [F(u+h*a) - F(u)]/h where
592      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
593        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   else
594 .ve
595 
596 .keywords: SNES, matrix-free, parameters
597 
598 .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
599           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
600           MatSNESMFKSPMonitor()
601 @*/
602 int MatSNESMFSetFunctionError(Mat mat,double error)
603 {
604   MatSNESMFCtx ctx;
605   int          ierr;
606 
607   PetscFunctionBegin;
608   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
609   if (ctx) {
610     if (error != PETSC_DEFAULT) ctx->error_rel = error;
611   }
612   PetscFunctionReturn(0);
613 }
614 
615 #undef __FUNC__
616 #define __FUNC__ "MatSNESMFAddNullSpace"
617 /*@
618    MatSNESMFAddNullSpace - Provides a null space that an operator is
619    supposed to have.  Since roundoff will create a small component in
620    the null space, if you know the null space you may have it
621    automatically removed.
622 
623    Collective on Mat
624 
625    Input Parameters:
626 +  J - the matrix-free matrix context
627 -  nullsp - object created with PCNullSpaceCreate()
628 
629    Level: advanced
630 
631 .keywords: SNES, matrix-free, null space
632 
633 .seealso: PCNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(),
634           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
635           MatSNESMFKSPMonitor(), MatSNESMFErrorRel()
636 @*/
637 int MatSNESMFAddNullSpace(Mat J,PCNullSpace nullsp)
638 {
639   int          ierr;
640   MatSNESMFCtx ctx;
641   MPI_Comm     comm;
642 
643   PetscFunctionBegin;
644   ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr);
645 
646   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
647   /* no context indicates that it is not the "matrix free" matrix type */
648   if (!ctx) PetscFunctionReturn(0);
649   ctx->sp = nullsp;
650   ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr);
651   PetscFunctionReturn(0);
652 }
653 
654 #undef __FUNC__
655 #define __FUNC__ "MatSNESMFSetHHistory"
656 /*@
657    MatSNESMFSetHHistory - Sets an array to collect a history of the
658    differencing values (h) computed for the matrix-free product.
659 
660    Collective on Mat
661 
662    Input Parameters:
663 +  J - the matrix-free matrix context
664 .  histroy - space to hold the history
665 -  nhistory - number of entries in history, if more entries are generated than
666               nhistory, then the later ones are discarded
667 
668    Level: advanced
669 
670    Notes:
671    Use MatSNESMFResetHHistory() to reset the history counter and collect
672    a new batch of differencing parameters, h.
673 
674 .keywords: SNES, matrix-free, h history, differencing history
675 
676 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
677           MatSNESMFResetHHistory(),
678           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
679 
680 @*/
681 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory)
682 {
683   int          ierr;
684   MatSNESMFCtx ctx;
685 
686   PetscFunctionBegin;
687 
688   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
689   /* no context indicates that it is not the "matrix free" matrix type */
690   if (!ctx) PetscFunctionReturn(0);
691   ctx->historyh    = history;
692   ctx->maxcurrenth = nhistory;
693   ctx->currenth    = 0;
694 
695   PetscFunctionReturn(0);
696 }
697 
698 #undef __FUNC__
699 #define __FUNC__ "MatSNESMFResetHHistory"
700 /*@
701    MatSNESMFResetHHistory - Resets the counter to zero to begin
702    collecting a new set of differencing histories.
703 
704    Collective on Mat
705 
706    Input Parameters:
707 .  J - the matrix-free matrix context
708 
709    Level: advanced
710 
711    Notes:
712    Use MatSNESMFSetHHistory() to create the original history counter.
713 
714 .keywords: SNES, matrix-free, h history, differencing history
715 
716 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
717           MatSNESMFSetHHistory(),
718           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
719 
720 @*/
721 int MatSNESMFResetHHistory(Mat J)
722 {
723   int          ierr;
724   MatSNESMFCtx ctx;
725 
726   PetscFunctionBegin;
727 
728   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
729   /* no context indicates that it is not the "matrix free" matrix type */
730   if (!ctx) PetscFunctionReturn(0);
731   ctx->ncurrenth    = 0;
732 
733   PetscFunctionReturn(0);
734 }
735 
736