181e6777dSBarry Smith 281e6777dSBarry Smith #ifndef lint 3*5392566eSBarry Smith static char vcid[] = "$Id: snesmfj.c,v 1.9 1995/06/08 03:11:42 bsmith Exp bsmith $"; 481e6777dSBarry Smith #endif 581e6777dSBarry Smith 681e6777dSBarry Smith #include "draw.h" 7f3b845d0SBarry Smith #include "snes.h" 881e6777dSBarry Smith 939e2f89bSBarry Smith typedef struct { 1039e2f89bSBarry Smith SNES snes; 1139e2f89bSBarry Smith Vec w; 1239e2f89bSBarry Smith } MFCtx_Private; 1339e2f89bSBarry Smith 1439e2f89bSBarry Smith /* 1539e2f89bSBarry Smith SNESMatrixFreeMult_Private - Default matrix free form of A*u. 1639e2f89bSBarry Smith 1739e2f89bSBarry Smith */ 1839e2f89bSBarry Smith int SNESMatrixFreeMult_Private(void *ptr,Vec dx,Vec y) 1939e2f89bSBarry Smith { 2039e2f89bSBarry Smith MFCtx_Private *ctx = (MFCtx_Private* ) ptr; 2139e2f89bSBarry Smith SNES snes = ctx->snes; 2239e2f89bSBarry Smith double norm,epsilon = 1.e-8; /* assumes double precision */ 2339e2f89bSBarry Smith Scalar h,dot,sum; 2439e2f89bSBarry Smith Scalar mone = -1.0; 2539e2f89bSBarry Smith Vec w = ctx->w,U,F; 2639e2f89bSBarry Smith int ierr; 2739e2f89bSBarry Smith 2878b31e54SBarry Smith ierr = SNESGetSolution(snes,&U); CHKERRQ(ierr); 2978b31e54SBarry Smith ierr = SNESGetFunction(snes,&F); CHKERRQ(ierr); 3039e2f89bSBarry Smith /* determine a "good" step size */ 3139e2f89bSBarry Smith VecDot(U,dx,&dot); VecASum(dx,&sum); VecNorm(dx,&norm); 32edd2f0e1SBarry Smith if (sum == 0.0) {dot = 1.0; norm = 1.0;} 33edd2f0e1SBarry Smith else if (dot < 1.e-16*sum && dot >= 0.0) dot = 1.e-16*sum; 3439e2f89bSBarry Smith else if (dot < 0.0 && dot > 1.e-16*sum) dot = -1.e-16*sum; 3539e2f89bSBarry Smith h = epsilon*dot/(norm*norm); 3639e2f89bSBarry Smith 3739e2f89bSBarry Smith /* evaluate function at F(x + dx) */ 3839e2f89bSBarry Smith VecWAXPY(&h,dx,U,w); 3978b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,y); CHKERRQ(ierr); 4039e2f89bSBarry Smith VecAXPY(&mone,F,y); 4139e2f89bSBarry Smith h = -1.0/h; 4239e2f89bSBarry Smith VecScale(&h,y); 4339e2f89bSBarry Smith return 0; 4439e2f89bSBarry Smith } 4581e6777dSBarry Smith /*@ 46*5392566eSBarry Smith SNESDefaultMatrixFreeMatCreate - Creates a matrix-free matrix 47*5392566eSBarry Smith for use with SNES solver. You may use this matrix as 48*5392566eSBarry Smith Jacobian argument for the routine SNESSetJacobian. This is 49*5392566eSBarry Smith most useful when you are using finite differences for a 50*5392566eSBarry Smith matrix free Newton method but explictly are forming a 51*5392566eSBarry Smith preconditioner matrix. 52*5392566eSBarry Smith 53*5392566eSBarry Smith Input Parameters: 54*5392566eSBarry Smith . x - vector where SNES solution is to be stored. 55*5392566eSBarry Smith 56*5392566eSBarry Smith Output Parameters: 57*5392566eSBarry Smith . J - the matrix-free matrix 58*5392566eSBarry Smith 59*5392566eSBarry Smith @*/ 60*5392566eSBarry Smith int SNESDefaultMatrixFreeMatCreate(SNES snes,Vec x, Mat *J) 61*5392566eSBarry Smith { 62*5392566eSBarry Smith MPI_Comm comm; 63*5392566eSBarry Smith MFCtx_Private *mfctx; 64*5392566eSBarry Smith int n,ierr; 65*5392566eSBarry Smith 66*5392566eSBarry Smith mfctx = (MFCtx_Private *) PETSCMALLOC(sizeof(MFCtx_Private));CHKPTRQ(mfctx); 67*5392566eSBarry Smith mfctx->snes = snes; 68*5392566eSBarry Smith ierr = VecDuplicate(x,&mfctx->w); CHKERRQ(ierr); 69*5392566eSBarry Smith PetscObjectGetComm((PetscObject)x,&comm); 70*5392566eSBarry Smith VecGetSize(x,&n); 71*5392566eSBarry Smith ierr = MatShellCreate(comm,n,n,(void*)mfctx,J); CHKERRQ(ierr); 72*5392566eSBarry Smith MatShellSetMult(*J,SNESMatrixFreeMult_Private); 73*5392566eSBarry Smith return 0; 74*5392566eSBarry Smith } 75*5392566eSBarry Smith /*@ 7639e2f89bSBarry Smith SNESDefaultMatrixFreeComputeJacobian - Computes Jacobian using finite 7771dce806SLois Curfman McInnes differences, matrix-free style. 7881e6777dSBarry Smith 7981e6777dSBarry Smith Input Parameters: 8081e6777dSBarry Smith . x - compute Jacobian at this point 81ad960d00SLois Curfman McInnes . ctx - application's function context, as set with SNESSetFunction() 8281e6777dSBarry Smith 8381e6777dSBarry Smith Output Parameters: 8481e6777dSBarry Smith . J - Jacobian 8581e6777dSBarry Smith . B - preconditioner, same as Jacobian 86ad960d00SLois Curfman McInnes . flag - matrix flag 87ad960d00SLois Curfman McInnes 88ad960d00SLois Curfman McInnes Options Database Key: 89ad960d00SLois Curfman McInnes $ -snes_mf 9081e6777dSBarry Smith 9171dce806SLois Curfman McInnes .keywords: SNES, finite differences, Jacobian 9281e6777dSBarry Smith 9371dce806SLois Curfman McInnes .seealso: SNESSetJacobian(), SNESTestJacobian() 9481e6777dSBarry Smith @*/ 9539e2f89bSBarry Smith int SNESDefaultMatrixFreeComputeJacobian(SNES snes, Vec x1,Mat *J,Mat *B, 96edd2f0e1SBarry Smith MatStructure *flag,void *ctx) 9781e6777dSBarry Smith { 9839e2f89bSBarry Smith int n,ierr; 997f223b93SBarry Smith MatType type; 1007f223b93SBarry Smith 10139e2f89bSBarry Smith VecGetSize(x1,&n); 1027f223b93SBarry Smith if (*J) MatGetType(*J,&type); 1037f223b93SBarry Smith if (!*J || type != MATSHELL) { 1047f223b93SBarry Smith MPI_Comm comm; 10539e2f89bSBarry Smith MFCtx_Private *mfctx; 10639e2f89bSBarry Smith /* first time in, therefore build datastructures */ 10778b31e54SBarry Smith mfctx = (MFCtx_Private *) PETSCMALLOC(sizeof(MFCtx_Private)); CHKPTRQ(mfctx); 10839e2f89bSBarry Smith mfctx->snes = snes; 10978b31e54SBarry Smith ierr = VecDuplicate(x1,&mfctx->w); CHKERRQ(ierr); 1107f223b93SBarry Smith PetscObjectGetComm((PetscObject)x1,&comm); 11178b31e54SBarry Smith ierr = MatShellCreate(comm,n,n,(void*)mfctx,J); CHKERRQ(ierr); 11239e2f89bSBarry Smith MatShellSetMult(*J,SNESMatrixFreeMult_Private); 11339e2f89bSBarry Smith *B = *J; 11481e6777dSBarry Smith } 11581e6777dSBarry Smith return 0; 11681e6777dSBarry Smith } 11781e6777dSBarry Smith 118