xref: /petsc/src/snes/mf/snesmfj.c (revision 7c2000337a446092e4e06a20f2ff73813d334fd7)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: snesmfj.c,v 1.92 1999/10/01 21:22:26 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 
38   PetscFunctionBegin;
39   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
40 
41   /* already set, so just return */
42   if (PetscTypeCompare(ctx,ftype)) PetscFunctionReturn(0);
43 
44   /* destroy the old one if it exists */
45   if (ctx->ops->destroy) {
46     ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);
47   }
48 
49   /* Get the function pointers for the requrested method */
50   if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
51 
52   ierr =  FListFind(ctx->comm, MatSNESMFList, ftype,(int (**)(void *)) &r );CHKERRQ(ierr);
53 
54   if (!r) SETERRQ(1,1,"Unknown MatSNESMF type given");
55 
56   ierr = (*r)(ctx);CHKERRQ(ierr);
57   ierr = PetscStrncpy(ctx->type_name,ftype,256);CHKERRQ(ierr);
58 
59   PetscFunctionReturn(0);
60 }
61 
62 /*MC
63    MatSNESMFRegister - Adds a method to the MatSNESMF registry.
64 
65    Synopsis:
66    MatSNESMFRegister(char *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESMF))
67 
68    Not Collective
69 
70    Input Parameters:
71 +  name_solver - name of a new user-defined compute-h module
72 .  path - path (either absolute or relative) the library containing this solver
73 .  name_create - name of routine to create method context
74 -  routine_create - routine to create method context
75 
76    Level: developer
77 
78    Notes:
79    MatSNESMFRegister() may be called multiple times to add several user-defined solvers.
80 
81    If dynamic libraries are used, then the fourth input argument (routine_create)
82    is ignored.
83 
84    Sample usage:
85 .vb
86    MatSNESMFRegister("my_h",/home/username/my_lib/lib/libO/solaris/mylib.a,
87                "MyHCreate",MyHCreate);
88 .ve
89 
90    Then, your solver can be chosen with the procedural interface via
91 $     MatSNESMFSetType(mfctx,"my_h")
92    or at runtime via the option
93 $     -snes_mf_type my_h
94 
95 .keywords: MatSNESMF, register
96 
97 .seealso: MatSNESMFRegisterAll(), MatSNESMFRegisterDestroy()
98 M*/
99 
100 #undef __FUNC__
101 #define __FUNC__ "MatSNESMFRegister_Private"
102 int MatSNESMFRegister_Private(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx))
103 {
104   int ierr;
105   char fullname[256];
106 
107   PetscFunctionBegin;
108   ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr);
109   PetscStrcat(fullname,":");PetscStrcat(fullname,name);
110   ierr = FListAdd_Private(&MatSNESMFList,sname,fullname,(int (*)(void*))function);CHKERRQ(ierr);
111   PetscFunctionReturn(0);
112 }
113 
114 
115 #undef __FUNC__
116 #define __FUNC__ "MatSNESMFRegisterDestroy"
117 /*@C
118    MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were
119    registered by MatSNESMFRegister().
120 
121    Not Collective
122 
123    Level: developer
124 
125 .keywords: MatSNESMF, register, destroy
126 
127 .seealso: MatSNESMFRegister(), MatSNESMFRegisterAll()
128 @*/
129 int MatSNESMFRegisterDestroy(void)
130 {
131   int ierr;
132 
133   PetscFunctionBegin;
134   if (MatSNESMFList) {
135     ierr = FListDestroy( MatSNESMFList );CHKERRQ(ierr);
136     MatSNESMFList = 0;
137   }
138   MatSNESMFRegisterAllCalled = 0;
139   PetscFunctionReturn(0);
140 }
141 
142 /* ----------------------------------------------------------------------------------------*/
143 #undef __FUNC__
144 #define __FUNC__ "MatSNESMFDestroy_Private"
145 int MatSNESMFDestroy_Private(Mat mat)
146 {
147   int          ierr;
148   MatSNESMFCtx ctx;
149 
150   PetscFunctionBegin;
151   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
152   ierr = VecDestroy(ctx->w);CHKERRQ(ierr);
153   if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);}
154   if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);}
155   ierr = PetscFree(ctx->ops);CHKERRQ(ierr);
156   ierr = PetscFree(ctx);CHKERRQ(ierr);
157   PetscFunctionReturn(0);
158 }
159 
160 #undef __FUNC__
161 #define __FUNC__ "MatSNESMFView_Private"
162 /*
163    MatSNESMFView_Private - Views matrix-free parameters.
164 
165 */
166 int MatSNESMFView_Private(Mat J,Viewer viewer)
167 {
168   int          ierr;
169   MatSNESMFCtx ctx;
170   MPI_Comm     comm;
171   FILE         *fd;
172 
173   PetscFunctionBegin;
174   ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr);
175   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
176   ierr = ViewerASCIIGetPointer(viewer,&fd);CHKERRQ(ierr);
177   if (PetscTypeCompare(viewer,ASCII_VIEWER)) {
178      ierr = PetscFPrintf(comm,fd,"  SNES matrix-free approximation:\n");CHKERRQ(ierr);
179      ierr = PetscFPrintf(comm,fd,"    err=%g (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr);
180      ierr = PetscFPrintf(ctx->comm,fd,"    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     SETERRQ(1,1,"Viewer type not supported for this object");
186   }
187   PetscFunctionReturn(0);
188 }
189 
190 #undef __FUNC__
191 #define __FUNC__ "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__ "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,"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",PetscReal(h),PetscImaginary(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);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 = PCNullSpaceRemove(ctx->sp,y);CHKERRQ(ierr);}
287 
288   PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);
289   PetscFunctionReturn(0);
290 }
291 
292 #undef __FUNC__
293 #define __FUNC__ "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(), MatSNESMFRegister()
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   mfctx = (MatSNESMFCtx) PetscMalloc(sizeof(struct _p_MatSNESMFCtx));CHKPTRQ(mfctx);
353   PLogObjectMemory(snes,sizeof(MatSNESMFCtx));
354   mfctx->comm         = snes->comm;
355   mfctx->sp           = 0;
356   mfctx->snes         = snes;
357   mfctx->error_rel    = 1.e-8; /* assumes double precision */
358   mfctx->currenth     = 0.0;
359   mfctx->historyh     = PETSC_NULL;
360   mfctx->ncurrenth    = 0;
361   mfctx->maxcurrenth  = 0;
362 
363   /*
364      Create the empty data structure to contain compute-h routines.
365      These will be filled in below from the command line options or
366      a later call with MatSNESMFSetType() or if that is not called
367      then it will default in the first use of MatSNESMFMult_private()
368   */
369   mfctx->ops                 = (MFOps *)PetscMalloc(sizeof(MFOps));CHKPTRQ(mfctx->ops);
370   mfctx->ops->compute        = 0;
371   mfctx->ops->destroy        = 0;
372   mfctx->ops->view           = 0;
373   mfctx->ops->printhelp      = 0;
374   mfctx->ops->setfromoptions = 0;
375   mfctx->hctx                = 0;
376 
377   mfctx->func                = 0;
378   mfctx->funcctx             = 0;
379   mfctx->funcvec             = 0;
380 
381   ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr);
382   ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr);
383   ierr = VecGetSize(x,&n);CHKERRQ(ierr);
384   ierr = VecGetLocalSize(x,&nloc);CHKERRQ(ierr);
385   ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr);
386   ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr);
387   ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr);
388   ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr);
389   ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr);
390   PLogObjectParent(*J,mfctx->w);
391   PLogObjectParent(snes,*J);
392 
393   mfctx->mat = *J;
394 
395 
396   PetscFunctionReturn(0);
397 }
398 
399 #undef __FUNC__
400 #define __FUNC__ "MatSNESMFSetFromOptions"
401 /*@
402    MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line
403    parameter.
404 
405    Collective on Mat
406 
407    Input Parameters:
408 .  mat - the matrix obtained with MatCreateSNESMF()
409 
410    Options Database Keys:
411 +  -snes_mf_type - <default,wp>
412 -  -snes_mf_err - square root of estimated relative error in function evaluation
413 
414    Level: advanced
415 
416 .keywords: SNES, matrix-free, parameters
417 
418 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
419           MatSNESMFResetHHistory(), MatSNESMFKSPMonitor()
420 @*/
421 int MatSNESMFSetFromOptions(Mat mat)
422 {
423   MatSNESMFCtx mfctx;
424   int          ierr,flg;
425   char         ftype[256],p[64];
426 
427   PetscFunctionBegin;
428   ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr);
429   if (mfctx) {
430     /* allow user to set the type */
431     ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr);
432     if (flg) {
433       ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr);
434     }
435 
436     ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg);CHKERRQ(ierr);
437     if (mfctx->ops->setfromoptions) {
438       ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr);
439     }
440 
441     ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr);
442     ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
443     if (mfctx->snes->prefix) {ierr = PetscStrcat(p,mfctx->snes->prefix);CHKERRQ(ierr);}
444     if (flg) {
445       ierr = (*PetscHelpPrintf)(mfctx->snes->comm,"   %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);CHKERRQ(ierr);
446       if (mfctx->ops->printhelp) {
447         ierr = (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr);
448       }
449     }
450   }
451   PetscFunctionReturn(0);
452 }
453 
454 #undef __FUNC__
455 #define __FUNC__ "MatSNESMFGetH"
456 /*@
457    MatSNESMFGetH - Gets the last value that was used as the differencing
458    parameter.
459 
460    Not Collective
461 
462    Input Parameters:
463 .  mat - the matrix obtained with MatCreateSNESMF()
464 
465    Output Paramter:
466 .  h - the differencing step size
467 
468    Level: advanced
469 
470 .keywords: SNES, matrix-free, parameters
471 
472 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
473           MatSNESMFResetHHistory(),MatSNESMFKSPMonitor()
474 @*/
475 int MatSNESMFGetH(Mat mat,Scalar *h)
476 {
477   MatSNESMFCtx ctx;
478   int          ierr;
479 
480   PetscFunctionBegin;
481   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
482   if (ctx) {
483     *h = ctx->currenth;
484   }
485   PetscFunctionReturn(0);
486 }
487 
488 #undef __FUNC__
489 #define __FUNC__ "MatSNESMFKSPMonitor"
490 /*
491    MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc
492    SNES matrix free routines. Prints the differencing parameter used at
493    each step.
494 */
495 int MatSNESMFKSPMonitor(KSP ksp,int n,double rnorm,void *dummy)
496 {
497   PC             pc;
498   MatSNESMFCtx   ctx;
499   int            ierr;
500   Mat            mat;
501   MPI_Comm       comm;
502   PetscTruth     nonzeroinitialguess;
503 
504   PetscFunctionBegin;
505   ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr);
506   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
507   ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr);
508   ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
509   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
510   if (!ctx) {
511     SETERRQ(1,1,"Matrix is not a matrix free shell matrix");
512   }
513   if (n > 0 || nonzeroinitialguess) {
514 #if defined(PETSC_USE_COMPLEX)
515     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm,
516                 PetscReal(ctx->currenth),PetscImaginary(ctx->currenth));CHKERRQ(ierr);
517 #else
518     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr);
519 #endif
520   } else {
521     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr);
522   }
523   PetscFunctionReturn(0);
524 }
525 
526 #undef __FUNC__
527 #define __FUNC__ "MatSNESMFSetFunction"
528 /*@C
529    MatSNESMFSetFunction - Sets the function used in applying the matrix free.
530 
531    Collective on Mat
532 
533    Input Parameters:
534 +  mat - the matrix free matrix created via MatCreateSNESMF()
535 .  v   - workspace vector
536 .  func - the function to use
537 -  funcctx - optional function context passed to function
538 
539    Level: advanced
540 
541    Notes:
542     If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free
543     matrix inside your compute Jacobian routine
544 
545     If this is not set then it will use the function set with SNESSetFunction()
546 
547 .keywords: SNES, matrix-free, function
548 
549 .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
550           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
551           MatSNESMFKSPMonitor(), SNESetFunction()
552 @*/
553 int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx)
554 {
555   MatSNESMFCtx ctx;
556   int          ierr;
557 
558   PetscFunctionBegin;
559   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
560   if (ctx) {
561     ctx->func    = func;
562     ctx->funcctx = funcctx;
563     ctx->funcvec = v;
564   }
565   PetscFunctionReturn(0);
566 }
567 
568 
569 #undef __FUNC__
570 #define __FUNC__ "MatSNESMFSetFunctionError"
571 /*@
572    MatSNESMFSetFunctionError - Sets the error_rel for the approximation of
573    matrix-vector products using finite differences.
574 
575    Collective on Mat
576 
577    Input Parameters:
578 +  mat - the matrix free matrix created via MatCreateSNESMF()
579 -  error_rel - relative error (should be set to the square root of
580                the relative error in the function evaluations)
581 
582    Options Database Keys:
583 +  -snes_mf_err <error_rel> - Sets error_rel
584 
585    Level: advanced
586 
587    Notes:
588    The default matrix-free matrix-vector product routine computes
589 .vb
590      F'(u)*a = [F(u+h*a) - F(u)]/h where
591      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
592        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   else
593 .ve
594 
595 .keywords: SNES, matrix-free, parameters
596 
597 .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
598           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
599           MatSNESMFKSPMonitor()
600 @*/
601 int MatSNESMFSetFunctionError(Mat mat,double error)
602 {
603   MatSNESMFCtx ctx;
604   int          ierr;
605 
606   PetscFunctionBegin;
607   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
608   if (ctx) {
609     if (error != PETSC_DEFAULT) ctx->error_rel = error;
610   }
611   PetscFunctionReturn(0);
612 }
613 
614 #undef __FUNC__
615 #define __FUNC__ "MatSNESMFAddNullSpace"
616 /*@
617    MatSNESMFAddNullSpace - Provides a null space that an operator is
618    supposed to have.  Since roundoff will create a small component in
619    the null space, if you know the null space you may have it
620    automatically removed.
621 
622    Collective on Mat
623 
624    Input Parameters:
625 +  J - the matrix-free matrix context
626 -  nullsp - object created with PCNullSpaceCreate()
627 
628    Level: advanced
629 
630 .keywords: SNES, matrix-free, null space
631 
632 .seealso: PCNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(),
633           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
634           MatSNESMFKSPMonitor(), MatSNESMFErrorRel()
635 @*/
636 int MatSNESMFAddNullSpace(Mat J,PCNullSpace nullsp)
637 {
638   int          ierr;
639   MatSNESMFCtx ctx;
640   MPI_Comm     comm;
641 
642   PetscFunctionBegin;
643   ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr);
644 
645   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
646   /* no context indicates that it is not the "matrix free" matrix type */
647   if (!ctx) PetscFunctionReturn(0);
648   ctx->sp = nullsp;
649   ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr);
650   PetscFunctionReturn(0);
651 }
652 
653 #undef __FUNC__
654 #define __FUNC__ "MatSNESMFSetHHistory"
655 /*@
656    MatSNESMFSetHHistory - Sets an array to collect a history of the
657    differencing values (h) computed for the matrix-free product.
658 
659    Collective on Mat
660 
661    Input Parameters:
662 +  J - the matrix-free matrix context
663 .  histroy - space to hold the history
664 -  nhistory - number of entries in history, if more entries are generated than
665               nhistory, then the later ones are discarded
666 
667    Level: advanced
668 
669    Notes:
670    Use MatSNESMFResetHHistory() to reset the history counter and collect
671    a new batch of differencing parameters, h.
672 
673 .keywords: SNES, matrix-free, h history, differencing history
674 
675 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
676           MatSNESMFResetHHistory(),
677           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
678 
679 @*/
680 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory)
681 {
682   int          ierr;
683   MatSNESMFCtx ctx;
684 
685   PetscFunctionBegin;
686 
687   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
688   /* no context indicates that it is not the "matrix free" matrix type */
689   if (!ctx) PetscFunctionReturn(0);
690   ctx->historyh    = history;
691   ctx->maxcurrenth = nhistory;
692   ctx->currenth    = 0;
693 
694   PetscFunctionReturn(0);
695 }
696 
697 #undef __FUNC__
698 #define __FUNC__ "MatSNESMFResetHHistory"
699 /*@
700    MatSNESMFResetHHistory - Resets the counter to zero to begin
701    collecting a new set of differencing histories.
702 
703    Collective on Mat
704 
705    Input Parameters:
706 .  J - the matrix-free matrix context
707 
708    Level: advanced
709 
710    Notes:
711    Use MatSNESMFSetHHistory() to create the original history counter.
712 
713 .keywords: SNES, matrix-free, h history, differencing history
714 
715 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
716           MatSNESMFSetHHistory(),
717           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
718 
719 @*/
720 int MatSNESMFResetHHistory(Mat J)
721 {
722   int          ierr;
723   MatSNESMFCtx ctx;
724 
725   PetscFunctionBegin;
726 
727   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
728   /* no context indicates that it is not the "matrix free" matrix type */
729   if (!ctx) PetscFunctionReturn(0);
730   ctx->ncurrenth    = 0;
731 
732   PetscFunctionReturn(0);
733 }
734 
735