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