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