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