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