xref: /petsc/src/snes/mf/snesmfj.c (revision b7fd4e6495d18b4621d8034d33525ddf6d2b3232)
1*b7fd4e64SBarry Smith /*$Id: snesmfj.c,v 1.102 2000/04/01 04:21:11 bsmith Exp bsmith $*/
281e6777dSBarry Smith 
39a6cb015SBarry Smith #include "src/snes/snesimpl.h"
49a6cb015SBarry Smith #include "src/snes/mf/snesmfj.h"   /*I  "snes.h"   I*/
581e6777dSBarry Smith 
65a655dc6SBarry Smith FList      MatSNESMFList              = 0;
74c49b128SBarry Smith PetscTruth MatSNESMFRegisterAllCalled = PETSC_FALSE;
8a4d4d686SBarry Smith 
95615d1e5SSatish Balay #undef __FUNC__
105a655dc6SBarry Smith #define __FUNC__ "MatSNESMFSetType"
11fd4bdd07SBarry Smith /*@C
1265f2ba5bSLois Curfman McInnes     MatSNESMFSetType - Sets the method that is used to compute the
1365f2ba5bSLois Curfman McInnes     differencing parameter for finite difference matrix-free formulations.
149a6cb015SBarry Smith 
159a6cb015SBarry Smith     Input Parameters:
16ef4ad1fdSLois Curfman McInnes +   mat - the "matrix-free" matrix created via MatCreateSNESMF()
179a6cb015SBarry Smith -   ftype - the type requested
189a6cb015SBarry Smith 
1915091d37SBarry Smith     Level: advanced
2015091d37SBarry Smith 
2165f2ba5bSLois Curfman McInnes     Notes:
2265f2ba5bSLois Curfman McInnes     For example, such routines can compute h for use in
2365f2ba5bSLois Curfman McInnes     Jacobian-vector products of the form
2465f2ba5bSLois Curfman McInnes 
2565f2ba5bSLois Curfman McInnes                         F(x+ha) - F(x)
26ef4ad1fdSLois Curfman McInnes           F'(u)a  ~=  ----------------
2765f2ba5bSLois Curfman McInnes                               h
2865f2ba5bSLois Curfman McInnes 
29f1af5d2fSBarry Smith .seealso: MatCreateSNESMF(), MatSNESMFRegisterDynamic)
309a6cb015SBarry Smith @*/
31f6a0df18SBarry Smith int MatSNESMFSetType(Mat mat,MatSNESMFType ftype)
32b9fa9cd0SBarry Smith {
335a655dc6SBarry Smith   int          ierr,(*r)(MatSNESMFCtx);
345a655dc6SBarry Smith   MatSNESMFCtx ctx;
356831982aSBarry Smith   PetscTruth   match;
36a4d4d686SBarry Smith 
37a4d4d686SBarry Smith   PetscFunctionBegin;
380f5bd95cSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
390f5bd95cSBarry Smith   PetscValidCharPointer(ftype);
400f5bd95cSBarry Smith 
41a4d4d686SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
42a4d4d686SBarry Smith 
439a6cb015SBarry Smith   /* already set, so just return */
446831982aSBarry Smith   ierr = PetscTypeCompare((PetscObject)ctx,ftype,&match);CHKERRQ(ierr);
450f5bd95cSBarry Smith   if (match) PetscFunctionReturn(0);
46a4d4d686SBarry Smith 
479a6cb015SBarry Smith   /* destroy the old one if it exists */
489a6cb015SBarry Smith   if (ctx->ops->destroy) {
499a6cb015SBarry Smith     ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);
509a6cb015SBarry Smith   }
519a6cb015SBarry Smith 
5265f2ba5bSLois Curfman McInnes   /* Get the function pointers for the requrested method */
535a655dc6SBarry Smith   if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
549a6cb015SBarry Smith 
555a655dc6SBarry Smith   ierr =  FListFind(ctx->comm,MatSNESMFList,ftype,(int (**)(void *)) &r);CHKERRQ(ierr);
569a6cb015SBarry Smith 
575a655dc6SBarry Smith   if (!r) SETERRQ(1,1,"Unknown MatSNESMF type given");
589a6cb015SBarry Smith 
599a6cb015SBarry Smith   ierr = (*r)(ctx);CHKERRQ(ierr);
606831982aSBarry Smith 
616831982aSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)ctx,ftype);CHKERRQ(ierr);
629a6cb015SBarry Smith 
639a6cb015SBarry Smith   PetscFunctionReturn(0);
649a6cb015SBarry Smith }
659a6cb015SBarry Smith 
669a6cb015SBarry Smith /*MC
67f1af5d2fSBarry Smith    MatSNESMFRegisterDynamic - Adds a method to the MatSNESMF registry.
689a6cb015SBarry Smith 
699a6cb015SBarry Smith    Synopsis:
70f1af5d2fSBarry Smith    MatSNESMFRegisterDynamicchar *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESMF))
719a6cb015SBarry Smith 
729a6cb015SBarry Smith    Not Collective
739a6cb015SBarry Smith 
749a6cb015SBarry Smith    Input Parameters:
759a6cb015SBarry Smith +  name_solver - name of a new user-defined compute-h module
769a6cb015SBarry Smith .  path - path (either absolute or relative) the library containing this solver
779a6cb015SBarry Smith .  name_create - name of routine to create method context
789a6cb015SBarry Smith -  routine_create - routine to create method context
799a6cb015SBarry Smith 
8015091d37SBarry Smith    Level: developer
8115091d37SBarry Smith 
829a6cb015SBarry Smith    Notes:
83f1af5d2fSBarry Smith    MatSNESMFRegisterDynamic) may be called multiple times to add several user-defined solvers.
849a6cb015SBarry Smith 
859a6cb015SBarry Smith    If dynamic libraries are used, then the fourth input argument (routine_create)
869a6cb015SBarry Smith    is ignored.
879a6cb015SBarry Smith 
889a6cb015SBarry Smith    Sample usage:
899a6cb015SBarry Smith .vb
90f1af5d2fSBarry Smith    MatSNESMFRegisterDynamic"my_h",/home/username/my_lib/lib/libO/solaris/mylib.a,
919a6cb015SBarry Smith                "MyHCreate",MyHCreate);
929a6cb015SBarry Smith .ve
939a6cb015SBarry Smith 
949a6cb015SBarry Smith    Then, your solver can be chosen with the procedural interface via
955a655dc6SBarry Smith $     MatSNESMFSetType(mfctx,"my_h")
969a6cb015SBarry Smith    or at runtime via the option
979a6cb015SBarry Smith $     -snes_mf_type my_h
989a6cb015SBarry Smith 
995a655dc6SBarry Smith .keywords: MatSNESMF, register
1009a6cb015SBarry Smith 
1015a655dc6SBarry Smith .seealso: MatSNESMFRegisterAll(), MatSNESMFRegisterDestroy()
1029a6cb015SBarry Smith M*/
1039a6cb015SBarry Smith 
1049a6cb015SBarry Smith #undef __FUNC__
105f1af5d2fSBarry Smith #define __FUNC__ "MatSNESMFRegister"
106f1af5d2fSBarry Smith int MatSNESMFRegister(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx))
1079a6cb015SBarry Smith {
1089a6cb015SBarry Smith   int ierr;
1099a6cb015SBarry Smith   char fullname[256];
1109a6cb015SBarry Smith 
1119a6cb015SBarry Smith   PetscFunctionBegin;
112f1af5d2fSBarry Smith   ierr = FListConcat(path,name,fullname);CHKERRQ(ierr);
113f1af5d2fSBarry Smith   ierr = FListAdd(&MatSNESMFList,sname,fullname,(int (*)(void*))function);CHKERRQ(ierr);
1149a6cb015SBarry Smith   PetscFunctionReturn(0);
1159a6cb015SBarry Smith }
1169a6cb015SBarry Smith 
1179a6cb015SBarry Smith 
1189a6cb015SBarry Smith #undef __FUNC__
1195a655dc6SBarry Smith #define __FUNC__ "MatSNESMFRegisterDestroy"
1209a6cb015SBarry Smith /*@C
1215a655dc6SBarry Smith    MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were
122f1af5d2fSBarry Smith    registered by MatSNESMFRegisterDynamic).
1239a6cb015SBarry Smith 
1249a6cb015SBarry Smith    Not Collective
1259a6cb015SBarry Smith 
12615091d37SBarry Smith    Level: developer
12715091d37SBarry Smith 
1285a655dc6SBarry Smith .keywords: MatSNESMF, register, destroy
1299a6cb015SBarry Smith 
130f1af5d2fSBarry Smith .seealso: MatSNESMFRegisterDynamic), MatSNESMFRegisterAll()
1319a6cb015SBarry Smith @*/
1325a655dc6SBarry Smith int MatSNESMFRegisterDestroy(void)
1339a6cb015SBarry Smith {
1349a6cb015SBarry Smith   int ierr;
1359a6cb015SBarry Smith 
1369a6cb015SBarry Smith   PetscFunctionBegin;
1375a655dc6SBarry Smith   if (MatSNESMFList) {
1385a655dc6SBarry Smith     ierr = FListDestroy(MatSNESMFList);CHKERRQ(ierr);
1395a655dc6SBarry Smith     MatSNESMFList = 0;
1409a6cb015SBarry Smith   }
1414c49b128SBarry Smith   MatSNESMFRegisterAllCalled = PETSC_FALSE;
1429a6cb015SBarry Smith   PetscFunctionReturn(0);
1439a6cb015SBarry Smith }
1449a6cb015SBarry Smith 
1459a6cb015SBarry Smith /* ----------------------------------------------------------------------------------------*/
146a4d4d686SBarry Smith #undef __FUNC__
1475a655dc6SBarry Smith #define __FUNC__ "MatSNESMFDestroy_Private"
1485a655dc6SBarry Smith int MatSNESMFDestroy_Private(Mat mat)
149a4d4d686SBarry Smith {
150a4d4d686SBarry Smith   int          ierr;
1515a655dc6SBarry Smith   MatSNESMFCtx ctx;
152fae171e0SBarry Smith 
1533a40ed3dSBarry Smith   PetscFunctionBegin;
1540a25c783SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
155b9fa9cd0SBarry Smith   ierr = VecDestroy(ctx->w);CHKERRQ(ierr);
1569a6cb015SBarry Smith   if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);}
157b4fd4287SBarry Smith   if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);}
1586831982aSBarry Smith   PetscHeaderDestroy(ctx);
1593a40ed3dSBarry Smith   PetscFunctionReturn(0);
160b9fa9cd0SBarry Smith }
16150361f65SLois Curfman McInnes 
1625615d1e5SSatish Balay #undef __FUNC__
1635a655dc6SBarry Smith #define __FUNC__ "MatSNESMFView_Private"
16439e2f89bSBarry Smith /*
1655a655dc6SBarry Smith    MatSNESMFView_Private - Views matrix-free parameters.
1668f6e3e37SBarry Smith 
16739e2f89bSBarry Smith */
1685a655dc6SBarry Smith int MatSNESMFView_Private(Mat J,Viewer viewer)
169eb9086c3SLois Curfman McInnes {
170eb9086c3SLois Curfman McInnes   int          ierr;
1715a655dc6SBarry Smith   MatSNESMFCtx ctx;
1726831982aSBarry Smith   PetscTruth   isascii;
173eb9086c3SLois Curfman McInnes 
1743a40ed3dSBarry Smith   PetscFunctionBegin;
175eb9086c3SLois Curfman McInnes   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
1766831982aSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,ASCII_VIEWER,&isascii);CHKERRQ(ierr);
1770f5bd95cSBarry Smith   if (isascii) {
1786831982aSBarry Smith      ierr = ViewerASCIIPrintf(viewer,"  SNES matrix-free approximation:\n");CHKERRQ(ierr);
1796831982aSBarry Smith      ierr = ViewerASCIIPrintf(viewer,"    err=%g (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr);
1806831982aSBarry Smith      ierr = ViewerASCIIPrintf(viewer,"    Using %s compute h routine\n",ctx->type_name);CHKERRQ(ierr);
1819a6cb015SBarry Smith      if (ctx->ops->view) {
1829a6cb015SBarry Smith        ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr);
1839a6cb015SBarry Smith      }
1845cd90555SBarry Smith   } else {
1850f5bd95cSBarry Smith     SETERRQ1(1,1,"Viewer type %s not supported for SNES matrix free matrix",((PetscObject)viewer)->type_name);
186eb9086c3SLois Curfman McInnes   }
1873a40ed3dSBarry Smith   PetscFunctionReturn(0);
188eb9086c3SLois Curfman McInnes }
189eb9086c3SLois Curfman McInnes 
190be726c96SBarry Smith #undef __FUNC__
1915a655dc6SBarry Smith #define __FUNC__ "MatSNESMFAssemblyEnd_Private"
192be726c96SBarry Smith /*
1935a655dc6SBarry Smith    MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This
19465f2ba5bSLois Curfman McInnes    allows the user to indicate the beginning of a new linear solve by calling
195be726c96SBarry Smith    MatAssemblyXXX() on the matrix free matrix. This then allows the
19665f2ba5bSLois Curfman McInnes    MatSNESMFCreate_WP() to properly compute ||U|| only the first time
19765f2ba5bSLois Curfman McInnes    in the linear solver rather than every time.
198be726c96SBarry Smith */
1995a655dc6SBarry Smith int MatSNESMFAssemblyEnd_Private(Mat J)
200be726c96SBarry Smith {
201be726c96SBarry Smith   int            ierr;
202be726c96SBarry Smith 
203be726c96SBarry Smith   PetscFunctionBegin;
2045a655dc6SBarry Smith   ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr);
205be726c96SBarry Smith   PetscFunctionReturn(0);
206be726c96SBarry Smith }
207be726c96SBarry Smith 
208c481317fSBarry Smith 
2095615d1e5SSatish Balay #undef __FUNC__
2105a655dc6SBarry Smith #define __FUNC__ "MatSNESMFMult_Private"
211eb9086c3SLois Curfman McInnes /*
2125a655dc6SBarry Smith   MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector
213eb9086c3SLois Curfman McInnes   product, y = F'(u)*a:
214a4d4d686SBarry Smith 
2159a6cb015SBarry Smith         y ~= (F(u + ha) - F(u))/h,
216eb9086c3SLois Curfman McInnes   where F = nonlinear function, as set by SNESSetFunction()
217eb9086c3SLois Curfman McInnes         u = current iterate
218eb9086c3SLois Curfman McInnes         h = difference interval
219eb9086c3SLois Curfman McInnes */
2205a655dc6SBarry Smith int MatSNESMFMult_Private(Mat mat,Vec a,Vec y)
22139e2f89bSBarry Smith {
2225a655dc6SBarry Smith   MatSNESMFCtx ctx;
223fae171e0SBarry Smith   SNES           snes;
224a4d4d686SBarry Smith   Scalar         h,mone = -1.0;
225fae171e0SBarry Smith   Vec            w,U,F;
226a305c92eSSatish Balay   int            ierr,(*eval_fct)(SNES,Vec,Vec)=0;
22739e2f89bSBarry Smith 
2283a40ed3dSBarry Smith   PetscFunctionBegin;
2299a6cb015SBarry Smith   /* We log matrix-free matrix-vector products separately, so that we can
2309a6cb015SBarry Smith      separate the performance monitoring from the cases that use conventional
2319a6cb015SBarry Smith      storage.  We may eventually modify event logging to associate events
2329a6cb015SBarry Smith      with particular objects, hence alleviating the more general problem. */
23356cd22aeSBarry Smith   PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);
23456cd22aeSBarry Smith 
2356e38a044SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
236fae171e0SBarry Smith   snes = ctx->snes;
237fae171e0SBarry Smith   w    = ctx->w;
23878b31e54SBarry Smith   ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr);
23950361f65SLois Curfman McInnes 
24085614651SBarry Smith   /*
24185614651SBarry Smith       Compute differencing parameter
24285614651SBarry Smith   */
2439a6cb015SBarry Smith   if (!ctx->ops->compute) {
244*b7fd4e64SBarry Smith     ierr = MatSNESMFSetType(mat,MATSNESMF_DEFAULT);CHKERRQ(ierr);
2455a655dc6SBarry Smith     ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr);
2469a6cb015SBarry Smith   }
2479a6cb015SBarry Smith   ierr = (*ctx->ops->compute)(ctx,U,a,&h);CHKERRQ(ierr);
248a4d4d686SBarry Smith 
249a4d4d686SBarry Smith   /* keep a record of the current differencing parameter h */
250a4d4d686SBarry Smith   ctx->currenth = h;
251aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
252329f5518SBarry Smith   PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscRealPart(h),PetscImaginaryPart(h));
253a4d4d686SBarry Smith #else
254a4d4d686SBarry Smith   PLogInfo(mat,"Current differencing parameter: %g\n",h);
255a4d4d686SBarry Smith #endif
256a4d4d686SBarry Smith   if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) {
25785614651SBarry Smith     ctx->historyh[ctx->ncurrenth] = h;
258a4d4d686SBarry Smith   }
25985614651SBarry Smith   ctx->ncurrenth++;
260a4d4d686SBarry Smith 
26185614651SBarry Smith   /* w = u + ha */
262a4d4d686SBarry Smith   ierr = VecWAXPY(&h,a,U,w);CHKERRQ(ierr);
26385614651SBarry Smith 
26485614651SBarry Smith 
26585614651SBarry Smith   if (!ctx->func) {
26685614651SBarry Smith     if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
26785614651SBarry Smith       eval_fct = SNESComputeFunction;
268184914b5SBarry Smith       ierr     = SNESGetFunction(snes,&F,PETSC_NULL);CHKERRQ(ierr);
26985614651SBarry Smith     } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
27085614651SBarry Smith       eval_fct = SNESComputeGradient;
271184914b5SBarry Smith       ierr     = SNESGetGradient(snes,&F,PETSC_NULL);CHKERRQ(ierr);
27285614651SBarry Smith     } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class");
273a4d4d686SBarry Smith     ierr = eval_fct(snes,w,y);CHKERRQ(ierr);
27485614651SBarry Smith   } else {
27585614651SBarry Smith     F = ctx->funcvec;
27685614651SBarry Smith     /* compute func(U) as base for differencing */
27785614651SBarry Smith     if (ctx->ncurrenth == 1) {
27885614651SBarry Smith       ierr = (*ctx->func)(snes,U,F,ctx->funcctx);CHKERRQ(ierr);
27985614651SBarry Smith     }
28085614651SBarry Smith     ierr = (*ctx->func)(snes,w,y,ctx->funcctx);CHKERRQ(ierr);
28185614651SBarry Smith   }
282a4d4d686SBarry Smith 
283a4d4d686SBarry Smith   ierr = VecAXPY(&mone,F,y);CHKERRQ(ierr);
284a4d4d686SBarry Smith   h    = 1.0/h;
285a4d4d686SBarry Smith   ierr = VecScale(&h,y);CHKERRQ(ierr);
286a4d4d686SBarry Smith   if (ctx->sp) {ierr = PCNullSpaceRemove(ctx->sp,y);CHKERRQ(ierr);}
287a4d4d686SBarry Smith 
288a4d4d686SBarry Smith   PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);
289a4d4d686SBarry Smith   PetscFunctionReturn(0);
290a4d4d686SBarry Smith }
291a4d4d686SBarry Smith 
292a4d4d686SBarry Smith #undef __FUNC__
2935a655dc6SBarry Smith #define __FUNC__ "MatCreateSNESMF"
294a4d4d686SBarry Smith /*@C
29565f2ba5bSLois Curfman McInnes    MatCreateSNESMF - Creates a matrix-free matrix context for use with
29665f2ba5bSLois Curfman McInnes    a SNES solver.  This matrix can be used as the Jacobian argument for
29765f2ba5bSLois Curfman McInnes    the routine SNESSetJacobian().
298a4d4d686SBarry Smith 
299a4d4d686SBarry Smith    Collective on SNES and Vec
300a4d4d686SBarry Smith 
301a4d4d686SBarry Smith    Input Parameters:
302a4d4d686SBarry Smith +  snes - the SNES context
303a4d4d686SBarry Smith -  x - vector where SNES solution is to be stored.
304a4d4d686SBarry Smith 
305a4d4d686SBarry Smith    Output Parameter:
306a4d4d686SBarry Smith .  J - the matrix-free matrix
307a4d4d686SBarry Smith 
30815091d37SBarry Smith    Level: advanced
30915091d37SBarry Smith 
310a4d4d686SBarry Smith    Notes:
311a4d4d686SBarry Smith    The matrix-free matrix context merely contains the function pointers
312a4d4d686SBarry Smith    and work space for performing finite difference approximations of
31365f2ba5bSLois Curfman McInnes    Jacobian-vector products, F'(u)*a,
3149a6cb015SBarry Smith 
3159a6cb015SBarry Smith    The default code uses the following approach to compute h
316a4d4d686SBarry Smith 
317a4d4d686SBarry Smith .vb
31865f2ba5bSLois Curfman McInnes      F'(u)*a = [F(u+h*a) - F(u)]/h where
319a4d4d686SBarry Smith      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
320a4d4d686SBarry Smith        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
321a4d4d686SBarry Smith  where
322a4d4d686SBarry Smith      error_rel = square root of relative error in function evaluation
323a4d4d686SBarry Smith      umin = minimum iterate parameter
324a4d4d686SBarry Smith .ve
325a4d4d686SBarry Smith 
3265a655dc6SBarry Smith    The user can set the error_rel via MatSNESMFSetFunctionError() and
32765f2ba5bSLois Curfman McInnes    umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter
32865f2ba5bSLois Curfman McInnes    of the users manual for details.
329a4d4d686SBarry Smith 
330a4d4d686SBarry Smith    The user should call MatDestroy() when finished with the matrix-free
331a4d4d686SBarry Smith    matrix context.
332a4d4d686SBarry Smith 
333a4d4d686SBarry Smith    Options Database Keys:
334a4d4d686SBarry Smith +  -snes_mf_err <error_rel> - Sets error_rel
3359a6cb015SBarry Smith .  -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only)
336a4d4d686SBarry Smith -  -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h
337a4d4d686SBarry Smith 
338a4d4d686SBarry Smith .keywords: SNES, default, matrix-free, create, matrix
339a4d4d686SBarry Smith 
3405a655dc6SBarry Smith .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin()
3415a655dc6SBarry Smith           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
342f1af5d2fSBarry Smith           MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic)
343a4d4d686SBarry Smith 
344a4d4d686SBarry Smith @*/
3455a655dc6SBarry Smith int MatCreateSNESMF(SNES snes,Vec x,Mat *J)
346a4d4d686SBarry Smith {
347a4d4d686SBarry Smith   MPI_Comm     comm;
3485a655dc6SBarry Smith   MatSNESMFCtx mfctx;
3499a6cb015SBarry Smith   int          n,nloc,ierr;
350a4d4d686SBarry Smith 
351a4d4d686SBarry Smith   PetscFunctionBegin;
3526831982aSBarry Smith   PetscHeaderCreate(mfctx,_p_MatSNESMFCtx,struct _MFOps,MATSNESMFCTX_COOKIE,0,"SNESMF",snes->comm,MatSNESMFDestroy_Private,MatSNESMFView_Private);
3536831982aSBarry Smith   PLogObjectCreate(mfctx);
354a4d4d686SBarry Smith   mfctx->sp              = 0;
355a4d4d686SBarry Smith   mfctx->snes            = snes;
356329f5518SBarry Smith   mfctx->error_rel       = 1.e-8; /* assumes PetscReal precision */
357329f5518SBarry Smith   mfctx->recomputeperiod = 1;
358329f5518SBarry Smith   mfctx->count           = 0;
359a4d4d686SBarry Smith   mfctx->currenth        = 0.0;
360a4d4d686SBarry Smith   mfctx->historyh        = PETSC_NULL;
361a4d4d686SBarry Smith   mfctx->ncurrenth       = 0;
362a4d4d686SBarry Smith   mfctx->maxcurrenth     = 0;
3636831982aSBarry Smith   mfctx->type_name       = 0;
364a4d4d686SBarry Smith 
3659a6cb015SBarry Smith   /*
3669a6cb015SBarry Smith      Create the empty data structure to contain compute-h routines.
3679a6cb015SBarry Smith      These will be filled in below from the command line options or
3685a655dc6SBarry Smith      a later call with MatSNESMFSetType() or if that is not called
3695a655dc6SBarry Smith      then it will default in the first use of MatSNESMFMult_private()
3709a6cb015SBarry Smith   */
3719a6cb015SBarry Smith   mfctx->ops->compute        = 0;
3729a6cb015SBarry Smith   mfctx->ops->destroy        = 0;
3739a6cb015SBarry Smith   mfctx->ops->view           = 0;
3749a6cb015SBarry Smith   mfctx->ops->printhelp      = 0;
3759a6cb015SBarry Smith   mfctx->ops->setfromoptions = 0;
3769a6cb015SBarry Smith   mfctx->hctx                = 0;
3779a6cb015SBarry Smith 
37885614651SBarry Smith   mfctx->func                = 0;
37985614651SBarry Smith   mfctx->funcctx             = 0;
38085614651SBarry Smith   mfctx->funcvec             = 0;
38185614651SBarry Smith 
382a4d4d686SBarry Smith   ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr);
383a4d4d686SBarry Smith   ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr);
384a4d4d686SBarry Smith   ierr = VecGetSize(x,&n);CHKERRQ(ierr);
385a4d4d686SBarry Smith   ierr = VecGetLocalSize(x,&nloc);CHKERRQ(ierr);
386ffa0fd9eSBarry Smith   ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr);
3875a655dc6SBarry Smith   ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr);
3885a655dc6SBarry Smith   ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr);
3895a655dc6SBarry Smith   ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr);
3905a655dc6SBarry Smith   ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr);
391a4d4d686SBarry Smith   PLogObjectParent(*J,mfctx->w);
392a4d4d686SBarry Smith   PLogObjectParent(snes,*J);
3939a6cb015SBarry Smith 
3949a6cb015SBarry Smith   mfctx->mat = *J;
3959a6cb015SBarry Smith 
3969a6cb015SBarry Smith 
3979a6cb015SBarry Smith   PetscFunctionReturn(0);
3989a6cb015SBarry Smith }
3999a6cb015SBarry Smith 
4009a6cb015SBarry Smith #undef __FUNC__
4015a655dc6SBarry Smith #define __FUNC__ "MatSNESMFSetFromOptions"
4029a6cb015SBarry Smith /*@
4035a655dc6SBarry Smith    MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line
4049a6cb015SBarry Smith    parameter.
4059a6cb015SBarry Smith 
4069a6cb015SBarry Smith    Collective on Mat
4079a6cb015SBarry Smith 
4089a6cb015SBarry Smith    Input Parameters:
4095a655dc6SBarry Smith .  mat - the matrix obtained with MatCreateSNESMF()
4105a655dc6SBarry Smith 
4115a655dc6SBarry Smith    Options Database Keys:
4125a655dc6SBarry Smith +  -snes_mf_type - <default,wp>
4135a655dc6SBarry Smith -  -snes_mf_err - square root of estimated relative error in function evaluation
414329f5518SBarry Smith -  -snes_mf_period - how often h is recomputed, defaults to 1, everytime
4159a6cb015SBarry Smith 
41615091d37SBarry Smith    Level: advanced
41715091d37SBarry Smith 
4189a6cb015SBarry Smith .keywords: SNES, matrix-free, parameters
4199a6cb015SBarry Smith 
4205a655dc6SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
4215a655dc6SBarry Smith           MatSNESMFResetHHistory(), MatSNESMFKSPMonitor()
4229a6cb015SBarry Smith @*/
4235a655dc6SBarry Smith int MatSNESMFSetFromOptions(Mat mat)
4249a6cb015SBarry Smith {
4255a655dc6SBarry Smith   MatSNESMFCtx mfctx;
426f1af5d2fSBarry Smith   int          ierr;
427f1af5d2fSBarry Smith   PetscTruth   flg;
4289a6cb015SBarry Smith   char         ftype[256],p[64];
4299a6cb015SBarry Smith 
4309a6cb015SBarry Smith   PetscFunctionBegin;
4319a6cb015SBarry Smith   ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr);
4329a6cb015SBarry Smith   if (mfctx) {
4339a6cb015SBarry Smith     /* allow user to set the type */
4349a6cb015SBarry Smith     ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr);
4359a6cb015SBarry Smith     if (flg) {
4365a655dc6SBarry Smith       ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr);
4379a6cb015SBarry Smith     }
4389a6cb015SBarry Smith 
439f1af5d2fSBarry Smith     ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,PETSC_NULL);CHKERRQ(ierr);
440329f5518SBarry Smith     ierr = OptionsGetInt(mfctx->snes->prefix,"-snes_mf_period",&mfctx->recomputeperiod,PETSC_NULL);CHKERRQ(ierr);
4419a6cb015SBarry Smith     if (mfctx->ops->setfromoptions) {
4429a6cb015SBarry Smith       ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr);
4439a6cb015SBarry Smith     }
4449a6cb015SBarry Smith 
4459a6cb015SBarry Smith     ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr);
446d132466eSBarry Smith     ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
447d132466eSBarry Smith     if (mfctx->snes->prefix) {ierr = PetscStrcat(p,mfctx->snes->prefix);CHKERRQ(ierr);}
4489a6cb015SBarry Smith     if (flg) {
449d132466eSBarry Smith       ierr = (*PetscHelpPrintf)(mfctx->snes->comm,"   %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);CHKERRQ(ierr);
450329f5518SBarry Smith       ierr = (*PetscHelpPrintf)(mfctx->snes->comm,"   %ssnes_mf_period <p>: how often h is recomputed (default 1, everytime)\n",p);CHKERRQ(ierr);
4519a6cb015SBarry Smith       if (mfctx->ops->printhelp) {
452d132466eSBarry Smith         ierr = (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr);
4539a6cb015SBarry Smith       }
4549a6cb015SBarry Smith     }
4559a6cb015SBarry Smith   }
456a4d4d686SBarry Smith   PetscFunctionReturn(0);
457a4d4d686SBarry Smith }
458a4d4d686SBarry Smith 
459a4d4d686SBarry Smith #undef __FUNC__
4605a655dc6SBarry Smith #define __FUNC__ "MatSNESMFGetH"
461a4d4d686SBarry Smith /*@
46265f2ba5bSLois Curfman McInnes    MatSNESMFGetH - Gets the last value that was used as the differencing
463a4d4d686SBarry Smith    parameter.
464a4d4d686SBarry Smith 
465a4d4d686SBarry Smith    Not Collective
466a4d4d686SBarry Smith 
467a4d4d686SBarry Smith    Input Parameters:
4685a655dc6SBarry Smith .  mat - the matrix obtained with MatCreateSNESMF()
469a4d4d686SBarry Smith 
470a4d4d686SBarry Smith    Output Paramter:
471a4d4d686SBarry Smith .  h - the differencing step size
472a4d4d686SBarry Smith 
47315091d37SBarry Smith    Level: advanced
47415091d37SBarry Smith 
475a4d4d686SBarry Smith .keywords: SNES, matrix-free, parameters
476a4d4d686SBarry Smith 
4775a655dc6SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(),
4785a655dc6SBarry Smith           MatSNESMFResetHHistory(),MatSNESMFKSPMonitor()
479a4d4d686SBarry Smith @*/
4805a655dc6SBarry Smith int MatSNESMFGetH(Mat mat,Scalar *h)
481a4d4d686SBarry Smith {
4825a655dc6SBarry Smith   MatSNESMFCtx ctx;
483a4d4d686SBarry Smith   int          ierr;
484a4d4d686SBarry Smith 
485a4d4d686SBarry Smith   PetscFunctionBegin;
486a4d4d686SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
487a4d4d686SBarry Smith   if (ctx) {
488a4d4d686SBarry Smith     *h = ctx->currenth;
489a4d4d686SBarry Smith   }
490a4d4d686SBarry Smith   PetscFunctionReturn(0);
491a4d4d686SBarry Smith }
492a4d4d686SBarry Smith 
493a4d4d686SBarry Smith #undef __FUNC__
4945a655dc6SBarry Smith #define __FUNC__ "MatSNESMFKSPMonitor"
495a4d4d686SBarry Smith /*
4965a655dc6SBarry Smith    MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc
49765f2ba5bSLois Curfman McInnes    SNES matrix free routines. Prints the differencing parameter used at
49865f2ba5bSLois Curfman McInnes    each step.
499a4d4d686SBarry Smith */
500329f5518SBarry Smith int MatSNESMFKSPMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
501a4d4d686SBarry Smith {
502a4d4d686SBarry Smith   PC             pc;
5035a655dc6SBarry Smith   MatSNESMFCtx   ctx;
504a4d4d686SBarry Smith   int            ierr;
505a4d4d686SBarry Smith   Mat            mat;
506a4d4d686SBarry Smith   MPI_Comm       comm;
507a4d4d686SBarry Smith   PetscTruth     nonzeroinitialguess;
508a4d4d686SBarry Smith 
509a4d4d686SBarry Smith   PetscFunctionBegin;
510a4d4d686SBarry Smith   ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr);
511a4d4d686SBarry Smith   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
512a4d4d686SBarry Smith   ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr);
513a4d4d686SBarry Smith   ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
514a4d4d686SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
5159a6cb015SBarry Smith   if (!ctx) {
5169a6cb015SBarry Smith     SETERRQ(1,1,"Matrix is not a matrix free shell matrix");
5179a6cb015SBarry Smith   }
518a4d4d686SBarry Smith   if (n > 0 || nonzeroinitialguess) {
519aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
520d132466eSBarry Smith     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm,
521329f5518SBarry Smith                 PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));CHKERRQ(ierr);
522a4d4d686SBarry Smith #else
523d132466eSBarry Smith     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr);
524a4d4d686SBarry Smith #endif
525a4d4d686SBarry Smith   } else {
526d132466eSBarry Smith     ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr);
527a4d4d686SBarry Smith   }
528a4d4d686SBarry Smith   PetscFunctionReturn(0);
529a4d4d686SBarry Smith }
530a4d4d686SBarry Smith 
531a4d4d686SBarry Smith #undef __FUNC__
53285614651SBarry Smith #define __FUNC__ "MatSNESMFSetFunction"
53385614651SBarry Smith /*@C
53485614651SBarry Smith    MatSNESMFSetFunction - Sets the function used in applying the matrix free.
53585614651SBarry Smith 
53685614651SBarry Smith    Collective on Mat
53785614651SBarry Smith 
53885614651SBarry Smith    Input Parameters:
53985614651SBarry Smith +  mat - the matrix free matrix created via MatCreateSNESMF()
54085614651SBarry Smith .  v   - workspace vector
54185614651SBarry Smith .  func - the function to use
54285614651SBarry Smith -  funcctx - optional function context passed to function
54385614651SBarry Smith 
54485614651SBarry Smith    Level: advanced
54585614651SBarry Smith 
54685614651SBarry Smith    Notes:
54785614651SBarry Smith     If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free
54885614651SBarry Smith     matrix inside your compute Jacobian routine
54985614651SBarry Smith 
55085614651SBarry Smith     If this is not set then it will use the function set with SNESSetFunction()
55185614651SBarry Smith 
55285614651SBarry Smith .keywords: SNES, matrix-free, function
55385614651SBarry Smith 
55485614651SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
55585614651SBarry Smith           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
55685614651SBarry Smith           MatSNESMFKSPMonitor(), SNESetFunction()
55785614651SBarry Smith @*/
55885614651SBarry Smith int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx)
55985614651SBarry Smith {
56085614651SBarry Smith   MatSNESMFCtx ctx;
56185614651SBarry Smith   int          ierr;
56285614651SBarry Smith 
56385614651SBarry Smith   PetscFunctionBegin;
56485614651SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
56585614651SBarry Smith   if (ctx) {
56685614651SBarry Smith     ctx->func    = func;
56785614651SBarry Smith     ctx->funcctx = funcctx;
56885614651SBarry Smith     ctx->funcvec = v;
56985614651SBarry Smith   }
57085614651SBarry Smith   PetscFunctionReturn(0);
57185614651SBarry Smith }
57285614651SBarry Smith 
57385614651SBarry Smith 
57485614651SBarry Smith #undef __FUNC__
575329f5518SBarry Smith #define __FUNC__ "MatSNESMFSetPeriod"
576329f5518SBarry Smith /*@
577329f5518SBarry Smith    MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime
578329f5518SBarry Smith 
579329f5518SBarry Smith    Collective on Mat
580329f5518SBarry Smith 
581329f5518SBarry Smith    Input Parameters:
582329f5518SBarry Smith +  mat - the matrix free matrix created via MatCreateSNESMF()
583329f5518SBarry Smith -  period - 1 for everytime, 2 for every second etc
584329f5518SBarry Smith 
585329f5518SBarry Smith    Options Database Keys:
586329f5518SBarry Smith +  -snes_mf_period <period>
587329f5518SBarry Smith 
588329f5518SBarry Smith    Level: advanced
589329f5518SBarry Smith 
590329f5518SBarry Smith 
591329f5518SBarry Smith .keywords: SNES, matrix-free, parameters
592329f5518SBarry Smith 
593329f5518SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
594329f5518SBarry Smith           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
595329f5518SBarry Smith           MatSNESMFKSPMonitor()
596329f5518SBarry Smith @*/
597329f5518SBarry Smith int MatSNESMFSetPeriod(Mat mat,int period)
598329f5518SBarry Smith {
599329f5518SBarry Smith   MatSNESMFCtx ctx;
600329f5518SBarry Smith   int          ierr;
601329f5518SBarry Smith 
602329f5518SBarry Smith   PetscFunctionBegin;
603329f5518SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
604329f5518SBarry Smith   if (ctx) {
605329f5518SBarry Smith     ctx->recomputeperiod = period;
606329f5518SBarry Smith   }
607329f5518SBarry Smith   PetscFunctionReturn(0);
608329f5518SBarry Smith }
609329f5518SBarry Smith 
610329f5518SBarry Smith #undef __FUNC__
6115a655dc6SBarry Smith #define __FUNC__ "MatSNESMFSetFunctionError"
612a4d4d686SBarry Smith /*@
6135a655dc6SBarry Smith    MatSNESMFSetFunctionError - Sets the error_rel for the approximation of
614a4d4d686SBarry Smith    matrix-vector products using finite differences.
615a4d4d686SBarry Smith 
616a4d4d686SBarry Smith    Collective on Mat
617a4d4d686SBarry Smith 
618a4d4d686SBarry Smith    Input Parameters:
6195a655dc6SBarry Smith +  mat - the matrix free matrix created via MatCreateSNESMF()
6209a6cb015SBarry Smith -  error_rel - relative error (should be set to the square root of
621a4d4d686SBarry Smith                the relative error in the function evaluations)
622a4d4d686SBarry Smith 
62315091d37SBarry Smith    Options Database Keys:
62415091d37SBarry Smith +  -snes_mf_err <error_rel> - Sets error_rel
62515091d37SBarry Smith 
62615091d37SBarry Smith    Level: advanced
62715091d37SBarry Smith 
628a4d4d686SBarry Smith    Notes:
629a4d4d686SBarry Smith    The default matrix-free matrix-vector product routine computes
630a4d4d686SBarry Smith .vb
63165f2ba5bSLois Curfman McInnes      F'(u)*a = [F(u+h*a) - F(u)]/h where
632a4d4d686SBarry Smith      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
633a4d4d686SBarry Smith        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   else
634a4d4d686SBarry Smith .ve
635a4d4d686SBarry Smith 
636a4d4d686SBarry Smith .keywords: SNES, matrix-free, parameters
637a4d4d686SBarry Smith 
6385a655dc6SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(),
6395a655dc6SBarry Smith           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
6405a655dc6SBarry Smith           MatSNESMFKSPMonitor()
641a4d4d686SBarry Smith @*/
642329f5518SBarry Smith int MatSNESMFSetFunctionError(Mat mat,PetscReal error)
643a4d4d686SBarry Smith {
6445a655dc6SBarry Smith   MatSNESMFCtx ctx;
645a4d4d686SBarry Smith   int          ierr;
646a4d4d686SBarry Smith 
647a4d4d686SBarry Smith   PetscFunctionBegin;
648a4d4d686SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
649a4d4d686SBarry Smith   if (ctx) {
650a4d4d686SBarry Smith     if (error != PETSC_DEFAULT) ctx->error_rel = error;
651a4d4d686SBarry Smith   }
652a4d4d686SBarry Smith   PetscFunctionReturn(0);
653a4d4d686SBarry Smith }
654a4d4d686SBarry Smith 
655a4d4d686SBarry Smith #undef __FUNC__
6565a655dc6SBarry Smith #define __FUNC__ "MatSNESMFAddNullSpace"
657a4d4d686SBarry Smith /*@
65865f2ba5bSLois Curfman McInnes    MatSNESMFAddNullSpace - Provides a null space that an operator is
65965f2ba5bSLois Curfman McInnes    supposed to have.  Since roundoff will create a small component in
66065f2ba5bSLois Curfman McInnes    the null space, if you know the null space you may have it
66165f2ba5bSLois Curfman McInnes    automatically removed.
662a4d4d686SBarry Smith 
663a4d4d686SBarry Smith    Collective on Mat
664a4d4d686SBarry Smith 
665a4d4d686SBarry Smith    Input Parameters:
666a4d4d686SBarry Smith +  J - the matrix-free matrix context
66785614651SBarry Smith -  nullsp - object created with PCNullSpaceCreate()
668a4d4d686SBarry Smith 
66915091d37SBarry Smith    Level: advanced
67015091d37SBarry Smith 
671a4d4d686SBarry Smith .keywords: SNES, matrix-free, null space
672a4d4d686SBarry Smith 
67353b79920SLois Curfman McInnes .seealso: PCNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(),
6745a655dc6SBarry Smith           MatSNESMFSetHHistory(), MatSNESMFResetHHistory(),
6755a655dc6SBarry Smith           MatSNESMFKSPMonitor(), MatSNESMFErrorRel()
676a4d4d686SBarry Smith @*/
67785614651SBarry Smith int MatSNESMFAddNullSpace(Mat J,PCNullSpace nullsp)
678a4d4d686SBarry Smith {
679a4d4d686SBarry Smith   int          ierr;
6805a655dc6SBarry Smith   MatSNESMFCtx ctx;
681a4d4d686SBarry Smith   MPI_Comm     comm;
682a4d4d686SBarry Smith 
683a4d4d686SBarry Smith   PetscFunctionBegin;
6842d0c0e3bSBarry Smith   ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr);
685a4d4d686SBarry Smith 
686a4d4d686SBarry Smith   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
687a4d4d686SBarry Smith   /* no context indicates that it is not the "matrix free" matrix type */
688a4d4d686SBarry Smith   if (!ctx) PetscFunctionReturn(0);
68985614651SBarry Smith   ctx->sp = nullsp;
69085614651SBarry Smith   ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr);
691a4d4d686SBarry Smith   PetscFunctionReturn(0);
692a4d4d686SBarry Smith }
693a4d4d686SBarry Smith 
694a4d4d686SBarry Smith #undef __FUNC__
6955a655dc6SBarry Smith #define __FUNC__ "MatSNESMFSetHHistory"
696a4d4d686SBarry Smith /*@
69765f2ba5bSLois Curfman McInnes    MatSNESMFSetHHistory - Sets an array to collect a history of the
69865f2ba5bSLois Curfman McInnes    differencing values (h) computed for the matrix-free product.
699a4d4d686SBarry Smith 
700a4d4d686SBarry Smith    Collective on Mat
701a4d4d686SBarry Smith 
702a4d4d686SBarry Smith    Input Parameters:
703a4d4d686SBarry Smith +  J - the matrix-free matrix context
70465f2ba5bSLois Curfman McInnes .  histroy - space to hold the history
70565f2ba5bSLois Curfman McInnes -  nhistory - number of entries in history, if more entries are generated than
70665f2ba5bSLois Curfman McInnes               nhistory, then the later ones are discarded
707a4d4d686SBarry Smith 
70815091d37SBarry Smith    Level: advanced
70915091d37SBarry Smith 
710a4d4d686SBarry Smith    Notes:
71165f2ba5bSLois Curfman McInnes    Use MatSNESMFResetHHistory() to reset the history counter and collect
71265f2ba5bSLois Curfman McInnes    a new batch of differencing parameters, h.
713a4d4d686SBarry Smith 
714a4d4d686SBarry Smith .keywords: SNES, matrix-free, h history, differencing history
715a4d4d686SBarry Smith 
7165a655dc6SBarry Smith .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
7175a655dc6SBarry Smith           MatSNESMFResetHHistory(),
7185a655dc6SBarry Smith           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
719a4d4d686SBarry Smith 
720a4d4d686SBarry Smith @*/
7215a655dc6SBarry Smith int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory)
722a4d4d686SBarry Smith {
723a4d4d686SBarry Smith   int          ierr;
7245a655dc6SBarry Smith   MatSNESMFCtx ctx;
725a4d4d686SBarry Smith 
726a4d4d686SBarry Smith   PetscFunctionBegin;
727a4d4d686SBarry Smith 
728a4d4d686SBarry Smith   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
729a4d4d686SBarry Smith   /* no context indicates that it is not the "matrix free" matrix type */
730a4d4d686SBarry Smith   if (!ctx) PetscFunctionReturn(0);
731a4d4d686SBarry Smith   ctx->historyh    = history;
732a4d4d686SBarry Smith   ctx->maxcurrenth = nhistory;
733a4d4d686SBarry Smith   ctx->currenth    = 0;
734a4d4d686SBarry Smith 
735a4d4d686SBarry Smith   PetscFunctionReturn(0);
736a4d4d686SBarry Smith }
737a4d4d686SBarry Smith 
738a4d4d686SBarry Smith #undef __FUNC__
7395a655dc6SBarry Smith #define __FUNC__ "MatSNESMFResetHHistory"
740a4d4d686SBarry Smith /*@
7415a655dc6SBarry Smith    MatSNESMFResetHHistory - Resets the counter to zero to begin
742a4d4d686SBarry Smith    collecting a new set of differencing histories.
743a4d4d686SBarry Smith 
744a4d4d686SBarry Smith    Collective on Mat
745a4d4d686SBarry Smith 
746a4d4d686SBarry Smith    Input Parameters:
747a4d4d686SBarry Smith .  J - the matrix-free matrix context
748a4d4d686SBarry Smith 
74915091d37SBarry Smith    Level: advanced
75015091d37SBarry Smith 
751a4d4d686SBarry Smith    Notes:
75265f2ba5bSLois Curfman McInnes    Use MatSNESMFSetHHistory() to create the original history counter.
753a4d4d686SBarry Smith 
754a4d4d686SBarry Smith .keywords: SNES, matrix-free, h history, differencing history
755a4d4d686SBarry Smith 
7565a655dc6SBarry Smith .seealso: MatSNESMFGetH(), MatCreateSNESMF(),
7575a655dc6SBarry Smith           MatSNESMFSetHHistory(),
7585a655dc6SBarry Smith           MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError()
759a4d4d686SBarry Smith 
760a4d4d686SBarry Smith @*/
7615a655dc6SBarry Smith int MatSNESMFResetHHistory(Mat J)
762a4d4d686SBarry Smith {
763a4d4d686SBarry Smith   int          ierr;
7645a655dc6SBarry Smith   MatSNESMFCtx ctx;
765a4d4d686SBarry Smith 
766a4d4d686SBarry Smith   PetscFunctionBegin;
767a4d4d686SBarry Smith 
768a4d4d686SBarry Smith   ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr);
769a4d4d686SBarry Smith   /* no context indicates that it is not the "matrix free" matrix type */
770a4d4d686SBarry Smith   if (!ctx) PetscFunctionReturn(0);
771be726c96SBarry Smith   ctx->ncurrenth    = 0;
772a4d4d686SBarry Smith 
773a4d4d686SBarry Smith   PetscFunctionReturn(0);
774a4d4d686SBarry Smith }
775a4d4d686SBarry Smith 
776