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