xref: /petsc/src/snes/mf/snesmfj.c (revision ef03ded036f36641663ecc6dce7b752c397a5081)
1 /*$Id: snesmfj.c,v 1.110 2000/09/02 02:49:35 bsmith Exp balay $*/
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,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      ierr = ViewerASCIIPrintf(viewer,"    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     SETERRQ1(1,1,"Viewer type %s not supported for SNES matrix free matrix",((PetscObject)viewer)->type_name);
186   }
187   PetscFunctionReturn(0);
188 }
189 
190 #undef __FUNC__
191 #define __FUNC__ /*<a name=""></a>*/"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   MatSNESMFCtx j;
203 
204   PetscFunctionBegin;
205   ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr);
206   ierr = MatShellGetContext(J,(void **)&j);CHKERRQ(ierr);
207   if (j->snes) {
208     ierr = SNESGetSolution(j->snes,&j->current_u);CHKERRQ(ierr);
209     if (j->snes->method_class == SNES_NONLINEAR_EQUATIONS) {
210       ierr = SNESGetFunction(j->snes,&j->current_f,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
211     } else if (j->snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
212       ierr = SNESGetGradient(j->snes,&j->current_f,PETSC_NULL);CHKERRQ(ierr);
213     } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class");
214   }
215   PetscFunctionReturn(0);
216 }
217 
218 
219 #undef __FUNC__
220 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFMult_Private"
221 /*
222   MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector
223   product, y = F'(u)*a:
224 
225         y ~= (F(u + ha) - F(u))/h,
226   where F = nonlinear function, as set by SNESSetFunction()
227         u = current iterate
228         h = difference interval
229 */
230 int MatSNESMFMult_Private(Mat mat,Vec a,Vec y)
231 {
232   MatSNESMFCtx ctx;
233   SNES           snes;
234   Scalar         h,mone = -1.0;
235   Vec            w,U,F;
236   int            ierr,(*eval_fct)(SNES,Vec,Vec)=0;
237 
238   PetscFunctionBegin;
239   /* We log matrix-free matrix-vector products separately, so that we can
240      separate the performance monitoring from the cases that use conventional
241      storage.  We may eventually modify event logging to associate events
242      with particular objects, hence alleviating the more general problem. */
243   ierr = PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);CHKERRQ(ierr);
244 
245   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
246   snes = ctx->snes;
247   w    = ctx->w;
248   U    = ctx->current_u;
249 
250   /*
251       Compute differencing parameter
252   */
253   if (!ctx->ops->compute) {
254     ierr = MatSNESMFSetType(mat,MATSNESMF_DEFAULT);CHKERRQ(ierr);
255     ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr);
256   }
257   ierr = (*ctx->ops->compute)(ctx,U,a,&h);CHKERRQ(ierr);
258 
259   /* keep a record of the current differencing parameter h */
260   ctx->currenth = h;
261 #if defined(PETSC_USE_COMPLEX)
262   PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscRealPart(h),PetscImaginaryPart(h));
263 #else
264   PLogInfo(mat,"Current differencing parameter: %g\n",h);
265 #endif
266   if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) {
267     ctx->historyh[ctx->ncurrenth] = h;
268   }
269   ctx->ncurrenth++;
270 
271   /* w = u + ha */
272   ierr = VecWAXPY(&h,a,U,w);CHKERRQ(ierr);
273 
274 
275   if (!ctx->func) {
276     if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
277       eval_fct = SNESComputeFunction;
278     } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
279       eval_fct = SNESComputeGradient;
280     } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class");
281     F    = ctx->current_f;
282     if (!F) SETERRQ(1,1,"You must call MatAssembly() even on matrix-free matrices");
283     ierr = eval_fct(snes,w,y);CHKERRQ(ierr);
284   } else {
285     F = ctx->funcvec;
286     /* compute func(U) as base for differencing */
287     if (ctx->ncurrenth == 1) {
288       ierr = (*ctx->func)(snes,U,F,ctx->funcctx);CHKERRQ(ierr);
289     }
290     ierr = (*ctx->func)(snes,w,y,ctx->funcctx);CHKERRQ(ierr);
291   }
292 
293   ierr = VecAXPY(&mone,F,y);CHKERRQ(ierr);
294   h    = 1.0/h;
295   ierr = VecScale(&h,y);CHKERRQ(ierr);
296   if (ctx->sp) {ierr = MatNullSpaceRemove(ctx->sp,y,PETSC_NULL);CHKERRQ(ierr);}
297 
298   ierr = PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);CHKERRQ(ierr);
299   PetscFunctionReturn(0);
300 }
301 
302 #undef __FUNC__
303 #define __FUNC__ /*<a name=""></a>*/"MatCreateSNESMF"
304 /*@C
305    MatCreateSNESMF - Creates a matrix-free matrix context for use with
306    a SNES solver.  This matrix can be used as the Jacobian argument for
307    the routine SNESSetJacobian().
308 
309    Collective on SNES and Vec
310 
311    Input Parameters:
312 +  snes - the SNES context
313 -  x - vector where SNES solution is to be stored.
314 
315    Output Parameter:
316 .  J - the matrix-free matrix
317 
318    Level: advanced
319 
320    Notes:
321    The matrix-free matrix context merely contains the function pointers
322    and work space for performing finite difference approximations of
323    Jacobian-vector products, F'(u)*a,
324 
325    The default code uses the following approach to compute h
326 
327 .vb
328      F'(u)*a = [F(u+h*a) - F(u)]/h where
329      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
330        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
331  where
332      error_rel = square root of relative error in function evaluation
333      umin = minimum iterate parameter
334 .ve
335 
336    The user can set the error_rel via MatSNESMFSetFunctionError() and
337    umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
338    of the users manual for details.
339 
340    The user should call MatDestroy() when finished with the matrix-free
341    matrix context.
342 
343    Options Database Keys:
344 +  -snes_mf_err <error_rel> - Sets error_rel
345 .  -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
346 -  -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h
347 
348 .keywords: SNES, default, matrix-free, create, matrix
349 
350 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
351           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateMF(),
352           MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic), MatSNESMFFormJacobian()
353 
354 @*/
355 int MatCreateSNESMF(SNES snes,Vec x,Mat *J)
356 {
357   MatSNESMFCtx mfctx;
358   int          ierr;
359 
360   PetscFunctionBegin;
361   ierr = MatCreateMF(x,J);CHKERRQ(ierr);
362   ierr = MatShellGetContext(*J,(void **)&mfctx);CHKERRQ(ierr);
363   mfctx->snes = snes;
364   PLogObjectParent(snes,*J);
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNC__
369 #define __FUNC__ /*<a name=""></a>*/"MatCreateMF"
370 /*@C
371    MatCreateMF - Creates a matrix-free matrix. See also MatCreateSNESMF()
372 
373    Collective on Vec
374 
375    Input Parameters:
376 .  x - vector that defines layout of the vectors and matrices
377 
378    Output Parameter:
379 .  J - the matrix-free matrix
380 
381    Level: advanced
382 
383    Notes:
384    The matrix-free matrix context merely contains the function pointers
385    and work space for performing finite difference approximations of
386    Jacobian-vector products, F'(u)*a,
387 
388    The default code uses the following approach to compute h
389 
390 .vb
391      F'(u)*a = [F(u+h*a) - F(u)]/h where
392      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
393        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
394  where
395      error_rel = square root of relative error in function evaluation
396      umin = minimum iterate parameter
397 .ve
398 
399    The user can set the error_rel via MatSNESMFSetFunctionError() and
400    umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
401    of the users manual for details.
402 
403    The user should call MatDestroy() when finished with the matrix-free
404    matrix context.
405 
406    Options Database Keys:
407 +  -snes_mf_err <error_rel> - Sets error_rel
408 .  -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
409 -  -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h
410 
411 .keywords: default, matrix-free, create, matrix
412 
413 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
414           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateSNESMF(),
415           MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic),, MatSNESMFFormJacobian()
416 
417 @*/
418 int MatCreateMF(Vec x,Mat *J)
419 {
420   MPI_Comm     comm;
421   MatSNESMFCtx mfctx;
422   int          n,nloc,ierr;
423 
424   PetscFunctionBegin;
425   ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr);
426   PetscHeaderCreate(mfctx,_p_MatSNESMFCtx,struct _MFOps,MATSNESMFCTX_COOKIE,0,"SNESMF",comm,MatSNESMFDestroy_Private,MatSNESMFView_Private);
427   PLogObjectCreate(mfctx);
428   mfctx->sp              = 0;
429   mfctx->snes            = 0;
430   mfctx->error_rel       = 1.e-8; /* assumes PetscReal precision */
431   mfctx->recomputeperiod = 1;
432   mfctx->count           = 0;
433   mfctx->currenth        = 0.0;
434   mfctx->historyh        = PETSC_NULL;
435   mfctx->ncurrenth       = 0;
436   mfctx->maxcurrenth     = 0;
437   mfctx->type_name       = 0;
438 
439   /*
440      Create the empty data structure to contain compute-h routines.
441      These will be filled in below from the command line options or
442      a later call with MatSNESMFSetType() or if that is not called
443      then it will default in the first use of MatSNESMFMult_private()
444   */
445   mfctx->ops->compute        = 0;
446   mfctx->ops->destroy        = 0;
447   mfctx->ops->view           = 0;
448   mfctx->ops->setfromoptions = 0;
449   mfctx->hctx                = 0;
450 
451   mfctx->func                = 0;
452   mfctx->funcctx             = 0;
453   mfctx->funcvec             = 0;
454 
455   ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr);
456   ierr = VecGetSize(mfctx->w,&n);CHKERRQ(ierr);
457   ierr = VecGetLocalSize(mfctx->w,&nloc);CHKERRQ(ierr);
458   ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr);
459   ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr);
460   ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr);
461   ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr);
462   ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr);
463   PLogObjectParent(*J,mfctx->w);
464 
465   mfctx->mat = *J;
466   PetscFunctionReturn(0);
467 }
468 
469 #undef __FUNC__
470 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFromOptions"
471 /*@
472    MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line
473    parameter.
474 
475    Collective on Mat
476 
477    Input Parameters:
478 .  mat - the matrix obtained with MatCreateSNESMF()
479 
480    Options Database Keys:
481 +  -snes_mf_type - <default,wp>
482 -  -snes_mf_err - square root of estimated relative error in function evaluation
483 -  -snes_mf_period - how often h is recomputed, defaults to 1, everytime
484 
485    Level: advanced
486 
487 .keywords: SNES, matrix-free, parameters
488 
489 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
490           MatSNESMFResetHHistory(), MatSNESMFKSPMonitor()
491 @*/
492 int MatSNESMFSetFromOptions(Mat mat)
493 {
494   MatSNESMFCtx mfctx;
495   int          ierr;
496   PetscTruth   flg;
497   char         ftype[256];
498 
499   PetscFunctionBegin;
500   ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr);
501   if (mfctx) {
502     if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
503 
504     ierr = OptionsBegin(mfctx->comm,mfctx->prefix,"Set matrix free computation parameters");CHKERRQ(ierr);
505       ierr = OptionsList("-snes_mf_type","Matrix free type","MatSNESMFSetType",MatSNESMFList,mfctx->type_name,ftype,256,&flg);CHKERRQ(ierr);
506       if (flg) {
507         ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr);
508       }
509 
510       ierr = OptionsDouble("-snes_mf_err","set sqrt relative error in function","MatSNESMFSetFunctionError",mfctx->error_rel,&mfctx->error_rel,0);CHKERRQ(ierr);
511       ierr = OptionsInt("-snes_mf_period","how often h is recomputed","MatSNESMFSetPeriod",mfctx->recomputeperiod,&mfctx->recomputeperiod,0);CHKERRQ(ierr);
512       if (mfctx->snes) {
513         ierr = OptionsName("-snes_mf_ksp_monitor","Monitor matrix-free parameters","MatSNESMFKSPMonitor",&flg);CHKERRQ(ierr);
514         if (flg) {
515           SLES sles;
516           KSP  ksp;
517           ierr = SNESGetSLES(mfctx->snes,&sles);CHKERRQ(ierr);
518           ierr = SLESGetKSP(sles,&ksp);CHKERRQ(ierr);
519           ierr = KSPSetMonitor(ksp,MatSNESMFKSPMonitor,PETSC_NULL,0);CHKERRQ(ierr);
520         }
521       }
522       if (mfctx->ops->setfromoptions) {
523         ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr);
524       }
525     ierr = OptionsEnd();CHKERRQ(ierr);
526 
527   }
528   PetscFunctionReturn(0);
529 }
530 
531 #undef __FUNC__
532 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFGetH"
533 /*@
534    MatSNESMFGetH - Gets the last value that was used as the differencing
535    parameter.
536 
537    Not Collective
538 
539    Input Parameters:
540 .  mat - the matrix obtained with MatCreateSNESMF()
541 
542    Output Paramter:
543 .  h - the differencing step size
544 
545    Level: advanced
546 
547 .keywords: SNES, matrix-free, parameters
548 
549 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
550           MatSNESMFResetHHistory(),MatSNESMFKSPMonitor()
551 @*/
552 int MatSNESMFGetH(Mat mat,Scalar *h)
553 {
554   MatSNESMFCtx ctx;
555   int          ierr;
556 
557   PetscFunctionBegin;
558   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
559   if (ctx) {
560     *h = ctx->currenth;
561   }
562   PetscFunctionReturn(0);
563 }
564 
565 #undef __FUNC__
566 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFKSPMonitor"
567 /*
568    MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc
569    SNES matrix free routines. Prints the differencing parameter used at
570    each step.
571 */
572 int MatSNESMFKSPMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
573 {
574   PC             pc;
575   MatSNESMFCtx   ctx;
576   int            ierr;
577   Mat            mat;
578   MPI_Comm       comm;
579   PetscTruth     nonzeroinitialguess;
580 
581   PetscFunctionBegin;
582   ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr);
583   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
584   ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr);
585   ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
586   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
587   if (!ctx) {
588     SETERRQ(1,1,"Matrix is not a matrix free shell matrix");
589   }
590   if (n > 0 || nonzeroinitialguess) {
591 #if defined(PETSC_USE_COMPLEX)
592     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm,
593                 PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));CHKERRQ(ierr);
594 #else
595     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr);
596 #endif
597   } else {
598     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr);
599   }
600   PetscFunctionReturn(0);
601 }
602 
603 #undef __FUNC__
604 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFunction"
605 /*@C
606    MatSNESMFSetFunction - Sets the function used in applying the matrix free.
607 
608    Collective on Mat
609 
610    Input Parameters:
611 +  mat - the matrix free matrix created via MatCreateSNESMF()
612 .  v   - workspace vector
613 .  func - the function to use
614 -  funcctx - optional function context passed to function
615 
616    Level: advanced
617 
618    Notes:
619     If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free
620     matrix inside your compute Jacobian routine
621 
622     If this is not set then it will use the function set with SNESSetFunction()
623 
624 .keywords: SNES, matrix-free, function
625 
626 .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
627           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
628           MatSNESMFKSPMonitor(), SNESetFunction()
629 @*/
630 int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx)
631 {
632   MatSNESMFCtx ctx;
633   int          ierr;
634 
635   PetscFunctionBegin;
636   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
637   if (ctx) {
638     ctx->func    = func;
639     ctx->funcctx = funcctx;
640     ctx->funcvec = v;
641   }
642   PetscFunctionReturn(0);
643 }
644 
645 
646 #undef __FUNC__
647 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetPeriod"
648 /*@
649    MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime
650 
651    Collective on Mat
652 
653    Input Parameters:
654 +  mat - the matrix free matrix created via MatCreateSNESMF()
655 -  period - 1 for everytime, 2 for every second etc
656 
657    Options Database Keys:
658 +  -snes_mf_period <period>
659 
660    Level: advanced
661 
662 
663 .keywords: SNES, matrix-free, parameters
664 
665 .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
666           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
667           MatSNESMFKSPMonitor()
668 @*/
669 int MatSNESMFSetPeriod(Mat mat,int period)
670 {
671   MatSNESMFCtx ctx;
672   int          ierr;
673 
674   PetscFunctionBegin;
675   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
676   if (ctx) {
677     ctx->recomputeperiod = period;
678   }
679   PetscFunctionReturn(0);
680 }
681 
682 #undef __FUNC__
683 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFunctionError"
684 /*@
685    MatSNESMFSetFunctionError - Sets the error_rel for the approximation of
686    matrix-vector products using finite differences.
687 
688    Collective on Mat
689 
690    Input Parameters:
691 +  mat - the matrix free matrix created via MatCreateSNESMF()
692 -  error_rel - relative error (should be set to the square root of
693                the relative error in the function evaluations)
694 
695    Options Database Keys:
696 +  -snes_mf_err <error_rel> - Sets error_rel
697 
698    Level: advanced
699 
700    Notes:
701    The default matrix-free matrix-vector product routine computes
702 .vb
703      F'(u)*a = [F(u+h*a) - F(u)]/h where
704      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
705        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   else
706 .ve
707 
708 .keywords: SNES, matrix-free, parameters
709 
710 .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
711           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
712           MatSNESMFKSPMonitor()
713 @*/
714 int MatSNESMFSetFunctionError(Mat mat,PetscReal error)
715 {
716   MatSNESMFCtx ctx;
717   int          ierr;
718 
719   PetscFunctionBegin;
720   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
721   if (ctx) {
722     if (error != PETSC_DEFAULT) ctx->error_rel = error;
723   }
724   PetscFunctionReturn(0);
725 }
726 
727 #undef __FUNC__
728 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFAddNullSpace"
729 /*@
730    MatSNESMFAddNullSpace - Provides a null space that an operator is
731    supposed to have.  Since roundoff will create a small component in
732    the null space, if you know the null space you may have it
733    automatically removed.
734 
735    Collective on Mat
736 
737    Input Parameters:
738 +  J - the matrix-free matrix context
739 -  nullsp - object created with MatNullSpaceCreate()
740 
741    Level: advanced
742 
743 .keywords: SNES, matrix-free, null space
744 
745 .seealso: MatNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(),
746           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
747           MatSNESMFKSPMonitor(), MatSNESMFErrorRel()
748 @*/
749 int MatSNESMFAddNullSpace(Mat J,MatNullSpace nullsp)
750 {
751   int          ierr;
752   MatSNESMFCtx ctx;
753   MPI_Comm     comm;
754 
755   PetscFunctionBegin;
756   ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr);
757 
758   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
759   /* no context indicates that it is not the "matrix free" matrix type */
760   if (!ctx) PetscFunctionReturn(0);
761   ctx->sp = nullsp;
762   ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr);
763   PetscFunctionReturn(0);
764 }
765 
766 #undef __FUNC__
767 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetHHistory"
768 /*@
769    MatSNESMFSetHHistory - Sets an array to collect a history of the
770    differencing values (h) computed for the matrix-free product.
771 
772    Collective on Mat
773 
774    Input Parameters:
775 +  J - the matrix-free matrix context
776 .  histroy - space to hold the history
777 -  nhistory - number of entries in history, if more entries are generated than
778               nhistory, then the later ones are discarded
779 
780    Level: advanced
781 
782    Notes:
783    Use MatSNESMFResetHHistory() to reset the history counter and collect
784    a new batch of differencing parameters, h.
785 
786 .keywords: SNES, matrix-free, h history, differencing history
787 
788 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
789           MatSNESMFResetHHistory(),
790           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
791 
792 @*/
793 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory)
794 {
795   int          ierr;
796   MatSNESMFCtx ctx;
797 
798   PetscFunctionBegin;
799 
800   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
801   /* no context indicates that it is not the "matrix free" matrix type */
802   if (!ctx) PetscFunctionReturn(0);
803   ctx->historyh    = history;
804   ctx->maxcurrenth = nhistory;
805   ctx->currenth    = 0;
806 
807   PetscFunctionReturn(0);
808 }
809 
810 #undef __FUNC__
811 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFResetHHistory"
812 /*@
813    MatSNESMFResetHHistory - Resets the counter to zero to begin
814    collecting a new set of differencing histories.
815 
816    Collective on Mat
817 
818    Input Parameters:
819 .  J - the matrix-free matrix context
820 
821    Level: advanced
822 
823    Notes:
824    Use MatSNESMFSetHHistory() to create the original history counter.
825 
826 .keywords: SNES, matrix-free, h history, differencing history
827 
828 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
829           MatSNESMFSetHHistory(),
830           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
831 
832 @*/
833 int MatSNESMFResetHHistory(Mat J)
834 {
835   int          ierr;
836   MatSNESMFCtx ctx;
837 
838   PetscFunctionBegin;
839 
840   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
841   /* no context indicates that it is not the "matrix free" matrix type */
842   if (!ctx) PetscFunctionReturn(0);
843   ctx->ncurrenth    = 0;
844 
845   PetscFunctionReturn(0);
846 }
847 
848 #undef __FUNC__
849 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFFormJacobian"
850 int MatSNESMFFormJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy)
851 {
852   int ierr;
853   PetscFunctionBegin;
854   ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
855   ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
856   PetscFunctionReturn(0);
857 }
858 
859 #undef __FUNC__
860 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetBase"
861 int MatSNESMFSetBase(Mat J,Vec U)
862 {
863   int          ierr;
864   MatSNESMFCtx ctx;
865 
866   PetscFunctionBegin;
867   PetscValidHeaderSpecific(J,MAT_COOKIE);
868   PetscValidHeaderSpecific(U,VEC_COOKIE);
869 
870   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
871   ctx->current_u = U;
872   PetscFunctionReturn(0);
873 }
874