xref: /petsc/src/snes/mf/snesmfj.c (revision 549d3d68a6ae470532d58d544870024f02ff2d7c)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: snesmfj.c,v 1.85 1999/04/19 22:15:35 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   PetscFree(ctx->ops);
156   PetscFree(ctx);
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 
241   ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr);
242   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
243     eval_fct = SNESComputeFunction;
244     ierr = SNESGetFunction(snes,&F);CHKERRQ(ierr);
245   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
246     eval_fct = SNESComputeGradient;
247     ierr = SNESGetGradient(snes,&F);CHKERRQ(ierr);
248   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class");
249 
250   if (!ctx->ops->compute) {
251     ierr = MatSNESMFSetType(mat,"default");CHKERRQ(ierr);
252     ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr);
253   }
254   ierr = (*ctx->ops->compute)(ctx,U,a,&h);CHKERRQ(ierr);
255 
256   /* keep a record of the current differencing parameter h */
257   ctx->currenth = h;
258 #if defined(USE_PETSC_COMPLEX)
259   PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscReal(h),PetscImaginary(h));
260 #else
261   PLogInfo(mat,"Current differencing parameter: %g\n",h);
262 #endif
263   if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) {
264     ctx->historyh[ctx->ncurrenth++] = h;
265   } else {
266     ctx->ncurrenth++;
267   }
268 
269   /* Evaluate function at F(u + ha) */
270   ierr = VecWAXPY(&h,a,U,w);CHKERRQ(ierr);
271   ierr = eval_fct(snes,w,y);CHKERRQ(ierr);
272 
273   ierr = VecAXPY(&mone,F,y);CHKERRQ(ierr);
274   h = 1.0/h;
275   ierr = VecScale(&h,y);CHKERRQ(ierr);
276   if (ctx->sp) {ierr = PCNullSpaceRemove(ctx->sp,y);CHKERRQ(ierr);}
277 
278   PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);
279   PetscFunctionReturn(0);
280 }
281 
282 #undef __FUNC__
283 #define __FUNC__ "MatCreateSNESMF"
284 /*@C
285    MatCreateSNESMF - Creates a matrix-free matrix context for use with
286    a SNES solver.  This matrix can be used as the Jacobian argument for
287    the routine SNESSetJacobian().
288 
289    Collective on SNES and Vec
290 
291    Input Parameters:
292 +  snes - the SNES context
293 -  x - vector where SNES solution is to be stored.
294 
295    Output Parameter:
296 .  J - the matrix-free matrix
297 
298    Level: advanced
299 
300    Notes:
301    The matrix-free matrix context merely contains the function pointers
302    and work space for performing finite difference approximations of
303    Jacobian-vector products, F'(u)*a,
304 
305    The default code uses the following approach to compute h
306 
307 .vb
308      F'(u)*a = [F(u+h*a) - F(u)]/h where
309      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
310        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
311  where
312      error_rel = square root of relative error in function evaluation
313      umin = minimum iterate parameter
314 .ve
315 
316    The user can set the error_rel via MatSNESMFSetFunctionError() and
317    umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
318    of the users manual for details.
319 
320    The user should call MatDestroy() when finished with the matrix-free
321    matrix context.
322 
323    Options Database Keys:
324 +  -snes_mf_err <error_rel> - Sets error_rel
325 .  -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
326 -  -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h
327 
328 .keywords: SNES, default, matrix-free, create, matrix
329 
330 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
331           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
332           MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegister()
333 
334 @*/
335 int MatCreateSNESMF(SNES snes,Vec x, Mat *J)
336 {
337   MPI_Comm       comm;
338   MatSNESMFCtx mfctx;
339   int            n, nloc, ierr;
340 
341   PetscFunctionBegin;
342   mfctx = (MatSNESMFCtx) PetscMalloc(sizeof(struct _p_MatSNESMFCtx));CHKPTRQ(mfctx);
343   PLogObjectMemory(snes,sizeof(MatSNESMFCtx));
344   mfctx->comm         = snes->comm;
345   mfctx->sp           = 0;
346   mfctx->snes         = snes;
347   mfctx->error_rel    = 1.e-8; /* assumes double precision */
348   mfctx->currenth     = 0.0;
349   mfctx->historyh     = PETSC_NULL;
350   mfctx->ncurrenth    = 0;
351   mfctx->maxcurrenth  = 0;
352 
353   /*
354      Create the empty data structure to contain compute-h routines.
355      These will be filled in below from the command line options or
356      a later call with MatSNESMFSetType() or if that is not called
357      then it will default in the first use of MatSNESMFMult_private()
358   */
359   mfctx->ops                 = (MFOps *)PetscMalloc(sizeof(MFOps));CHKPTRQ(mfctx->ops);
360   mfctx->ops->compute        = 0;
361   mfctx->ops->destroy        = 0;
362   mfctx->ops->view           = 0;
363   mfctx->ops->printhelp      = 0;
364   mfctx->ops->setfromoptions = 0;
365   mfctx->hctx                = 0;
366 
367   ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr);
368   ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr);
369   ierr = VecGetSize(x,&n);CHKERRQ(ierr);
370   ierr = VecGetLocalSize(x,&nloc);CHKERRQ(ierr);
371   ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr);
372   ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr);
373   ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr);
374   ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr);
375   ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr);
376   PLogObjectParent(*J,mfctx->w);
377   PLogObjectParent(snes,*J);
378 
379   mfctx->mat = *J;
380 
381 
382   PetscFunctionReturn(0);
383 }
384 
385 #undef __FUNC__
386 #define __FUNC__ "MatSNESMFSetFromOptions"
387 /*@
388    MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line
389    parameter.
390 
391    Collective on Mat
392 
393    Input Parameters:
394 .  mat - the matrix obtained with MatCreateSNESMF()
395 
396    Options Database Keys:
397 +  -snes_mf_type - <default,wp>
398 -  -snes_mf_err - square root of estimated relative error in function evaluation
399 
400    Level: advanced
401 
402 .keywords: SNES, matrix-free, parameters
403 
404 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
405           MatSNESMFResetHHistory(), MatSNESMFKSPMonitor()
406 @*/
407 int MatSNESMFSetFromOptions(Mat mat)
408 {
409   MatSNESMFCtx mfctx;
410   int            ierr,flg;
411   char           ftype[256],p[64];
412 
413   PetscFunctionBegin;
414   ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr);
415   if (mfctx) {
416     /* allow user to set the type */
417     ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr);
418     if (flg) {
419       ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr);
420     }
421 
422     ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg);CHKERRQ(ierr);
423     if (mfctx->ops->setfromoptions) {
424       ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr);
425     }
426 
427     ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr);
428     ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
429     if (mfctx->snes->prefix) {ierr = PetscStrcat(p,mfctx->snes->prefix);CHKERRQ(ierr);}
430     if (flg) {
431       ierr = (*PetscHelpPrintf)(mfctx->snes->comm,"   %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);CHKERRQ(ierr);
432       if (mfctx->ops->printhelp) {
433         ierr = (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr);
434       }
435     }
436   }
437   PetscFunctionReturn(0);
438 }
439 
440 #undef __FUNC__
441 #define __FUNC__ "MatSNESMFGetH"
442 /*@
443    MatSNESMFGetH - Gets the last value that was used as the differencing
444    parameter.
445 
446    Not Collective
447 
448    Input Parameters:
449 .  mat - the matrix obtained with MatCreateSNESMF()
450 
451    Output Paramter:
452 .  h - the differencing step size
453 
454    Level: advanced
455 
456 .keywords: SNES, matrix-free, parameters
457 
458 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
459           MatSNESMFResetHHistory(),MatSNESMFKSPMonitor()
460 @*/
461 int MatSNESMFGetH(Mat mat,Scalar *h)
462 {
463   MatSNESMFCtx ctx;
464   int            ierr;
465 
466   PetscFunctionBegin;
467   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
468   if (ctx) {
469     *h = ctx->currenth;
470   }
471   PetscFunctionReturn(0);
472 }
473 
474 #undef __FUNC__
475 #define __FUNC__ "MatSNESMFKSPMonitor"
476 /*
477    MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc
478    SNES matrix free routines. Prints the differencing parameter used at
479    each step.
480 */
481 int MatSNESMFKSPMonitor(KSP ksp,int n,double rnorm,void *dummy)
482 {
483   PC             pc;
484   MatSNESMFCtx   ctx;
485   int            ierr;
486   Mat            mat;
487   MPI_Comm       comm;
488   PetscTruth     nonzeroinitialguess;
489 
490   PetscFunctionBegin;
491   ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr);
492   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
493   ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr);
494   ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
495   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
496   if (!ctx) {
497     SETERRQ(1,1,"Matrix is not a matrix free shell matrix");
498   }
499   if (n > 0 || nonzeroinitialguess) {
500 #if defined(USE_PETSC_COMPLEX)
501     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm,
502                 PetscReal(ctx->currenth),PetscImaginary(ctx->currenth));CHKERRQ(ierr);
503 #else
504     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr);
505 #endif
506   } else {
507     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr);
508   }
509   PetscFunctionReturn(0);
510 }
511 
512 #undef __FUNC__
513 #define __FUNC__ "MatSNESMFSetFunctionError"
514 /*@
515    MatSNESMFSetFunctionError - Sets the error_rel for the approximation of
516    matrix-vector products using finite differences.
517 
518    Collective on Mat
519 
520    Input Parameters:
521 +  mat - the matrix free matrix created via MatCreateSNESMF()
522 -  error_rel - relative error (should be set to the square root of
523                the relative error in the function evaluations)
524 
525    Options Database Keys:
526 +  -snes_mf_err <error_rel> - Sets error_rel
527 
528    Level: advanced
529 
530    Notes:
531    The default matrix-free matrix-vector product routine computes
532 .vb
533      F'(u)*a = [F(u+h*a) - F(u)]/h where
534      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
535        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   else
536 .ve
537 
538 .keywords: SNES, matrix-free, parameters
539 
540 .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
541           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
542           MatSNESMFKSPMonitor()
543 @*/
544 int MatSNESMFSetFunctionError(Mat mat,double error)
545 {
546   MatSNESMFCtx ctx;
547   int            ierr;
548 
549   PetscFunctionBegin;
550   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
551   if (ctx) {
552     if (error != PETSC_DEFAULT) ctx->error_rel = error;
553   }
554   PetscFunctionReturn(0);
555 }
556 
557 #undef __FUNC__
558 #define __FUNC__ "MatSNESMFAddNullSpace"
559 /*@
560    MatSNESMFAddNullSpace - Provides a null space that an operator is
561    supposed to have.  Since roundoff will create a small component in
562    the null space, if you know the null space you may have it
563    automatically removed.
564 
565    Collective on Mat
566 
567    Input Parameters:
568 +  J - the matrix-free matrix context
569 .  has_cnst - PETSC_TRUE or PETSC_FALSE, indicating whether null space has constants
570 .  n - number of vectors (excluding constant vector) in null space
571 -  vecs - the vectors that span the null space (excluding the constant vector);
572           these vectors must be orthonormal
573 
574    Level: advanced
575 
576 .keywords: SNES, matrix-free, null space
577 
578 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
579           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
580           MatSNESMFKSPMonitor(), MatSNESMFErrorRel()
581 
582 @*/
583 int MatSNESMFAddNullSpace(Mat J,int has_cnst,int n,Vec *vecs)
584 {
585   int            ierr;
586   MatSNESMFCtx ctx;
587   MPI_Comm       comm;
588 
589   PetscFunctionBegin;
590   ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr);
591 
592   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
593   /* no context indicates that it is not the "matrix free" matrix type */
594   if (!ctx) PetscFunctionReturn(0);
595   ierr = PCNullSpaceCreate(comm,has_cnst,n,vecs,&ctx->sp);CHKERRQ(ierr);
596   PetscFunctionReturn(0);
597 }
598 
599 #undef __FUNC__
600 #define __FUNC__ "MatSNESMFSetHHistory"
601 /*@
602    MatSNESMFSetHHistory - Sets an array to collect a history of the
603    differencing values (h) computed for the matrix-free product.
604 
605    Collective on Mat
606 
607    Input Parameters:
608 +  J - the matrix-free matrix context
609 .  histroy - space to hold the history
610 -  nhistory - number of entries in history, if more entries are generated than
611               nhistory, then the later ones are discarded
612 
613    Level: advanced
614 
615    Notes:
616    Use MatSNESMFResetHHistory() to reset the history counter and collect
617    a new batch of differencing parameters, h.
618 
619 .keywords: SNES, matrix-free, h history, differencing history
620 
621 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
622           MatSNESMFResetHHistory(),
623           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
624 
625 @*/
626 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory)
627 {
628   int            ierr;
629   MatSNESMFCtx ctx;
630 
631   PetscFunctionBegin;
632 
633   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
634   /* no context indicates that it is not the "matrix free" matrix type */
635   if (!ctx) PetscFunctionReturn(0);
636   ctx->historyh    = history;
637   ctx->maxcurrenth = nhistory;
638   ctx->currenth    = 0;
639 
640   PetscFunctionReturn(0);
641 }
642 
643 #undef __FUNC__
644 #define __FUNC__ "MatSNESMFResetHHistory"
645 /*@
646    MatSNESMFResetHHistory - Resets the counter to zero to begin
647    collecting a new set of differencing histories.
648 
649    Collective on Mat
650 
651    Input Parameters:
652 .  J - the matrix-free matrix context
653 
654    Level: advanced
655 
656    Notes:
657    Use MatSNESMFSetHHistory() to create the original history counter.
658 
659 .keywords: SNES, matrix-free, h history, differencing history
660 
661 .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
662           MatSNESMFSetHHistory(),
663           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
664 
665 @*/
666 int MatSNESMFResetHHistory(Mat J)
667 {
668   int            ierr;
669   MatSNESMFCtx ctx;
670 
671   PetscFunctionBegin;
672 
673   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
674   /* no context indicates that it is not the "matrix free" matrix type */
675   if (!ctx) PetscFunctionReturn(0);
676   ctx->ncurrenth    = 0;
677 
678   PetscFunctionReturn(0);
679 }
680 
681