181e6777dSBarry Smith 281e6777dSBarry Smith #ifndef lint 3*57c37382SLois Curfman McInnes static char vcid[] = "$Id: snesmfj.c,v 1.25 1996/01/23 00:19:51 bsmith Exp curfman $"; 481e6777dSBarry Smith #endif 581e6777dSBarry Smith 6b1f0a012SBarry Smith #include "draw.h" /*I "draw.h" I*/ 7b1f0a012SBarry Smith #include "snes.h" /*I "snes.h" I*/ 881e6777dSBarry Smith 950361f65SLois Curfman McInnes typedef struct { /* default context for matrix-free SNES */ 1039e2f89bSBarry Smith SNES snes; 1139e2f89bSBarry Smith Vec w; 12b4fd4287SBarry Smith PCNullSpace sp; 1339e2f89bSBarry Smith } MFCtx_Private; 1439e2f89bSBarry Smith 15b9fa9cd0SBarry Smith int SNESMatrixFreeDestroy_Private(void *ptr) 16b9fa9cd0SBarry Smith { 17b9fa9cd0SBarry Smith int ierr; 18b9fa9cd0SBarry Smith MFCtx_Private *ctx = (MFCtx_Private* ) ptr; 19b9fa9cd0SBarry Smith ierr = VecDestroy(ctx->w); CHKERRQ(ierr); 20b4fd4287SBarry Smith if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp); CHKERRQ(ierr);} 210452661fSBarry Smith PetscFree(ptr); 22b9fa9cd0SBarry Smith return 0; 23b9fa9cd0SBarry Smith } 2450361f65SLois Curfman McInnes 2539e2f89bSBarry Smith /* 2639e2f89bSBarry Smith SNESMatrixFreeMult_Private - Default matrix free form of A*u. 2739e2f89bSBarry Smith */ 2839e2f89bSBarry Smith int SNESMatrixFreeMult_Private(void *ptr,Vec dx,Vec y) 2939e2f89bSBarry Smith { 3039e2f89bSBarry Smith MFCtx_Private *ctx = (MFCtx_Private* ) ptr; 3139e2f89bSBarry Smith SNES snes = ctx->snes; 325334005bSBarry Smith double norm,sum,epsilon = 1.e-8; /* assumes double precision */ 335334005bSBarry Smith Scalar h,dot,mone = -1.0; 3439e2f89bSBarry Smith Vec w = ctx->w,U,F; 3539e2f89bSBarry Smith int ierr; 3639e2f89bSBarry Smith 37*57c37382SLois Curfman McInnes /* We log matrix-free matrix-vector products separately, so that we can 38*57c37382SLois Curfman McInnes separate the performance monitoring from the cases that use conventional 39*57c37382SLois Curfman McInnes storage. We may eventually modify event logging to associate events 40*57c37382SLois Curfman McInnes with particular objects, hence alleviating the more general problem. */ 41*57c37382SLois Curfman McInnes PLogEventBegin(MAT_MatrixFreeMult,dx,y,0,0); 42*57c37382SLois Curfman McInnes 4378b31e54SBarry Smith ierr = SNESGetSolution(snes,&U); CHKERRQ(ierr); 4478b31e54SBarry Smith ierr = SNESGetFunction(snes,&F); CHKERRQ(ierr); 4550361f65SLois Curfman McInnes 4650361f65SLois Curfman McInnes /* Determine a "good" step size */ 4750361f65SLois Curfman McInnes ierr = VecDot(U,dx,&dot); CHKERRQ(ierr); 48cddf8d76SBarry Smith ierr = VecNorm(dx,NORM_1,&sum); CHKERRQ(ierr); 49cddf8d76SBarry Smith ierr = VecNorm(dx,NORM_2,&norm); CHKERRQ(ierr); 50edd2f0e1SBarry Smith if (sum == 0.0) {dot = 1.0; norm = 1.0;} 5119a167f6SBarry Smith #if defined(PETSC_COMPLEX) 5219a167f6SBarry Smith else if (abs(dot) < 1.e-16*sum && real(dot) >= 0.0) dot = 1.e-16*sum; 5319a167f6SBarry Smith else if (abs(dot) < 0.0 && real(dot) > 1.e-16*sum) dot = -1.e-16*sum; 5419a167f6SBarry Smith #else 55edd2f0e1SBarry Smith else if (dot < 1.e-16*sum && dot >= 0.0) dot = 1.e-16*sum; 5639e2f89bSBarry Smith else if (dot < 0.0 && dot > 1.e-16*sum) dot = -1.e-16*sum; 5719a167f6SBarry Smith #endif 5839e2f89bSBarry Smith h = epsilon*dot/(norm*norm); 5939e2f89bSBarry Smith 6050361f65SLois Curfman McInnes /* Evaluate function at F(x + dx) */ 61195ee392SLois Curfman McInnes ierr = VecWAXPY(&h,dx,U,w); CHKERRQ(ierr); 6278b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,y); CHKERRQ(ierr); 63195ee392SLois Curfman McInnes ierr = VecAXPY(&mone,F,y); CHKERRQ(ierr); 645334005bSBarry Smith h = 1.0/h; 65195ee392SLois Curfman McInnes ierr = VecScale(&h,y); CHKERRQ(ierr); 66b4fd4287SBarry Smith if (ctx->sp) { ierr = PCNullSpaceRemove(ctx->sp,y); CHKERRQ(ierr);} 67*57c37382SLois Curfman McInnes 68*57c37382SLois Curfman McInnes PLogEventEnd(MAT_MatrixFreeMult,dx,y,0,0); 6939e2f89bSBarry Smith return 0; 7039e2f89bSBarry Smith } 714b828684SBarry Smith /*@C 725392566eSBarry Smith SNESDefaultMatrixFreeMatCreate - Creates a matrix-free matrix 7350361f65SLois Curfman McInnes context for use with a SNES solver. This matrix can be used as 7450361f65SLois Curfman McInnes the Jacobian argument for the routine SNESSetJacobian(). 755392566eSBarry Smith 765392566eSBarry Smith Input Parameters: 775392566eSBarry Smith . x - vector where SNES solution is to be stored. 785392566eSBarry Smith 795392566eSBarry Smith Output Parameters: 805392566eSBarry Smith . J - the matrix-free matrix 815392566eSBarry Smith 8265afa06eSLois Curfman McInnes Notes: 8365afa06eSLois Curfman McInnes The matrix-free matrix context merely contains the function pointers 8465afa06eSLois Curfman McInnes and work space for performing finite difference approximations of 8565afa06eSLois Curfman McInnes matrix operations such as matrix-vector products. 8665afa06eSLois Curfman McInnes 8765afa06eSLois Curfman McInnes The user should call MatDestroy() when finished with the matrix-free 8865afa06eSLois Curfman McInnes matrix context. 8965afa06eSLois Curfman McInnes 9065afa06eSLois Curfman McInnes .keywords: SNES, default, matrix-free, create, matrix 9165afa06eSLois Curfman McInnes 9265afa06eSLois Curfman McInnes .seealso: MatDestroy() 935392566eSBarry Smith @*/ 945392566eSBarry Smith int SNESDefaultMatrixFreeMatCreate(SNES snes,Vec x, Mat *J) 955392566eSBarry Smith { 965392566eSBarry Smith MPI_Comm comm; 975392566eSBarry Smith MFCtx_Private *mfctx; 985392566eSBarry Smith int n,ierr; 995392566eSBarry Smith 1000452661fSBarry Smith mfctx = (MFCtx_Private *) PetscMalloc(sizeof(MFCtx_Private)); CHKPTRQ(mfctx); 101464493b3SBarry Smith PLogObjectMemory(snes,sizeof(MFCtx_Private)); 102b4fd4287SBarry Smith mfctx->sp = 0; 1035392566eSBarry Smith mfctx->snes = snes; 1045392566eSBarry Smith ierr = VecDuplicate(x,&mfctx->w); CHKERRQ(ierr); 105195ee392SLois Curfman McInnes ierr = PetscObjectGetComm((PetscObject)x,&comm); CHKERRQ(ierr); 106195ee392SLois Curfman McInnes ierr = VecGetSize(x,&n); CHKERRQ(ierr); 107052efed2SBarry Smith ierr = MatCreateShell(comm,n,n,(void*)mfctx,J); CHKERRQ(ierr); 108195ee392SLois Curfman McInnes ierr = MatShellSetMult(*J,SNESMatrixFreeMult_Private); CHKERRQ(ierr); 109195ee392SLois Curfman McInnes ierr = MatShellSetDestroy(*J,SNESMatrixFreeDestroy_Private); CHKERRQ(ierr); 110b9fa9cd0SBarry Smith PLogObjectParent(*J,mfctx->w); 111d370d78aSBarry Smith PLogObjectParent(snes,*J); 11281e6777dSBarry Smith return 0; 11381e6777dSBarry Smith } 11481e6777dSBarry Smith 115b4fd4287SBarry Smith /*@ 116b4fd4287SBarry Smith SNESDefaultMatrixFreeMatAddNullSpace - Provide a null space that 117b4fd4287SBarry Smith an operator is suppose to have. Since round off will create a 118b4fd4287SBarry Smith small component in the null space, if you know the null space 119b4fd4287SBarry Smith you may have it automatically removed. 120b4fd4287SBarry Smith 121b4fd4287SBarry Smith Input Parameters: 122b4fd4287SBarry Smith . J - the matrix free matrix 123b4fd4287SBarry Smith . has_cnst - PETSC_TRUE or PETSC_FALSE indicating if null space has constants 124b4fd4287SBarry Smith . n - number of vectors (excluding constant vector) in null space 125b4fd4287SBarry Smith . vecs - the vectors that span the null space (excluding the constant vector) 126b4fd4287SBarry Smith . these vectors must be orthonormal 127b4fd4287SBarry Smith 128b4fd4287SBarry Smith .keywords: SNES, matrix-free, null space 129b4fd4287SBarry Smith @*/ 130b4fd4287SBarry Smith int SNESDefaultMatrixFreeMatAddNullSpace(Mat J,int has_cnst,int n,Vec *vecs) 131b4fd4287SBarry Smith { 132b4fd4287SBarry Smith int ierr; 133b4fd4287SBarry Smith MFCtx_Private *ctx; 134b4fd4287SBarry Smith MPI_Comm comm; 135b4fd4287SBarry Smith 136b4fd4287SBarry Smith PetscObjectGetComm((PetscObject)J,&comm); 137b4fd4287SBarry Smith 138b4fd4287SBarry Smith ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 139b4fd4287SBarry Smith /* no context indicates that it is not the "matrix free" matrix type */ 140b4fd4287SBarry Smith if (!ctx) return 0; 141b4fd4287SBarry Smith ierr = PCNullSpaceCreate(comm,has_cnst,n,vecs,&ctx->sp); CHKERRQ(ierr); 142b4fd4287SBarry Smith return 0; 143b4fd4287SBarry Smith } 144b4fd4287SBarry Smith 1455334005bSBarry Smith 1465334005bSBarry Smith 1475334005bSBarry Smith 148