xref: /petsc/src/snes/mf/snesmfj.c (revision 8f6e3e372e6ee449ab18d8c1c992d4d989996686)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*8f6e3e37SBarry Smith static char vcid[] = "$Id: snesmfj.c,v 1.67 1998/07/08 21:24:28 bsmith Exp bsmith $";
381e6777dSBarry Smith #endif
481e6777dSBarry Smith 
570f55243SBarry Smith #include "src/snes/snesimpl.h"   /*I  "snes.h"   I*/
6eb9086c3SLois Curfman McInnes #include "pinclude/pviewer.h"
7c481317fSBarry Smith #include <math.h>
881e6777dSBarry Smith 
950361f65SLois Curfman McInnes typedef struct {  /* default context for matrix-free SNES */
10eb9086c3SLois Curfman McInnes   SNES        snes;      /* SNES context */
11eb9086c3SLois Curfman McInnes   Vec         w;         /* work vector */
12eb9086c3SLois Curfman McInnes   PCNullSpace sp;        /* null space context */
13eb9086c3SLois Curfman McInnes   double      error_rel; /* square root of relative error in computing function */
14639f9d9dSBarry Smith   double      umin;      /* minimum allowable u'a value relative to |u|_1 */
15*8f6e3e37SBarry Smith   double      currenth;  /* last differencing parameter used */
1639e2f89bSBarry Smith } MFCtx_Private;
1739e2f89bSBarry Smith 
185615d1e5SSatish Balay #undef __FUNC__
19d4bb536fSBarry Smith #define __FUNC__ "SNESMatrixFreeDestroy_Private"
20e1311b90SBarry Smith int SNESMatrixFreeDestroy_Private(Mat mat)
21b9fa9cd0SBarry Smith {
22b9fa9cd0SBarry Smith   int           ierr;
23fae171e0SBarry Smith   MFCtx_Private *ctx;
24fae171e0SBarry Smith 
253a40ed3dSBarry Smith   PetscFunctionBegin;
260a25c783SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr);
27b9fa9cd0SBarry Smith   ierr = VecDestroy(ctx->w); CHKERRQ(ierr);
28b4fd4287SBarry Smith   if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);}
29fae171e0SBarry Smith   PetscFree(ctx);
303a40ed3dSBarry Smith   PetscFunctionReturn(0);
31b9fa9cd0SBarry Smith }
3250361f65SLois Curfman McInnes 
335615d1e5SSatish Balay #undef __FUNC__
34d4bb536fSBarry Smith #define __FUNC__ "SNESMatrixFreeView_Private"
3539e2f89bSBarry Smith /*
361d1bbde2SLois Curfman McInnes    SNESMatrixFreeView_Private - Views matrix-free parameters.
37*8f6e3e37SBarry Smith 
3839e2f89bSBarry Smith */
39eb9086c3SLois Curfman McInnes int SNESMatrixFreeView_Private(Mat J,Viewer viewer)
40eb9086c3SLois Curfman McInnes {
41eb9086c3SLois Curfman McInnes   int           ierr;
42eb9086c3SLois Curfman McInnes   MFCtx_Private *ctx;
43eb9086c3SLois Curfman McInnes   MPI_Comm      comm;
44eb9086c3SLois Curfman McInnes   FILE          *fd;
45eb9086c3SLois Curfman McInnes   ViewerType    vtype;
46eb9086c3SLois Curfman McInnes 
473a40ed3dSBarry Smith   PetscFunctionBegin;
48eb9086c3SLois Curfman McInnes   PetscObjectGetComm((PetscObject)J,&comm);
49eb9086c3SLois Curfman McInnes   ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr);
50eb9086c3SLois Curfman McInnes   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
51eb9086c3SLois Curfman McInnes   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
52eb9086c3SLois Curfman McInnes   if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
53eb9086c3SLois Curfman McInnes      PetscFPrintf(comm,fd,"  SNES matrix-free approximation:\n");
54eb9086c3SLois Curfman McInnes      PetscFPrintf(comm,fd,"    err=%g (relative error in function evaluation)\n",ctx->error_rel);
55eb9086c3SLois Curfman McInnes      PetscFPrintf(comm,fd,"    umin=%g (minimum iterate parameter)\n",ctx->umin);
565cd90555SBarry Smith   } else {
575cd90555SBarry Smith     SETERRQ(1,1,"Viewer type not supported for this object");
58eb9086c3SLois Curfman McInnes   }
593a40ed3dSBarry Smith   PetscFunctionReturn(0);
60eb9086c3SLois Curfman McInnes }
61eb9086c3SLois Curfman McInnes 
62e9cf3c21SBarry Smith extern int VecDot_Seq(Vec,Vec,Scalar *);
63c481317fSBarry Smith extern int VecNorm_Seq(Vec,NormType,double *);
64c481317fSBarry Smith 
655615d1e5SSatish Balay #undef __FUNC__
665615d1e5SSatish Balay #define __FUNC__ "SNESMatrixFreeMult_Private"
67eb9086c3SLois Curfman McInnes /*
68eb9086c3SLois Curfman McInnes   SNESMatrixFreeMult_Private - Default matrix-free form for Jacobian-vector
69eb9086c3SLois Curfman McInnes   product, y = F'(u)*a:
70eb9086c3SLois Curfman McInnes         y = ( F(u + ha) - F(u) ) /h,
71eb9086c3SLois Curfman McInnes   where F = nonlinear function, as set by SNESSetFunction()
72eb9086c3SLois Curfman McInnes         u = current iterate
73eb9086c3SLois Curfman McInnes         h = difference interval
74eb9086c3SLois Curfman McInnes */
75eb9086c3SLois Curfman McInnes int SNESMatrixFreeMult_Private(Mat mat,Vec a,Vec y)
7639e2f89bSBarry Smith {
77fae171e0SBarry Smith   MFCtx_Private *ctx;
78fae171e0SBarry Smith   SNES          snes;
79c31ba22aSSatish Balay   double        ovalues[3],norm, sum, umin;
805334005bSBarry Smith   Scalar        h, dot, mone = -1.0;
81fae171e0SBarry Smith   Vec           w,U,F;
8283e56afdSLois Curfman McInnes   int           ierr, (*eval_fct)(SNES,Vec,Vec);
83c481317fSBarry Smith   MPI_Comm      comm;
84c31ba22aSSatish Balay #if !defined(USE_PETSC_COMPLEX)
85c31ba22aSSatish Balay   double        values[3];
86c31ba22aSSatish Balay #endif
8739e2f89bSBarry Smith 
883a40ed3dSBarry Smith   PetscFunctionBegin;
8956cd22aeSBarry Smith   PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);
9056cd22aeSBarry Smith 
91c481317fSBarry Smith   PetscObjectGetComm((PetscObject)mat,&comm);
926e38a044SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr);
93fae171e0SBarry Smith   snes = ctx->snes;
94fae171e0SBarry Smith   w    = ctx->w;
95eb9086c3SLois Curfman McInnes   umin = ctx->umin;
96fae171e0SBarry Smith 
9757c37382SLois Curfman McInnes   /* We log matrix-free matrix-vector products separately, so that we can
9857c37382SLois Curfman McInnes      separate the performance monitoring from the cases that use conventional
9957c37382SLois Curfman McInnes      storage.  We may eventually modify event logging to associate events
10057c37382SLois Curfman McInnes      with particular objects, hence alleviating the more general problem. */
10157c37382SLois Curfman McInnes 
10278b31e54SBarry Smith   ierr = SNESGetSolution(snes,&U); CHKERRQ(ierr);
10383e56afdSLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
10483e56afdSLois Curfman McInnes     eval_fct = SNESComputeFunction;
10578b31e54SBarry Smith     ierr = SNESGetFunction(snes,&F); CHKERRQ(ierr);
10683e56afdSLois Curfman McInnes   }
10783e56afdSLois Curfman McInnes   else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
10883e56afdSLois Curfman McInnes     eval_fct = SNESComputeGradient;
10983e56afdSLois Curfman McInnes     ierr = SNESGetGradient(snes,&F); CHKERRQ(ierr);
11083e56afdSLois Curfman McInnes   }
111a8c6a408SBarry Smith   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class");
11250361f65SLois Curfman McInnes 
113eb9086c3SLois Curfman McInnes   /* Determine a "good" step size, h */
114c481317fSBarry Smith 
115c481317fSBarry Smith   /*
116eb9086c3SLois Curfman McInnes     ierr = VecDot(U,a,&dot); CHKERRQ(ierr);
117eb9086c3SLois Curfman McInnes     ierr = VecNorm(a,NORM_1,&sum); CHKERRQ(ierr);
118eb9086c3SLois Curfman McInnes     ierr = VecNorm(a,NORM_2,&norm); CHKERRQ(ierr);
119c481317fSBarry Smith   */
120c481317fSBarry Smith 
121c481317fSBarry Smith   /*
12286f5173aSBarry Smith      Call the Seq Vector routines and then do a single reduction
12386f5173aSBarry Smith      to reduce the number of communications required
124c481317fSBarry Smith   */
125c481317fSBarry Smith 
1263a40ed3dSBarry Smith #if !defined(USE_PETSC_COMPLEX)
127c481317fSBarry Smith   PLogEventBegin(VEC_Dot,U,a,0,0);
128c481317fSBarry Smith   ierr = VecDot_Seq(U,a,ovalues); CHKERRQ(ierr);
129c481317fSBarry Smith   PLogEventEnd(VEC_Dot,U,a,0,0);
130c481317fSBarry Smith   PLogEventBegin(VEC_Norm,a,0,0,0);
131c481317fSBarry Smith   ierr = VecNorm_Seq(a,NORM_1,ovalues+1); CHKERRQ(ierr);
132c481317fSBarry Smith   ierr = VecNorm_Seq(a,NORM_2,ovalues+2); CHKERRQ(ierr);
133c481317fSBarry Smith   ovalues[2] = ovalues[2]*ovalues[2];
134005c665bSBarry Smith   PLogEventBarrierBegin(VEC_NormBarrier,0,0,0,0,comm);
135ca161407SBarry Smith   ierr = MPI_Allreduce(ovalues,values,3,MPI_DOUBLE,MPI_SUM,comm );CHKERRQ(ierr);
136005c665bSBarry Smith   PLogEventBarrierEnd(VEC_NormBarrier,0,0,0,0,comm);
137c481317fSBarry Smith   dot = values[0]; sum = values[1]; norm = sqrt(values[2]);
138c481317fSBarry Smith   PLogEventEnd(VEC_Norm,a,0,0,0);
13986f5173aSBarry Smith #else
14086f5173aSBarry Smith   {
14186f5173aSBarry Smith     Scalar cvalues[3],covalues[3];
14286f5173aSBarry Smith 
14386f5173aSBarry Smith     PLogEventBegin(VEC_Dot,U,a,0,0);
14486f5173aSBarry Smith     ierr = VecDot_Seq(U,a,covalues); CHKERRQ(ierr);
14586f5173aSBarry Smith     PLogEventEnd(VEC_Dot,U,a,0,0);
14686f5173aSBarry Smith     PLogEventBegin(VEC_Norm,a,0,0,0);
14786f5173aSBarry Smith     ierr = VecNorm_Seq(a,NORM_1,ovalues+1); CHKERRQ(ierr);
14886f5173aSBarry Smith     ierr = VecNorm_Seq(a,NORM_2,ovalues+2); CHKERRQ(ierr);
14986f5173aSBarry Smith     covalues[1] = ovalues[1];
15086f5173aSBarry Smith     covalues[2] = ovalues[2]*ovalues[2];
151005c665bSBarry Smith     PLogEventBarrierBegin(VEC_NormBarrier,0,0,0,0,comm);
152ca161407SBarry Smith     ierr = MPI_Allreduce(covalues,cvalues,6,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr);
153005c665bSBarry Smith     PLogEventBarrierBegin(VEC_NormBarrier,0,0,0,0,comm);
15486f5173aSBarry Smith     dot = cvalues[0]; sum = PetscReal(cvalues[1]); norm = sqrt(PetscReal(cvalues[2]));
15586f5173aSBarry Smith     PLogEventEnd(VEC_Norm,a,0,0,0);
15686f5173aSBarry Smith   }
15786f5173aSBarry Smith #endif
158c481317fSBarry Smith 
159eb9086c3SLois Curfman McInnes 
160eb9086c3SLois Curfman McInnes   /* Safeguard for step sizes too small */
161edd2f0e1SBarry Smith   if (sum == 0.0) {dot = 1.0; norm = 1.0;}
1623a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
163e20fef11SSatish Balay   else if (PetscAbsScalar(dot) < umin*sum && PetscReal(dot) >= 0.0) dot = umin*sum;
164e20fef11SSatish Balay   else if (PetscAbsScalar(dot) < 0.0 && PetscReal(dot) > -umin*sum) dot = -umin*sum;
16519a167f6SBarry Smith #else
166eb9086c3SLois Curfman McInnes   else if (dot < umin*sum && dot >= 0.0) dot = umin*sum;
167eb9086c3SLois Curfman McInnes   else if (dot < 0.0 && dot > -umin*sum) dot = -umin*sum;
16819a167f6SBarry Smith #endif
169eb9086c3SLois Curfman McInnes   h = ctx->error_rel*dot/(norm*norm);
17039e2f89bSBarry Smith 
171*8f6e3e37SBarry Smith   /* keep a record of the current differencing parameter h */
172*8f6e3e37SBarry Smith   ctx->currenth = h;
173*8f6e3e37SBarry Smith   PLogInfo(mat,"Current differencing parameter: %g\n",h);
174*8f6e3e37SBarry Smith 
175eb9086c3SLois Curfman McInnes   /* Evaluate function at F(u + ha) */
176eb9086c3SLois Curfman McInnes   ierr = VecWAXPY(&h,a,U,w); CHKERRQ(ierr);
17783e56afdSLois Curfman McInnes   ierr = eval_fct(snes,w,y); CHKERRQ(ierr);
1780a25c783SBarry Smith 
179195ee392SLois Curfman McInnes   ierr = VecAXPY(&mone,F,y); CHKERRQ(ierr);
1805334005bSBarry Smith   h = 1.0/h;
181195ee392SLois Curfman McInnes   ierr = VecScale(&h,y); CHKERRQ(ierr);
182b4fd4287SBarry Smith   if (ctx->sp) {ierr = PCNullSpaceRemove(ctx->sp,y); CHKERRQ(ierr);}
18357c37382SLois Curfman McInnes 
184eb9086c3SLois Curfman McInnes   PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);
1853a40ed3dSBarry Smith   PetscFunctionReturn(0);
18639e2f89bSBarry Smith }
18783e56afdSLois Curfman McInnes 
1885615d1e5SSatish Balay #undef __FUNC__
1895615d1e5SSatish Balay #define __FUNC__ "SNESDefaultMatrixFreeMatCreate"
1904b828684SBarry Smith /*@C
1915392566eSBarry Smith    SNESDefaultMatrixFreeMatCreate - Creates a matrix-free matrix
19250361f65SLois Curfman McInnes    context for use with a SNES solver.  This matrix can be used as
19350361f65SLois Curfman McInnes    the Jacobian argument for the routine SNESSetJacobian().
1945392566eSBarry Smith 
195c7afd0dbSLois Curfman McInnes    Collective on SNES and Vec
196c7afd0dbSLois Curfman McInnes 
1975392566eSBarry Smith    Input Parameters:
198c7afd0dbSLois Curfman McInnes +  snes - the SNES context
199c7afd0dbSLois Curfman McInnes -  x - vector where SNES solution is to be stored.
2005392566eSBarry Smith 
201eb9086c3SLois Curfman McInnes    Output Parameter:
2025392566eSBarry Smith .  J - the matrix-free matrix
2035392566eSBarry Smith 
20465afa06eSLois Curfman McInnes    Notes:
20565afa06eSLois Curfman McInnes    The matrix-free matrix context merely contains the function pointers
20665afa06eSLois Curfman McInnes    and work space for performing finite difference approximations of
2073d5db8e1SLois Curfman McInnes    Jacobian-vector products, J(u)*a, via
2083d5db8e1SLois Curfman McInnes 
209c7afd0dbSLois Curfman McInnes .vb
210c7afd0dbSLois Curfman McInnes      J(u)*a = [J(u+h*a) - J(u)]/h where
211c7afd0dbSLois Curfman McInnes      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
212c7afd0dbSLois Curfman McInnes        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
213c7afd0dbSLois Curfman McInnes  where
214c7afd0dbSLois Curfman McInnes      error_rel = square root of relative error in function evaluation
215c7afd0dbSLois Curfman McInnes      umin = minimum iterate parameter
216c7afd0dbSLois Curfman McInnes .ve
2173d5db8e1SLois Curfman McInnes 
2183d5db8e1SLois Curfman McInnes    The user can set these parameters via SNESSetMatrixFreeParameters().
2193d5db8e1SLois Curfman McInnes    See the nonlinear solvers chapter of the users manual for details.
22065afa06eSLois Curfman McInnes 
22165afa06eSLois Curfman McInnes    The user should call MatDestroy() when finished with the matrix-free
22265afa06eSLois Curfman McInnes    matrix context.
22365afa06eSLois Curfman McInnes 
2243d5db8e1SLois Curfman McInnes    Options Database Keys:
225c7afd0dbSLois Curfman McInnes +  -snes_mf_err <error_rel> - Sets error_rel
226c7afd0dbSLois Curfman McInnes -  -snes_mf_unim <umin> - Sets umin
2273d5db8e1SLois Curfman McInnes 
22865afa06eSLois Curfman McInnes .keywords: SNES, default, matrix-free, create, matrix
22965afa06eSLois Curfman McInnes 
2303d5db8e1SLois Curfman McInnes .seealso: MatDestroy(), SNESSetMatrixFreeParameters()
2315392566eSBarry Smith @*/
2325392566eSBarry Smith int SNESDefaultMatrixFreeMatCreate(SNES snes,Vec x, Mat *J)
2335392566eSBarry Smith {
2345392566eSBarry Smith   MPI_Comm      comm;
2355392566eSBarry Smith   MFCtx_Private *mfctx;
236eb9086c3SLois Curfman McInnes   int           n, nloc, ierr, flg;
2373e966953SLois Curfman McInnes   char          p[64];
2385392566eSBarry Smith 
2393a40ed3dSBarry Smith   PetscFunctionBegin;
2400452661fSBarry Smith   mfctx = (MFCtx_Private *) PetscMalloc(sizeof(MFCtx_Private)); CHKPTRQ(mfctx);
241464493b3SBarry Smith   PLogObjectMemory(snes,sizeof(MFCtx_Private));
242b4fd4287SBarry Smith   mfctx->sp   = 0;
2435392566eSBarry Smith   mfctx->snes = snes;
244eb9086c3SLois Curfman McInnes   mfctx->error_rel = 1.e-8; /* assumes double precision */
245639f9d9dSBarry Smith   mfctx->umin      = 1.e-6;
246eb9086c3SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg); CHKERRQ(ierr);
247eb9086c3SLois Curfman McInnes   ierr = OptionsGetDouble(snes->prefix,"-snes_mf_umin",&mfctx->umin,&flg); CHKERRQ(ierr);
248639f9d9dSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr);
2493e966953SLois Curfman McInnes   PetscStrcpy(p,"-");
2503e966953SLois Curfman McInnes   if (snes->prefix) PetscStrcat(p,snes->prefix);
251639f9d9dSBarry Smith   if (flg) {
25276be9ce4SBarry Smith     (*PetscHelpPrintf)(snes->comm,"   %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);
25376be9ce4SBarry Smith     (*PetscHelpPrintf)(snes->comm,"   %ssnes_mf_umin <umin> see users manual (default %g)\n",p,mfctx->umin);
254639f9d9dSBarry Smith   }
2555392566eSBarry Smith   ierr = VecDuplicate(x,&mfctx->w); CHKERRQ(ierr);
256195ee392SLois Curfman McInnes   ierr = PetscObjectGetComm((PetscObject)x,&comm); CHKERRQ(ierr);
257195ee392SLois Curfman McInnes   ierr = VecGetSize(x,&n); CHKERRQ(ierr);
2587ddc982cSLois Curfman McInnes   ierr = VecGetLocalSize(x,&nloc); CHKERRQ(ierr);
259029af93fSBarry Smith   ierr = MatCreateShell(comm,nloc,n,n,n,mfctx,J); CHKERRQ(ierr);
2601c1c02c0SLois Curfman McInnes   ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)SNESMatrixFreeMult_Private);CHKERRQ(ierr);
2611c1c02c0SLois Curfman McInnes   ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)SNESMatrixFreeDestroy_Private);CHKERRQ(ierr);
2621c1c02c0SLois Curfman McInnes   ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)SNESMatrixFreeView_Private); CHKERRQ(ierr);
263b9fa9cd0SBarry Smith   PLogObjectParent(*J,mfctx->w);
264d370d78aSBarry Smith   PLogObjectParent(snes,*J);
2653a40ed3dSBarry Smith   PetscFunctionReturn(0);
26681e6777dSBarry Smith }
26781e6777dSBarry Smith 
2685615d1e5SSatish Balay #undef __FUNC__
269*8f6e3e37SBarry Smith #define __FUNC__ "SNESGetMatrixFreeH"
270*8f6e3e37SBarry Smith /*@
271*8f6e3e37SBarry Smith    SNESGetMatrixFreeH - Gets the last h that was used as the differencing
272*8f6e3e37SBarry Smith      parameter.
273*8f6e3e37SBarry Smith 
274*8f6e3e37SBarry Smith    Not Collective
275*8f6e3e37SBarry Smith 
276*8f6e3e37SBarry Smith    Input Parameters:
277*8f6e3e37SBarry Smith .  snes - the SNES context
278*8f6e3e37SBarry Smith 
279*8f6e3e37SBarry Smith    Output Paramter:
280*8f6e3e37SBarry Smith .  h - the differencing step size
281*8f6e3e37SBarry Smith 
282*8f6e3e37SBarry Smith .keywords: SNES, matrix-free, parameters
283*8f6e3e37SBarry Smith 
284*8f6e3e37SBarry Smith .seealso: SNESDefaultMatrixFreeMatCreate()
285*8f6e3e37SBarry Smith @*/
286*8f6e3e37SBarry Smith int SNESGetMatrixFreeH(SNES snes,double *h)
287*8f6e3e37SBarry Smith {
288*8f6e3e37SBarry Smith   MFCtx_Private *ctx;
289*8f6e3e37SBarry Smith   int           ierr;
290*8f6e3e37SBarry Smith   Mat           mat;
291*8f6e3e37SBarry Smith 
292*8f6e3e37SBarry Smith   PetscFunctionBegin;
293*8f6e3e37SBarry Smith   ierr = SNESGetJacobian(snes,&mat,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr);
294*8f6e3e37SBarry Smith   ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr);
295*8f6e3e37SBarry Smith   if (ctx) {
296*8f6e3e37SBarry Smith     *h = ctx->currenth;
297*8f6e3e37SBarry Smith   }
298*8f6e3e37SBarry Smith   PetscFunctionReturn(0);
299*8f6e3e37SBarry Smith }
300*8f6e3e37SBarry Smith 
301*8f6e3e37SBarry Smith #undef __FUNC__
3025615d1e5SSatish Balay #define __FUNC__ "SNESSetMatrixFreeParameters"
303b4fd4287SBarry Smith /*@
304eb9086c3SLois Curfman McInnes    SNESSetMatrixFreeParameters - Sets the parameters for the approximation of
305eb9086c3SLois Curfman McInnes    matrix-vector products using finite differences.
306eb9086c3SLois Curfman McInnes 
307c7afd0dbSLois Curfman McInnes    Collective on SNES
308c7afd0dbSLois Curfman McInnes 
309eb9086c3SLois Curfman McInnes    Input Parameters:
310c7afd0dbSLois Curfman McInnes +  snes - the SNES context
311ccb6204bSLois Curfman McInnes .  error_rel - relative error (should be set to the square root of
312ccb6204bSLois Curfman McInnes                the relative error in the function evaluations)
313c7afd0dbSLois Curfman McInnes -  umin - minimum allowable u-value
314eb9086c3SLois Curfman McInnes 
315c7afd0dbSLois Curfman McInnes    Notes:
316c7afd0dbSLois Curfman McInnes    The default matrix-free matrix-vector product routine computes
317c7afd0dbSLois Curfman McInnes .vb
318c7afd0dbSLois Curfman McInnes      J(u)*a = [J(u+h*a) - J(u)]/h where
319c7afd0dbSLois Curfman McInnes      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
320c7afd0dbSLois Curfman McInnes        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   else
321c7afd0dbSLois Curfman McInnes .ve
322c7afd0dbSLois Curfman McInnes 
323c7afd0dbSLois Curfman McInnes    Options Database Keys:
324c7afd0dbSLois Curfman McInnes +  -snes_mf_err <error_rel> - Sets error_rel
325c7afd0dbSLois Curfman McInnes -  -snes_mf_unim <umin> - Sets umin
326fee21e36SBarry Smith 
327eb9086c3SLois Curfman McInnes .keywords: SNES, matrix-free, parameters
3283d5db8e1SLois Curfman McInnes 
3293d5db8e1SLois Curfman McInnes .seealso: SNESDefaultMatrixFreeMatCreate()
330eb9086c3SLois Curfman McInnes @*/
331eb9086c3SLois Curfman McInnes int SNESSetMatrixFreeParameters(SNES snes,double error,double umin)
332eb9086c3SLois Curfman McInnes {
333eb9086c3SLois Curfman McInnes   MFCtx_Private *ctx;
334eb9086c3SLois Curfman McInnes   int           ierr;
335eb9086c3SLois Curfman McInnes   Mat           mat;
336eb9086c3SLois Curfman McInnes 
3373a40ed3dSBarry Smith   PetscFunctionBegin;
338eb9086c3SLois Curfman McInnes   ierr = SNESGetJacobian(snes,&mat,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr);
339eb9086c3SLois Curfman McInnes   ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr);
340eb9086c3SLois Curfman McInnes   if (ctx) {
341eb9086c3SLois Curfman McInnes     if (error != PETSC_DEFAULT) ctx->error_rel = error;
342eb9086c3SLois Curfman McInnes     if (umin != PETSC_DEFAULT)  ctx->umin = umin;
343eb9086c3SLois Curfman McInnes   }
3443a40ed3dSBarry Smith   PetscFunctionReturn(0);
345eb9086c3SLois Curfman McInnes }
346eb9086c3SLois Curfman McInnes 
3475615d1e5SSatish Balay #undef __FUNC__
3485615d1e5SSatish Balay #define __FUNC__ "SNESDefaultMatrixFreeMatAddNullSpace"
349eb9086c3SLois Curfman McInnes /*@
35021a45821SLois Curfman McInnes    SNESDefaultMatrixFreeMatAddNullSpace - Provides a null space that
351f525115eSLois Curfman McInnes    an operator is supposed to have.  Since roundoff will create a
352b4fd4287SBarry Smith    small component in the null space, if you know the null space
353b4fd4287SBarry Smith    you may have it automatically removed.
354b4fd4287SBarry Smith 
355c7afd0dbSLois Curfman McInnes    Collective on Mat
356c7afd0dbSLois Curfman McInnes 
357b4fd4287SBarry Smith    Input Parameters:
358c7afd0dbSLois Curfman McInnes +  J - the matrix-free matrix context
35921a45821SLois Curfman McInnes .  has_cnst - PETSC_TRUE or PETSC_FALSE, indicating if null space has constants
360b4fd4287SBarry Smith .  n - number of vectors (excluding constant vector) in null space
361c7afd0dbSLois Curfman McInnes -  vecs - the vectors that span the null space (excluding the constant vector);
362c7afd0dbSLois Curfman McInnes           these vectors must be orthonormal
363fee21e36SBarry Smith 
364b4fd4287SBarry Smith .keywords: SNES, matrix-free, null space
365b4fd4287SBarry Smith @*/
366b4fd4287SBarry Smith int SNESDefaultMatrixFreeMatAddNullSpace(Mat J,int has_cnst,int n,Vec *vecs)
367b4fd4287SBarry Smith {
368b4fd4287SBarry Smith   int           ierr;
369b4fd4287SBarry Smith   MFCtx_Private *ctx;
370b4fd4287SBarry Smith   MPI_Comm      comm;
371b4fd4287SBarry Smith 
3723a40ed3dSBarry Smith   PetscFunctionBegin;
373b4fd4287SBarry Smith   PetscObjectGetComm((PetscObject)J,&comm);
374b4fd4287SBarry Smith 
375b4fd4287SBarry Smith   ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr);
376b4fd4287SBarry Smith   /* no context indicates that it is not the "matrix free" matrix type */
3773a40ed3dSBarry Smith   if (!ctx) PetscFunctionReturn(0);
378b4fd4287SBarry Smith   ierr = PCNullSpaceCreate(comm,has_cnst,n,vecs,&ctx->sp); CHKERRQ(ierr);
3793a40ed3dSBarry Smith   PetscFunctionReturn(0);
380b4fd4287SBarry Smith }
381b4fd4287SBarry Smith 
3825334005bSBarry Smith 
3835334005bSBarry Smith 
3845334005bSBarry Smith 
385