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