19a6cb015SBarry Smith 2a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 3*3f1db9ecSBarry Smith static char vcid[] = "$Id: snesmfj.c,v 1.76 1998/12/09 16:08:05 balay Exp bsmith $"; 481e6777dSBarry Smith #endif 581e6777dSBarry Smith 69a6cb015SBarry Smith #include "src/snes/snesimpl.h" 79a6cb015SBarry Smith #include "src/snes/mf/snesmfj.h" /*I "snes.h" I*/ 881e6777dSBarry Smith 99a6cb015SBarry Smith FList MatSNESFDMFList = 0; 109a6cb015SBarry Smith int MatSNESFDMFRegisterAllCalled = 0; 11a4d4d686SBarry Smith 1239e2f89bSBarry Smith 135615d1e5SSatish Balay #undef __FUNC__ 14a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFSetType" 159a6cb015SBarry Smith /*@ 169a6cb015SBarry Smith MatSNESFDMFSetType - Sets the method that is used to compute the h in the 179a6cb015SBarry Smith finite difference matrix free formulation. 189a6cb015SBarry Smith 199a6cb015SBarry Smith Input Parameters: 209a6cb015SBarry Smith + mat - the matrix free matrix created via MatCreateSNESFDMF() 219a6cb015SBarry Smith - ftype - the type requested 229a6cb015SBarry Smith 239a6cb015SBarry Smith .seealso: MatCreateSNESFDMF(), MatSNESFDMFRegister() 249a6cb015SBarry Smith @*/ 259a6cb015SBarry Smith int MatSNESFDMFSetType(Mat mat,char *ftype) 26b9fa9cd0SBarry Smith { 279a6cb015SBarry Smith int ierr, (*r)(MatSNESFDMFCtx); 28a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 29a4d4d686SBarry Smith 30a4d4d686SBarry Smith PetscFunctionBegin; 31a4d4d686SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 32a4d4d686SBarry Smith 339a6cb015SBarry Smith /* already set, so just return */ 34*3f1db9ecSBarry Smith if (PetscTypeCompare(ctx->type_name,ftype)) PetscFunctionReturn(0); 35a4d4d686SBarry Smith 369a6cb015SBarry Smith /* destroy the old one if it exists */ 379a6cb015SBarry Smith if (ctx->ops->destroy) { 389a6cb015SBarry Smith ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr); 399a6cb015SBarry Smith } 409a6cb015SBarry Smith 419a6cb015SBarry Smith /* Get the function pointers for the iterative method requested */ 429a6cb015SBarry Smith if (!MatSNESFDMFRegisterAllCalled) {ierr = MatSNESFDMFRegisterAll(PETSC_NULL); CHKERRQ(ierr);} 439a6cb015SBarry Smith 449a6cb015SBarry Smith ierr = FListFind(ctx->comm, MatSNESFDMFList, ftype,(int (**)(void *)) &r );CHKERRQ(ierr); 459a6cb015SBarry Smith 469a6cb015SBarry Smith if (!r) SETERRQ(1,1,"Unknown MatSNESFDMF type given"); 479a6cb015SBarry Smith 489a6cb015SBarry Smith ierr = (*r)(ctx); CHKERRQ(ierr); 499a6cb015SBarry Smith ierr = PetscStrncpy(ctx->type_name,ftype,256);CHKERRQ(ierr); 509a6cb015SBarry Smith 519a6cb015SBarry Smith PetscFunctionReturn(0); 529a6cb015SBarry Smith } 539a6cb015SBarry Smith 549a6cb015SBarry Smith /*MC 559a6cb015SBarry Smith MatSNESFDMFRegister - Adds a method to the MatSNESFDMF registry 569a6cb015SBarry Smith 579a6cb015SBarry Smith Synopsis: 589a6cb015SBarry Smith MatSNESFDMFRegister(char *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESFDMF)) 599a6cb015SBarry Smith 609a6cb015SBarry Smith Not Collective 619a6cb015SBarry Smith 629a6cb015SBarry Smith Input Parameters: 639a6cb015SBarry Smith + name_solver - name of a new user-defined compute-h module 649a6cb015SBarry Smith . path - path (either absolute or relative) the library containing this solver 659a6cb015SBarry Smith . name_create - name of routine to create method context 669a6cb015SBarry Smith - routine_create - routine to create method context 679a6cb015SBarry Smith 689a6cb015SBarry Smith Notes: 699a6cb015SBarry Smith MatSNESFDMFRegister() may be called multiple times to add several user-defined solvers. 709a6cb015SBarry Smith 719a6cb015SBarry Smith If dynamic libraries are used, then the fourth input argument (routine_create) 729a6cb015SBarry Smith is ignored. 739a6cb015SBarry Smith 749a6cb015SBarry Smith Sample usage: 759a6cb015SBarry Smith .vb 769a6cb015SBarry Smith MatSNESFDMFRegister("my_h",/home/username/my_lib/lib/libO/solaris/mylib.a, 779a6cb015SBarry Smith "MyHCreate",MyHCreate); 789a6cb015SBarry Smith .ve 799a6cb015SBarry Smith 809a6cb015SBarry Smith Then, your solver can be chosen with the procedural interface via 819a6cb015SBarry Smith $ MatSNESFDMFSetType(mfctx,"my_h") 829a6cb015SBarry Smith or at runtime via the option 839a6cb015SBarry Smith $ -snes_mf_type my_h 849a6cb015SBarry Smith 859a6cb015SBarry Smith .keywords: MatSNESFDMF, register 869a6cb015SBarry Smith 879a6cb015SBarry Smith .seealso: MatSNESFDMFRegisterAll(), MatSNESFDMFRegisterDestroy() 889a6cb015SBarry Smith M*/ 899a6cb015SBarry Smith 909a6cb015SBarry Smith #undef __FUNC__ 919a6cb015SBarry Smith #define __FUNC__ "MatSNESFDMFRegister_Private" 929a6cb015SBarry Smith int MatSNESFDMFRegister_Private(char *sname,char *path,char *name,int (*function)(MatSNESFDMFCtx)) 939a6cb015SBarry Smith { 949a6cb015SBarry Smith int ierr; 959a6cb015SBarry Smith char fullname[256]; 969a6cb015SBarry Smith 979a6cb015SBarry Smith PetscFunctionBegin; 989a6cb015SBarry Smith PetscStrcpy(fullname,path); PetscStrcat(fullname,":");PetscStrcat(fullname,name); 999a6cb015SBarry Smith ierr = FListAdd_Private(&MatSNESFDMFList,sname,fullname,(int (*)(void*))function);CHKERRQ(ierr); 1009a6cb015SBarry Smith PetscFunctionReturn(0); 1019a6cb015SBarry Smith } 1029a6cb015SBarry Smith 1039a6cb015SBarry Smith 1049a6cb015SBarry Smith #undef __FUNC__ 1059a6cb015SBarry Smith #define __FUNC__ "MatSNESFDMFRegisterDestroy" 1069a6cb015SBarry Smith /*@C 1079a6cb015SBarry Smith MatSNESFDMFRegisterDestroy - Frees the list of MatSNESFDMF methods that were 1089a6cb015SBarry Smith registered by MatSNESFDMFRegister(). 1099a6cb015SBarry Smith 1109a6cb015SBarry Smith Not Collective 1119a6cb015SBarry Smith 1129a6cb015SBarry Smith .keywords: MatSNESFDMF, register, destroy 1139a6cb015SBarry Smith 1149a6cb015SBarry Smith .seealso: MatSNESFDMFRegister(), MatSNESFDMFRegisterAll() 1159a6cb015SBarry Smith @*/ 1169a6cb015SBarry Smith int MatSNESFDMFRegisterDestroy(void) 1179a6cb015SBarry Smith { 1189a6cb015SBarry Smith int ierr; 1199a6cb015SBarry Smith 1209a6cb015SBarry Smith PetscFunctionBegin; 1219a6cb015SBarry Smith if (MatSNESFDMFList) { 1229a6cb015SBarry Smith ierr = FListDestroy( MatSNESFDMFList );CHKERRQ(ierr); 1239a6cb015SBarry Smith MatSNESFDMFList = 0; 1249a6cb015SBarry Smith } 1259a6cb015SBarry Smith MatSNESFDMFRegisterAllCalled = 0; 1269a6cb015SBarry Smith PetscFunctionReturn(0); 1279a6cb015SBarry Smith } 1289a6cb015SBarry Smith 1299a6cb015SBarry Smith /* ----------------------------------------------------------------------------------------*/ 130a4d4d686SBarry Smith #undef __FUNC__ 131a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFDestroy_Private" 132a4d4d686SBarry Smith int MatSNESFDMFDestroy_Private(Mat mat) 133a4d4d686SBarry Smith { 134a4d4d686SBarry Smith int ierr; 135a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 136fae171e0SBarry Smith 1373a40ed3dSBarry Smith PetscFunctionBegin; 1380a25c783SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 139b9fa9cd0SBarry Smith ierr = VecDestroy(ctx->w); CHKERRQ(ierr); 1409a6cb015SBarry Smith if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);} 141b4fd4287SBarry Smith if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);} 1429a6cb015SBarry Smith PetscFree(ctx->ops); 143fae171e0SBarry Smith PetscFree(ctx); 1443a40ed3dSBarry Smith PetscFunctionReturn(0); 145b9fa9cd0SBarry Smith } 14650361f65SLois Curfman McInnes 1475615d1e5SSatish Balay #undef __FUNC__ 148a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFView_Private" 14939e2f89bSBarry Smith /* 150a4d4d686SBarry Smith MatSNESFDMFView_Private - Views matrix-free parameters. 1518f6e3e37SBarry Smith 15239e2f89bSBarry Smith */ 153a4d4d686SBarry Smith int MatSNESFDMFView_Private(Mat J,Viewer viewer) 154eb9086c3SLois Curfman McInnes { 155eb9086c3SLois Curfman McInnes int ierr; 156a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 157eb9086c3SLois Curfman McInnes MPI_Comm comm; 158eb9086c3SLois Curfman McInnes FILE *fd; 159eb9086c3SLois Curfman McInnes ViewerType vtype; 160eb9086c3SLois Curfman McInnes 1613a40ed3dSBarry Smith PetscFunctionBegin; 162eb9086c3SLois Curfman McInnes PetscObjectGetComm((PetscObject)J,&comm); 163eb9086c3SLois Curfman McInnes ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 164eb9086c3SLois Curfman McInnes ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 165eb9086c3SLois Curfman McInnes ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 166*3f1db9ecSBarry Smith if (PetscTypeCompare(vtype,ASCII_VIEWER)) { 167eb9086c3SLois Curfman McInnes PetscFPrintf(comm,fd," SNES matrix-free approximation:\n"); 168eb9086c3SLois Curfman McInnes PetscFPrintf(comm,fd," err=%g (relative error in function evaluation)\n",ctx->error_rel); 1699a6cb015SBarry Smith PetscFPrintf(ctx->comm,fd," Using %s compute h routine\n",ctx->type_name); 1709a6cb015SBarry Smith if (ctx->ops->view) { 1719a6cb015SBarry Smith ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr); 1729a6cb015SBarry Smith } 1735cd90555SBarry Smith } else { 1745cd90555SBarry Smith SETERRQ(1,1,"Viewer type not supported for this object"); 175eb9086c3SLois Curfman McInnes } 1763a40ed3dSBarry Smith PetscFunctionReturn(0); 177eb9086c3SLois Curfman McInnes } 178eb9086c3SLois Curfman McInnes 179be726c96SBarry Smith #undef __FUNC__ 180be726c96SBarry Smith #define __FUNC__ "MatSNESFDMFAssemblyEnd_Private" 181be726c96SBarry Smith /* 182be726c96SBarry Smith MatSNESFDMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This 183be726c96SBarry Smith allows the user to indicate the beginning of a new linear solve by call 184be726c96SBarry Smith MatAssemblyXXX() on the matrix free matrix. This then allows the 185be726c96SBarry Smith MatSNESFDMFCreate_WP() to properly compute the || U|| only the first 186be726c96SBarry Smith time in the linear solver rather than every time 187be726c96SBarry Smith 188be726c96SBarry Smith */ 189be726c96SBarry Smith int MatSNESFDMFAssemblyEnd_Private(Mat J) 190be726c96SBarry Smith { 191be726c96SBarry Smith int ierr; 192be726c96SBarry Smith 193be726c96SBarry Smith PetscFunctionBegin; 194be726c96SBarry Smith ierr = MatSNESFDMFResetHHistory(J);CHKERRQ(ierr); 195be726c96SBarry Smith PetscFunctionReturn(0); 196be726c96SBarry Smith } 197be726c96SBarry Smith 198c481317fSBarry Smith 1995615d1e5SSatish Balay #undef __FUNC__ 200a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFMult_Private" 201eb9086c3SLois Curfman McInnes /* 202a4d4d686SBarry Smith MatSNESFDMFMult_Private - Default matrix-free form for Jacobian-vector 203eb9086c3SLois Curfman McInnes product, y = F'(u)*a: 204a4d4d686SBarry Smith 2059a6cb015SBarry Smith y ~= ( F(u + ha) - F(u) )/h, 206eb9086c3SLois Curfman McInnes where F = nonlinear function, as set by SNESSetFunction() 207eb9086c3SLois Curfman McInnes u = current iterate 208eb9086c3SLois Curfman McInnes h = difference interval 209eb9086c3SLois Curfman McInnes */ 210a4d4d686SBarry Smith int MatSNESFDMFMult_Private(Mat mat,Vec a,Vec y) 21139e2f89bSBarry Smith { 212a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 213fae171e0SBarry Smith SNES snes; 214a4d4d686SBarry Smith Scalar h, mone = -1.0; 215fae171e0SBarry Smith Vec w,U,F; 216a305c92eSSatish Balay int ierr, (*eval_fct)(SNES,Vec,Vec)=0; 21739e2f89bSBarry Smith 2183a40ed3dSBarry Smith PetscFunctionBegin; 2199a6cb015SBarry Smith /* We log matrix-free matrix-vector products separately, so that we can 2209a6cb015SBarry Smith separate the performance monitoring from the cases that use conventional 2219a6cb015SBarry Smith storage. We may eventually modify event logging to associate events 2229a6cb015SBarry Smith with particular objects, hence alleviating the more general problem. */ 22356cd22aeSBarry Smith PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0); 22456cd22aeSBarry Smith 2256e38a044SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 226fae171e0SBarry Smith snes = ctx->snes; 227fae171e0SBarry Smith w = ctx->w; 228fae171e0SBarry Smith 22978b31e54SBarry Smith ierr = SNESGetSolution(snes,&U); CHKERRQ(ierr); 23083e56afdSLois Curfman McInnes if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 23183e56afdSLois Curfman McInnes eval_fct = SNESComputeFunction; 23278b31e54SBarry Smith ierr = SNESGetFunction(snes,&F); CHKERRQ(ierr); 233a4d4d686SBarry Smith } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 23483e56afdSLois Curfman McInnes eval_fct = SNESComputeGradient; 23583e56afdSLois Curfman McInnes ierr = SNESGetGradient(snes,&F); CHKERRQ(ierr); 236a4d4d686SBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class"); 23750361f65SLois Curfman McInnes 2389a6cb015SBarry Smith if (!ctx->ops->compute) { 2399a6cb015SBarry Smith ierr = MatSNESFDMFSetType(mat,"default");CHKERRQ(ierr); 2409a6cb015SBarry Smith ierr = MatSNESFDMFSetFromOptions(mat);CHKERRQ(ierr); 2419a6cb015SBarry Smith } 2429a6cb015SBarry Smith ierr = (*ctx->ops->compute)(ctx,U,a,&h); CHKERRQ(ierr); 243a4d4d686SBarry Smith 244a4d4d686SBarry Smith /* keep a record of the current differencing parameter h */ 245a4d4d686SBarry Smith ctx->currenth = h; 246a4d4d686SBarry Smith #if defined(USE_PETSC_COMPLEX) 247a4d4d686SBarry Smith PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscReal(h),PetscImaginary(h)); 248a4d4d686SBarry Smith #else 249a4d4d686SBarry Smith PLogInfo(mat,"Current differencing parameter: %g\n",h); 250a4d4d686SBarry Smith #endif 251a4d4d686SBarry Smith if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) { 252a4d4d686SBarry Smith ctx->historyh[ctx->ncurrenth++] = h; 253be726c96SBarry Smith } else { 254be726c96SBarry Smith ctx->ncurrenth++; 255a4d4d686SBarry Smith } 256a4d4d686SBarry Smith 257a4d4d686SBarry Smith /* Evaluate function at F(u + ha) */ 258a4d4d686SBarry Smith ierr = VecWAXPY(&h,a,U,w); CHKERRQ(ierr); 259a4d4d686SBarry Smith ierr = eval_fct(snes,w,y); CHKERRQ(ierr); 260a4d4d686SBarry Smith 261a4d4d686SBarry Smith ierr = VecAXPY(&mone,F,y); CHKERRQ(ierr); 262a4d4d686SBarry Smith h = 1.0/h; 263a4d4d686SBarry Smith ierr = VecScale(&h,y); CHKERRQ(ierr); 264a4d4d686SBarry Smith if (ctx->sp) {ierr = PCNullSpaceRemove(ctx->sp,y); CHKERRQ(ierr);} 265a4d4d686SBarry Smith 266a4d4d686SBarry Smith PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0); 267a4d4d686SBarry Smith PetscFunctionReturn(0); 268a4d4d686SBarry Smith } 269a4d4d686SBarry Smith 270a4d4d686SBarry Smith #undef __FUNC__ 271a4d4d686SBarry Smith #define __FUNC__ "MatCreateSNESFDMF" 272a4d4d686SBarry Smith /*@C 273a4d4d686SBarry Smith MatCreateSNESFDMF - Creates a matrix-free matrix 274a4d4d686SBarry Smith context for use with a SNES solver. This matrix can be used as 275a4d4d686SBarry Smith the Jacobian argument for the routine SNESSetJacobian(). 276a4d4d686SBarry Smith 277a4d4d686SBarry Smith Collective on SNES and Vec 278a4d4d686SBarry Smith 279a4d4d686SBarry Smith Input Parameters: 280a4d4d686SBarry Smith + snes - the SNES context 281a4d4d686SBarry Smith - x - vector where SNES solution is to be stored. 282a4d4d686SBarry Smith 283a4d4d686SBarry Smith Output Parameter: 284a4d4d686SBarry Smith . J - the matrix-free matrix 285a4d4d686SBarry Smith 286a4d4d686SBarry Smith Notes: 287a4d4d686SBarry Smith The matrix-free matrix context merely contains the function pointers 288a4d4d686SBarry Smith and work space for performing finite difference approximations of 2899a6cb015SBarry Smith Jacobian-vector products, J(u)*a, 2909a6cb015SBarry Smith 2919a6cb015SBarry Smith The default code uses the following approach to compute h 292a4d4d686SBarry Smith 293a4d4d686SBarry Smith .vb 294a4d4d686SBarry Smith J(u)*a = [J(u+h*a) - J(u)]/h where 295a4d4d686SBarry Smith h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 296a4d4d686SBarry Smith = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 297a4d4d686SBarry Smith where 298a4d4d686SBarry Smith error_rel = square root of relative error in function evaluation 299a4d4d686SBarry Smith umin = minimum iterate parameter 300a4d4d686SBarry Smith .ve 301a4d4d686SBarry Smith 3029a6cb015SBarry Smith The user can set the error_rel via MatSNESFDMFSetFunctionError() and 3039a6cb015SBarry Smith umin via MatSNESFDMFDefaultSetUmin() 304a4d4d686SBarry Smith See the nonlinear solvers chapter of the users manual for details. 305a4d4d686SBarry Smith 306a4d4d686SBarry Smith The user should call MatDestroy() when finished with the matrix-free 307a4d4d686SBarry Smith matrix context. 308a4d4d686SBarry Smith 309a4d4d686SBarry Smith Options Database Keys: 310a4d4d686SBarry Smith + -snes_mf_err <error_rel> - Sets error_rel 3119a6cb015SBarry Smith . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 312a4d4d686SBarry Smith - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 313a4d4d686SBarry Smith 314a4d4d686SBarry Smith .keywords: SNES, default, matrix-free, create, matrix 315a4d4d686SBarry Smith 3169a6cb015SBarry Smith .seealso: MatDestroy(), MatSNESFDMFSetFunctionError(), MatSNESFDMFDefaultSetUmin() 317a4d4d686SBarry Smith MatSNESFDMFSetHHistory(), MatSNESFDMFResetHHistory(), 3189a6cb015SBarry Smith MatSNESFDMFGetH(),MatSNESFDMFKSPMonitor(), MatSNESFDMFRegister() 319a4d4d686SBarry Smith 320a4d4d686SBarry Smith @*/ 321a4d4d686SBarry Smith int MatCreateSNESFDMF(SNES snes,Vec x, Mat *J) 322a4d4d686SBarry Smith { 323a4d4d686SBarry Smith MPI_Comm comm; 324a4d4d686SBarry Smith MatSNESFDMFCtx mfctx; 3259a6cb015SBarry Smith int n, nloc, ierr; 326a4d4d686SBarry Smith 327a4d4d686SBarry Smith PetscFunctionBegin; 328a4d4d686SBarry Smith mfctx = (MatSNESFDMFCtx) PetscMalloc(sizeof(struct _p_MatSNESFDMFCtx)); CHKPTRQ(mfctx); 329a4d4d686SBarry Smith PLogObjectMemory(snes,sizeof(MatSNESFDMFCtx)); 3309a6cb015SBarry Smith mfctx->comm = snes->comm; 331a4d4d686SBarry Smith mfctx->sp = 0; 332a4d4d686SBarry Smith mfctx->snes = snes; 333a4d4d686SBarry Smith mfctx->error_rel = 1.e-8; /* assumes double precision */ 334a4d4d686SBarry Smith mfctx->currenth = 0.0; 335a4d4d686SBarry Smith mfctx->historyh = PETSC_NULL; 336a4d4d686SBarry Smith mfctx->ncurrenth = 0; 337a4d4d686SBarry Smith mfctx->maxcurrenth = 0; 338a4d4d686SBarry Smith 3399a6cb015SBarry Smith /* 3409a6cb015SBarry Smith Create the empty data structure to contain compute-h routines. 3419a6cb015SBarry Smith These will be filled in below from the command line options or 3429a6cb015SBarry Smith a later call with MatSNESFDMFSetType() or if that is not called 3439a6cb015SBarry Smith then it will default in the first use of MatSNESFDMFMult_private() 3449a6cb015SBarry Smith */ 3459a6cb015SBarry Smith mfctx->ops = (MFOps *)PetscMalloc(sizeof(MFOps)); CHKPTRQ(mfctx->ops); 3469a6cb015SBarry Smith mfctx->ops->compute = 0; 3479a6cb015SBarry Smith mfctx->ops->destroy = 0; 3489a6cb015SBarry Smith mfctx->ops->view = 0; 3499a6cb015SBarry Smith mfctx->ops->printhelp = 0; 3509a6cb015SBarry Smith mfctx->ops->setfromoptions = 0; 3519a6cb015SBarry Smith mfctx->hctx = 0; 3529a6cb015SBarry Smith 353a4d4d686SBarry Smith ierr = VecDuplicate(x,&mfctx->w); CHKERRQ(ierr); 354a4d4d686SBarry Smith ierr = PetscObjectGetComm((PetscObject)x,&comm); CHKERRQ(ierr); 355a4d4d686SBarry Smith ierr = VecGetSize(x,&n); CHKERRQ(ierr); 356a4d4d686SBarry Smith ierr = VecGetLocalSize(x,&nloc); CHKERRQ(ierr); 357a4d4d686SBarry Smith ierr = MatCreateShell(comm,nloc,n,n,n,mfctx,J); CHKERRQ(ierr); 358a4d4d686SBarry Smith ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESFDMFMult_Private);CHKERRQ(ierr); 359a4d4d686SBarry Smith ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESFDMFDestroy_Private);CHKERRQ(ierr); 360a4d4d686SBarry Smith ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESFDMFView_Private); CHKERRQ(ierr); 361be726c96SBarry Smith ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESFDMFAssemblyEnd_Private);CHKERRQ(ierr); 362a4d4d686SBarry Smith PLogObjectParent(*J,mfctx->w); 363a4d4d686SBarry Smith PLogObjectParent(snes,*J); 3649a6cb015SBarry Smith 3659a6cb015SBarry Smith mfctx->mat = *J; 3669a6cb015SBarry Smith 3679a6cb015SBarry Smith 3689a6cb015SBarry Smith PetscFunctionReturn(0); 3699a6cb015SBarry Smith } 3709a6cb015SBarry Smith 3719a6cb015SBarry Smith #undef __FUNC__ 3729a6cb015SBarry Smith #define __FUNC__ "MatSNESFDMFGetH" 3739a6cb015SBarry Smith /*@ 3749a6cb015SBarry Smith MatSNESFDMFSetFromOptions - Sets the MatSNESFDMF options from the command line 3759a6cb015SBarry Smith parameter. 3769a6cb015SBarry Smith 3779a6cb015SBarry Smith Collective on Mat 3789a6cb015SBarry Smith 3799a6cb015SBarry Smith Input Parameters: 3809a6cb015SBarry Smith . mat - the matrix obtained with MatCreateSNESFDMF() 3819a6cb015SBarry Smith 3829a6cb015SBarry Smith .keywords: SNES, matrix-free, parameters 3839a6cb015SBarry Smith 3849a6cb015SBarry Smith .seealso: MatCreateSNESFDMF(),MatSNESFDMFSetHHistory(), 3859a6cb015SBarry Smith MatSNESFDMFResetHHistory(),MatSNESFDMFKSPMonitor() 3869a6cb015SBarry Smith @*/ 3879a6cb015SBarry Smith int MatSNESFDMFSetFromOptions(Mat mat) 3889a6cb015SBarry Smith { 3899a6cb015SBarry Smith MatSNESFDMFCtx mfctx; 3909a6cb015SBarry Smith int ierr,flg; 3919a6cb015SBarry Smith char ftype[256],p[64]; 3929a6cb015SBarry Smith 3939a6cb015SBarry Smith PetscFunctionBegin; 3949a6cb015SBarry Smith ierr = MatShellGetContext(mat,(void **)&mfctx); CHKERRQ(ierr); 3959a6cb015SBarry Smith if (mfctx) { 3969a6cb015SBarry Smith /* allow user to set the type */ 3979a6cb015SBarry Smith ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr); 3989a6cb015SBarry Smith if (flg) { 3999a6cb015SBarry Smith ierr = MatSNESFDMFSetType(mat,ftype);CHKERRQ(ierr); 4009a6cb015SBarry Smith } 4019a6cb015SBarry Smith 4029a6cb015SBarry Smith ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg);CHKERRQ(ierr); 4039a6cb015SBarry Smith if (mfctx->ops->setfromoptions) { 4049a6cb015SBarry Smith ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 4059a6cb015SBarry Smith } 4069a6cb015SBarry Smith 4079a6cb015SBarry Smith ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr); 4089a6cb015SBarry Smith PetscStrcpy(p,"-"); 4099a6cb015SBarry Smith if (mfctx->snes->prefix) PetscStrcat(p,mfctx->snes->prefix); 4109a6cb015SBarry Smith if (flg) { 4119a6cb015SBarry Smith (*PetscHelpPrintf)(mfctx->snes->comm," %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel); 4129a6cb015SBarry Smith if (mfctx->ops->printhelp) { 4139a6cb015SBarry Smith (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr); 4149a6cb015SBarry Smith } 4159a6cb015SBarry Smith } 4169a6cb015SBarry Smith } 417a4d4d686SBarry Smith PetscFunctionReturn(0); 418a4d4d686SBarry Smith } 419a4d4d686SBarry Smith 420a4d4d686SBarry Smith #undef __FUNC__ 421a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFGetH" 422a4d4d686SBarry Smith /*@ 423a4d4d686SBarry Smith MatSNESFDMFGetH - Gets the last h that was used as the differencing 424a4d4d686SBarry Smith parameter. 425a4d4d686SBarry Smith 426a4d4d686SBarry Smith Not Collective 427a4d4d686SBarry Smith 428a4d4d686SBarry Smith Input Parameters: 429a4d4d686SBarry Smith . mat - the matrix obtained with MatCreateSNESFDMF() 430a4d4d686SBarry Smith 431a4d4d686SBarry Smith Output Paramter: 432a4d4d686SBarry Smith . h - the differencing step size 433a4d4d686SBarry Smith 434a4d4d686SBarry Smith .keywords: SNES, matrix-free, parameters 435a4d4d686SBarry Smith 436a4d4d686SBarry Smith .seealso: MatCreateSNESFDMF(),MatSNESFDMFSetHHistory(), 437a4d4d686SBarry Smith MatSNESFDMFResetHHistory(),MatSNESFDMFKSPMonitor() 438a4d4d686SBarry Smith @*/ 439a4d4d686SBarry Smith int MatSNESFDMFGetH(Mat mat,Scalar *h) 440a4d4d686SBarry Smith { 441a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 442a4d4d686SBarry Smith int ierr; 443a4d4d686SBarry Smith 444a4d4d686SBarry Smith PetscFunctionBegin; 445a4d4d686SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 446a4d4d686SBarry Smith if (ctx) { 447a4d4d686SBarry Smith *h = ctx->currenth; 448a4d4d686SBarry Smith } 449a4d4d686SBarry Smith PetscFunctionReturn(0); 450a4d4d686SBarry Smith } 451a4d4d686SBarry Smith 452a4d4d686SBarry Smith #undef __FUNC__ 453a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFKSPMonitor" 454a4d4d686SBarry Smith /* 455a4d4d686SBarry Smith MatSNESFDMFKSPMonitor - A KSP monitor for use with the default PETSc 456a4d4d686SBarry Smith SNES matrix free routines. Prints the h differencing parameter used at each 457a4d4d686SBarry Smith timestep. 458a4d4d686SBarry Smith 459a4d4d686SBarry Smith */ 460a4d4d686SBarry Smith int MatSNESFDMFKSPMonitor(KSP ksp,int n,double rnorm,void *dummy) 461a4d4d686SBarry Smith { 462a4d4d686SBarry Smith PC pc; 463a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 464a4d4d686SBarry Smith int ierr; 465a4d4d686SBarry Smith Mat mat; 466a4d4d686SBarry Smith MPI_Comm comm; 467a4d4d686SBarry Smith PetscTruth nonzeroinitialguess; 468a4d4d686SBarry Smith 469a4d4d686SBarry Smith PetscFunctionBegin; 470a4d4d686SBarry Smith ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 471a4d4d686SBarry Smith ierr = KSPGetPC(ksp,&pc); CHKERRQ(ierr); 472a4d4d686SBarry Smith ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 473a4d4d686SBarry Smith ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr); 474a4d4d686SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 4759a6cb015SBarry Smith if (!ctx) { 4769a6cb015SBarry Smith SETERRQ(1,1,"Matrix is not a matrix free shell matrix"); 4779a6cb015SBarry Smith } 478a4d4d686SBarry Smith if (n > 0 || nonzeroinitialguess) { 479a4d4d686SBarry Smith #if defined(USE_PETSC_COMPLEX) 480a4d4d686SBarry Smith PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 481a4d4d686SBarry Smith PetscReal(ctx->currenth),PetscImaginary(ctx->currenth)); 482a4d4d686SBarry Smith #else 483a4d4d686SBarry Smith PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth); 484a4d4d686SBarry Smith #endif 485a4d4d686SBarry Smith } else { 486a4d4d686SBarry Smith PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm); 487a4d4d686SBarry Smith } 488a4d4d686SBarry Smith PetscFunctionReturn(0); 489a4d4d686SBarry Smith } 490a4d4d686SBarry Smith 491a4d4d686SBarry Smith #undef __FUNC__ 4929a6cb015SBarry Smith #define __FUNC__ "MatSNESFDMFSetFunctionError" 493a4d4d686SBarry Smith /*@ 4949a6cb015SBarry Smith MatSNESFDMFSetFunctionError - Sets the error_rel for the approximation of 495a4d4d686SBarry Smith matrix-vector products using finite differences. 496a4d4d686SBarry Smith 497a4d4d686SBarry Smith Collective on Mat 498a4d4d686SBarry Smith 499a4d4d686SBarry Smith Input Parameters: 500a4d4d686SBarry Smith + mat - the matrix free matrix created via MatCreateSNESFDMF() 5019a6cb015SBarry Smith - error_rel - relative error (should be set to the square root of 502a4d4d686SBarry Smith the relative error in the function evaluations) 503a4d4d686SBarry Smith 504a4d4d686SBarry Smith Notes: 505a4d4d686SBarry Smith The default matrix-free matrix-vector product routine computes 506a4d4d686SBarry Smith .vb 507a4d4d686SBarry Smith J(u)*a = [J(u+h*a) - J(u)]/h where 508a4d4d686SBarry Smith h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 509a4d4d686SBarry Smith = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 510a4d4d686SBarry Smith .ve 511a4d4d686SBarry Smith 512a4d4d686SBarry Smith Options Database Keys: 513a4d4d686SBarry Smith + -snes_mf_err <error_rel> - Sets error_rel 514a4d4d686SBarry Smith 515a4d4d686SBarry Smith .keywords: SNES, matrix-free, parameters 516a4d4d686SBarry Smith 517a4d4d686SBarry Smith .seealso: MatCreateSNESFDMF(),MatSNESFDMFGetH(), 518a4d4d686SBarry Smith MatSNESFDMFSetHHistory(), MatSNESFDMFResetHHistory(), 519a4d4d686SBarry Smith MatSNESFDMFKSPMonitor() 520a4d4d686SBarry Smith @*/ 5219a6cb015SBarry Smith int MatSNESFDMFSetFunctionError(Mat mat,double error) 522a4d4d686SBarry Smith { 523a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 524a4d4d686SBarry Smith int ierr; 525a4d4d686SBarry Smith 526a4d4d686SBarry Smith PetscFunctionBegin; 527a4d4d686SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 528a4d4d686SBarry Smith if (ctx) { 529a4d4d686SBarry Smith if (error != PETSC_DEFAULT) ctx->error_rel = error; 530a4d4d686SBarry Smith } 531a4d4d686SBarry Smith PetscFunctionReturn(0); 532a4d4d686SBarry Smith } 533a4d4d686SBarry Smith 534a4d4d686SBarry Smith #undef __FUNC__ 535a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFAddNullSpace" 536a4d4d686SBarry Smith /*@ 537a4d4d686SBarry Smith MatSNESFDMFAddNullSpace - Provides a null space that 538a4d4d686SBarry Smith an operator is supposed to have. Since roundoff will create a 539a4d4d686SBarry Smith small component in the null space, if you know the null space 540a4d4d686SBarry Smith you may have it automatically removed. 541a4d4d686SBarry Smith 542a4d4d686SBarry Smith Collective on Mat 543a4d4d686SBarry Smith 544a4d4d686SBarry Smith Input Parameters: 545a4d4d686SBarry Smith + J - the matrix-free matrix context 546a4d4d686SBarry Smith . has_cnst - PETSC_TRUE or PETSC_FALSE, indicating if null space has constants 547a4d4d686SBarry Smith . n - number of vectors (excluding constant vector) in null space 548a4d4d686SBarry Smith - vecs - the vectors that span the null space (excluding the constant vector); 549a4d4d686SBarry Smith these vectors must be orthonormal 550a4d4d686SBarry Smith 551a4d4d686SBarry Smith .keywords: SNES, matrix-free, null space 552a4d4d686SBarry Smith 553a4d4d686SBarry Smith .seealso: MatSNESFDMFGetH(), MatCreateSNESFDMF(), 554a4d4d686SBarry Smith MatSNESFDMFSetHHistory(), MatSNESFDMFResetHHistory(), 5559a6cb015SBarry Smith MatSNESFDMFKSPMonitor(), MatSNESFDMFErrorRel() 556a4d4d686SBarry Smith 557a4d4d686SBarry Smith @*/ 558a4d4d686SBarry Smith int MatSNESFDMFAddNullSpace(Mat J,int has_cnst,int n,Vec *vecs) 559a4d4d686SBarry Smith { 560a4d4d686SBarry Smith int ierr; 561a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 562a4d4d686SBarry Smith MPI_Comm comm; 563a4d4d686SBarry Smith 564a4d4d686SBarry Smith PetscFunctionBegin; 565a4d4d686SBarry Smith PetscObjectGetComm((PetscObject)J,&comm); 566a4d4d686SBarry Smith 567a4d4d686SBarry Smith ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 568a4d4d686SBarry Smith /* no context indicates that it is not the "matrix free" matrix type */ 569a4d4d686SBarry Smith if (!ctx) PetscFunctionReturn(0); 570a4d4d686SBarry Smith ierr = PCNullSpaceCreate(comm,has_cnst,n,vecs,&ctx->sp); CHKERRQ(ierr); 571a4d4d686SBarry Smith PetscFunctionReturn(0); 572a4d4d686SBarry Smith } 573a4d4d686SBarry Smith 574a4d4d686SBarry Smith #undef __FUNC__ 575a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFSetHHistory" 576a4d4d686SBarry Smith /*@ 577a4d4d686SBarry Smith MatSNESFDMFSetHHistory - Sets an array to collect a history 578a4d4d686SBarry Smith of the differencing values h computed for the matrix free product 579a4d4d686SBarry Smith 580a4d4d686SBarry Smith Collective on Mat 581a4d4d686SBarry Smith 582a4d4d686SBarry Smith Input Parameters: 583a4d4d686SBarry Smith + J - the matrix-free matrix context 584a4d4d686SBarry Smith . histroy - space to hold the h history 585a4d4d686SBarry Smith - nhistory - number of entries in history, if more h are generated than 586a4d4d686SBarry Smith nhistory the later ones are discarded 587a4d4d686SBarry Smith 588a4d4d686SBarry Smith Notes: 589a4d4d686SBarry Smith Use MatSNESFDMFResetHHistory() to reset the history counter 590a4d4d686SBarry Smith and collect a new batch of h. 591a4d4d686SBarry Smith 592a4d4d686SBarry Smith .keywords: SNES, matrix-free, h history, differencing history 593a4d4d686SBarry Smith 594a4d4d686SBarry Smith .seealso: MatSNESFDMFGetH(), MatCreateSNESFDMF(), 595a4d4d686SBarry Smith MatSNESFDMFResetHHistory(), 5969a6cb015SBarry Smith MatSNESFDMFKSPMonitor(), MatSNESFDMFSetFunctionError() 597a4d4d686SBarry Smith 598a4d4d686SBarry Smith @*/ 599a4d4d686SBarry Smith int MatSNESFDMFSetHHistory(Mat J,Scalar *history,int nhistory) 600a4d4d686SBarry Smith { 601a4d4d686SBarry Smith int ierr; 602a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 603a4d4d686SBarry Smith 604a4d4d686SBarry Smith PetscFunctionBegin; 605a4d4d686SBarry Smith 606a4d4d686SBarry Smith ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 607a4d4d686SBarry Smith /* no context indicates that it is not the "matrix free" matrix type */ 608a4d4d686SBarry Smith if (!ctx) PetscFunctionReturn(0); 609a4d4d686SBarry Smith ctx->historyh = history; 610a4d4d686SBarry Smith ctx->maxcurrenth = nhistory; 611a4d4d686SBarry Smith ctx->currenth = 0; 612a4d4d686SBarry Smith 613a4d4d686SBarry Smith PetscFunctionReturn(0); 614a4d4d686SBarry Smith } 615a4d4d686SBarry Smith 616a4d4d686SBarry Smith #undef __FUNC__ 617a4d4d686SBarry Smith #define __FUNC__ "MatSNESFDMFResetHHistory" 618a4d4d686SBarry Smith /*@ 619a4d4d686SBarry Smith MatSNESFDMFResetHHistory - Resets the counter to zero to begin 620a4d4d686SBarry Smith collecting a new set of differencing histories. 621a4d4d686SBarry Smith 622a4d4d686SBarry Smith Collective on Mat 623a4d4d686SBarry Smith 624a4d4d686SBarry Smith Input Parameters: 625a4d4d686SBarry Smith . J - the matrix-free matrix context 626a4d4d686SBarry Smith 627a4d4d686SBarry Smith Notes: 628a4d4d686SBarry Smith Use MatSNESFDMFSetHHistory() to create the original history counter 629a4d4d686SBarry Smith 630a4d4d686SBarry Smith .keywords: SNES, matrix-free, h history, differencing history 631a4d4d686SBarry Smith 632a4d4d686SBarry Smith .seealso: MatSNESFDMFGetH(), MatCreateSNESFDMF(), 633a4d4d686SBarry Smith MatSNESFDMFSetHHistory(), 6349a6cb015SBarry Smith MatSNESFDMFKSPMonitor(), MatSNESFDMFSetFunctionError() 635a4d4d686SBarry Smith 636a4d4d686SBarry Smith @*/ 637a4d4d686SBarry Smith int MatSNESFDMFResetHHistory(Mat J) 638a4d4d686SBarry Smith { 639a4d4d686SBarry Smith int ierr; 640a4d4d686SBarry Smith MatSNESFDMFCtx ctx; 641a4d4d686SBarry Smith 642a4d4d686SBarry Smith PetscFunctionBegin; 643a4d4d686SBarry Smith 644a4d4d686SBarry Smith ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 645a4d4d686SBarry Smith /* no context indicates that it is not the "matrix free" matrix type */ 646a4d4d686SBarry Smith if (!ctx) PetscFunctionReturn(0); 647be726c96SBarry Smith ctx->ncurrenth = 0; 648a4d4d686SBarry Smith 649a4d4d686SBarry Smith PetscFunctionReturn(0); 650a4d4d686SBarry Smith } 651a4d4d686SBarry Smith 652