1*cf57b110SBarry Smith /*$Id: snesmfj.c,v 1.123 2001/06/21 21:18:42 bsmith Exp bsmith $*/ 281e6777dSBarry Smith 39a6cb015SBarry Smith #include "src/snes/snesimpl.h" 4e090d566SSatish Balay #include "src/snes/mf/snesmfj.h" /*I "petscsnes.h" I*/ 581e6777dSBarry Smith 6b0a32e0cSBarry Smith PetscFList MatSNESMPetscFList = 0; 74c49b128SBarry Smith PetscTruth MatSNESMFRegisterAllCalled = PETSC_FALSE; 8a4d4d686SBarry Smith 94a2ae208SSatish Balay #undef __FUNCT__ 104a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetType" 11fd4bdd07SBarry Smith /*@C 1265f2ba5bSLois Curfman McInnes MatSNESMFSetType - Sets the method that is used to compute the 13b0a32e0cSBarry Smith differencing parameter for finite differene matrix-free formulations. 149a6cb015SBarry Smith 159a6cb015SBarry Smith Input Parameters: 16ef4ad1fdSLois Curfman McInnes + mat - the "matrix-free" matrix created via MatCreateSNESMF() 179a6cb015SBarry Smith - ftype - the type requested 189a6cb015SBarry Smith 1915091d37SBarry Smith Level: advanced 2015091d37SBarry Smith 2165f2ba5bSLois Curfman McInnes Notes: 2265f2ba5bSLois Curfman McInnes For example, such routines can compute h for use in 2365f2ba5bSLois Curfman McInnes Jacobian-vector products of the form 2465f2ba5bSLois Curfman McInnes 2565f2ba5bSLois Curfman McInnes F(x+ha) - F(x) 26ef4ad1fdSLois Curfman McInnes F'(u)a ~= ---------------- 2765f2ba5bSLois Curfman McInnes h 2865f2ba5bSLois Curfman McInnes 29f1af5d2fSBarry Smith .seealso: MatCreateSNESMF(), MatSNESMFRegisterDynamic) 309a6cb015SBarry Smith @*/ 31f6a0df18SBarry Smith int MatSNESMFSetType(Mat mat,MatSNESMFType ftype) 32b9fa9cd0SBarry Smith { 335a655dc6SBarry Smith int ierr,(*r)(MatSNESMFCtx); 345a655dc6SBarry Smith MatSNESMFCtx ctx; 356831982aSBarry Smith PetscTruth match; 36a4d4d686SBarry Smith 37a4d4d686SBarry Smith PetscFunctionBegin; 380f5bd95cSBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 390f5bd95cSBarry Smith PetscValidCharPointer(ftype); 400f5bd95cSBarry Smith 41a4d4d686SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 42a4d4d686SBarry Smith 439a6cb015SBarry Smith /* already set, so just return */ 446831982aSBarry Smith ierr = PetscTypeCompare((PetscObject)ctx,ftype,&match);CHKERRQ(ierr); 450f5bd95cSBarry Smith if (match) PetscFunctionReturn(0); 46a4d4d686SBarry Smith 479a6cb015SBarry Smith /* destroy the old one if it exists */ 489a6cb015SBarry Smith if (ctx->ops->destroy) { 499a6cb015SBarry Smith ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr); 509a6cb015SBarry Smith } 519a6cb015SBarry Smith 5265f2ba5bSLois Curfman McInnes /* Get the function pointers for the requrested method */ 535a655dc6SBarry Smith if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 549a6cb015SBarry Smith 55b9617806SBarry Smith ierr = PetscFListFind(ctx->comm,MatSNESMPetscFList,ftype,(void (**)(void)) &r);CHKERRQ(ierr); 569a6cb015SBarry Smith 5729bbc08cSBarry Smith if (!r) SETERRQ(1,"Unknown MatSNESMF type given"); 589a6cb015SBarry Smith 599a6cb015SBarry Smith ierr = (*r)(ctx);CHKERRQ(ierr); 606831982aSBarry Smith 616831982aSBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)ctx,ftype);CHKERRQ(ierr); 629a6cb015SBarry Smith 639a6cb015SBarry Smith PetscFunctionReturn(0); 649a6cb015SBarry Smith } 659a6cb015SBarry Smith 669a6cb015SBarry Smith /*MC 67f1af5d2fSBarry Smith MatSNESMFRegisterDynamic - Adds a method to the MatSNESMF registry. 689a6cb015SBarry Smith 699a6cb015SBarry Smith Synopsis: 70fed8bd04SBarry Smith int MatSNESMFRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESMF)) 719a6cb015SBarry Smith 729a6cb015SBarry Smith Not Collective 739a6cb015SBarry Smith 749a6cb015SBarry Smith Input Parameters: 759a6cb015SBarry Smith + name_solver - name of a new user-defined compute-h module 769a6cb015SBarry Smith . path - path (either absolute or relative) the library containing this solver 779a6cb015SBarry Smith . name_create - name of routine to create method context 789a6cb015SBarry Smith - routine_create - routine to create method context 799a6cb015SBarry Smith 8015091d37SBarry Smith Level: developer 8115091d37SBarry Smith 829a6cb015SBarry Smith Notes: 83f1af5d2fSBarry Smith MatSNESMFRegisterDynamic) may be called multiple times to add several user-defined solvers. 849a6cb015SBarry Smith 859a6cb015SBarry Smith If dynamic libraries are used, then the fourth input argument (routine_create) 869a6cb015SBarry Smith is ignored. 879a6cb015SBarry Smith 889a6cb015SBarry Smith Sample usage: 899a6cb015SBarry Smith .vb 90f1af5d2fSBarry Smith MatSNESMFRegisterDynamic"my_h",/home/username/my_lib/lib/libO/solaris/mylib.a, 919a6cb015SBarry Smith "MyHCreate",MyHCreate); 929a6cb015SBarry Smith .ve 939a6cb015SBarry Smith 949a6cb015SBarry Smith Then, your solver can be chosen with the procedural interface via 955a655dc6SBarry Smith $ MatSNESMFSetType(mfctx,"my_h") 969a6cb015SBarry Smith or at runtime via the option 979a6cb015SBarry Smith $ -snes_mf_type my_h 989a6cb015SBarry Smith 995a655dc6SBarry Smith .keywords: MatSNESMF, register 1009a6cb015SBarry Smith 1015a655dc6SBarry Smith .seealso: MatSNESMFRegisterAll(), MatSNESMFRegisterDestroy() 1029a6cb015SBarry Smith M*/ 1039a6cb015SBarry Smith 1044a2ae208SSatish Balay #undef __FUNCT__ 1054a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFRegister" 106f1af5d2fSBarry Smith int MatSNESMFRegister(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx)) 1079a6cb015SBarry Smith { 1089a6cb015SBarry Smith int ierr; 1099a6cb015SBarry Smith char fullname[256]; 1109a6cb015SBarry Smith 1119a6cb015SBarry Smith PetscFunctionBegin; 112b0a32e0cSBarry Smith ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 113b9617806SBarry Smith ierr = PetscFListAdd(&MatSNESMPetscFList,sname,fullname,(void (*)())function);CHKERRQ(ierr); 1149a6cb015SBarry Smith PetscFunctionReturn(0); 1159a6cb015SBarry Smith } 1169a6cb015SBarry Smith 1179a6cb015SBarry Smith 1184a2ae208SSatish Balay #undef __FUNCT__ 1194a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFRegisterDestroy" 1209a6cb015SBarry Smith /*@C 1215a655dc6SBarry Smith MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were 122f1af5d2fSBarry Smith registered by MatSNESMFRegisterDynamic). 1239a6cb015SBarry Smith 1249a6cb015SBarry Smith Not Collective 1259a6cb015SBarry Smith 12615091d37SBarry Smith Level: developer 12715091d37SBarry Smith 1285a655dc6SBarry Smith .keywords: MatSNESMF, register, destroy 1299a6cb015SBarry Smith 130f1af5d2fSBarry Smith .seealso: MatSNESMFRegisterDynamic), MatSNESMFRegisterAll() 1319a6cb015SBarry Smith @*/ 1325a655dc6SBarry Smith int MatSNESMFRegisterDestroy(void) 1339a6cb015SBarry Smith { 1349a6cb015SBarry Smith int ierr; 1359a6cb015SBarry Smith 1369a6cb015SBarry Smith PetscFunctionBegin; 137b0a32e0cSBarry Smith if (MatSNESMPetscFList) { 138b0a32e0cSBarry Smith ierr = PetscFListDestroy(&MatSNESMPetscFList);CHKERRQ(ierr); 139b0a32e0cSBarry Smith MatSNESMPetscFList = 0; 1409a6cb015SBarry Smith } 1414c49b128SBarry Smith MatSNESMFRegisterAllCalled = PETSC_FALSE; 1429a6cb015SBarry Smith PetscFunctionReturn(0); 1439a6cb015SBarry Smith } 1449a6cb015SBarry Smith 1459a6cb015SBarry Smith /* ----------------------------------------------------------------------------------------*/ 1464a2ae208SSatish Balay #undef __FUNCT__ 1474a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFDestroy_Private" 1485a655dc6SBarry Smith int MatSNESMFDestroy_Private(Mat mat) 149a4d4d686SBarry Smith { 150a4d4d686SBarry Smith int ierr; 1515a655dc6SBarry Smith MatSNESMFCtx ctx; 152fae171e0SBarry Smith 1533a40ed3dSBarry Smith PetscFunctionBegin; 1540a25c783SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 155b9fa9cd0SBarry Smith ierr = VecDestroy(ctx->w);CHKERRQ(ierr); 1569a6cb015SBarry Smith if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);} 15774637425SBarry Smith if (ctx->sp) {ierr = MatNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);} 1586831982aSBarry Smith PetscHeaderDestroy(ctx); 1593a40ed3dSBarry Smith PetscFunctionReturn(0); 160b9fa9cd0SBarry Smith } 16150361f65SLois Curfman McInnes 1624a2ae208SSatish Balay #undef __FUNCT__ 1634a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFView_Private" 16439e2f89bSBarry Smith /* 1655a655dc6SBarry Smith MatSNESMFView_Private - Views matrix-free parameters. 1668f6e3e37SBarry Smith 16739e2f89bSBarry Smith */ 168b0a32e0cSBarry Smith int MatSNESMFView_Private(Mat J,PetscViewer viewer) 169eb9086c3SLois Curfman McInnes { 170eb9086c3SLois Curfman McInnes int ierr; 1715a655dc6SBarry Smith MatSNESMFCtx ctx; 1726831982aSBarry Smith PetscTruth isascii; 173eb9086c3SLois Curfman McInnes 1743a40ed3dSBarry Smith PetscFunctionBegin; 175eb9086c3SLois Curfman McInnes ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 176b0a32e0cSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr); 1770f5bd95cSBarry Smith if (isascii) { 178b0a32e0cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," SNES matrix-free approximation:\n");CHKERRQ(ierr); 179b0a32e0cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," err=%g (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr); 180473c83c3SBarry Smith if (!ctx->type_name) { 181b0a32e0cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," The compute h routine has not yet been set\n");CHKERRQ(ierr); 182473c83c3SBarry Smith } else { 183b0a32e0cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using %s compute h routine\n",ctx->type_name);CHKERRQ(ierr); 184473c83c3SBarry Smith } 1859a6cb015SBarry Smith if (ctx->ops->view) { 1869a6cb015SBarry Smith ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr); 1879a6cb015SBarry Smith } 1885cd90555SBarry Smith } else { 18929bbc08cSBarry Smith SETERRQ1(1,"Viewer type %s not supported for SNES matrix free matrix",((PetscObject)viewer)->type_name); 190eb9086c3SLois Curfman McInnes } 1913a40ed3dSBarry Smith PetscFunctionReturn(0); 192eb9086c3SLois Curfman McInnes } 193eb9086c3SLois Curfman McInnes 1944a2ae208SSatish Balay #undef __FUNCT__ 1954a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFAssemblyEnd_Private" 196be726c96SBarry Smith /* 1975a655dc6SBarry Smith MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This 19865f2ba5bSLois Curfman McInnes allows the user to indicate the beginning of a new linear solve by calling 199be726c96SBarry Smith MatAssemblyXXX() on the matrix free matrix. This then allows the 20065f2ba5bSLois Curfman McInnes MatSNESMFCreate_WP() to properly compute ||U|| only the first time 20165f2ba5bSLois Curfman McInnes in the linear solver rather than every time. 202be726c96SBarry Smith */ 2035a655dc6SBarry Smith int MatSNESMFAssemblyEnd_Private(Mat J) 204be726c96SBarry Smith { 205be726c96SBarry Smith int ierr; 2061d1367b7SBarry Smith MatSNESMFCtx j; 207be726c96SBarry Smith 208be726c96SBarry Smith PetscFunctionBegin; 2095a655dc6SBarry Smith ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr); 2101d1367b7SBarry Smith ierr = MatShellGetContext(J,(void **)&j);CHKERRQ(ierr); 211b0a32e0cSBarry Smith if (j->usesnes) { 2121d1367b7SBarry Smith ierr = SNESGetSolution(j->snes,&j->current_u);CHKERRQ(ierr); 2131d1367b7SBarry Smith if (j->snes->method_class == SNES_NONLINEAR_EQUATIONS) { 2141d1367b7SBarry Smith ierr = SNESGetFunction(j->snes,&j->current_f,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 2151d1367b7SBarry Smith } else if (j->snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 2161d1367b7SBarry Smith ierr = SNESGetGradient(j->snes,&j->current_f,PETSC_NULL);CHKERRQ(ierr); 21729bbc08cSBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class"); 2181d1367b7SBarry Smith } 219be726c96SBarry Smith PetscFunctionReturn(0); 220be726c96SBarry Smith } 221be726c96SBarry Smith 2224a2ae208SSatish Balay #undef __FUNCT__ 2234a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFMult_Private" 224eb9086c3SLois Curfman McInnes /* 2255a655dc6SBarry Smith MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector 226eb9086c3SLois Curfman McInnes product, y = F'(u)*a: 227a4d4d686SBarry Smith 2289a6cb015SBarry Smith y ~= (F(u + ha) - F(u))/h, 229eb9086c3SLois Curfman McInnes where F = nonlinear function, as set by SNESSetFunction() 230eb9086c3SLois Curfman McInnes u = current iterate 231eb9086c3SLois Curfman McInnes h = difference interval 232eb9086c3SLois Curfman McInnes */ 2335a655dc6SBarry Smith int MatSNESMFMult_Private(Mat mat,Vec a,Vec y) 23439e2f89bSBarry Smith { 2355a655dc6SBarry Smith MatSNESMFCtx ctx; 236fae171e0SBarry Smith SNES snes; 237a4d4d686SBarry Smith Scalar h,mone = -1.0; 238fae171e0SBarry Smith Vec w,U,F; 239a305c92eSSatish Balay int ierr,(*eval_fct)(SNES,Vec,Vec)=0; 24039e2f89bSBarry Smith 2413a40ed3dSBarry Smith PetscFunctionBegin; 2429a6cb015SBarry Smith /* We log matrix-free matrix-vector products separately, so that we can 2439a6cb015SBarry Smith separate the performance monitoring from the cases that use conventional 2449a6cb015SBarry Smith storage. We may eventually modify event logging to associate events 2459a6cb015SBarry Smith with particular objects, hence alleviating the more general problem. */ 246b0a32e0cSBarry Smith ierr = PetscLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);CHKERRQ(ierr); 24756cd22aeSBarry Smith 2486e38a044SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 249fae171e0SBarry Smith snes = ctx->snes; 250fae171e0SBarry Smith w = ctx->w; 2511d1367b7SBarry Smith U = ctx->current_u; 25250361f65SLois Curfman McInnes 25385614651SBarry Smith /* 25485614651SBarry Smith Compute differencing parameter 25585614651SBarry Smith */ 2569a6cb015SBarry Smith if (!ctx->ops->compute) { 257b7fd4e64SBarry Smith ierr = MatSNESMFSetType(mat,MATSNESMF_DEFAULT);CHKERRQ(ierr); 2585a655dc6SBarry Smith ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr); 2599a6cb015SBarry Smith } 2609a6cb015SBarry Smith ierr = (*ctx->ops->compute)(ctx,U,a,&h);CHKERRQ(ierr); 261a4d4d686SBarry Smith 262a4d4d686SBarry Smith /* keep a record of the current differencing parameter h */ 263a4d4d686SBarry Smith ctx->currenth = h; 264aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 265b0a32e0cSBarry Smith PetscLogInfo(mat,"MatSNESMFMult_Private:Current differencing parameter: %g + %g i\n",PetscRealPart(h),PetscImaginaryPart(h)); 266a4d4d686SBarry Smith #else 267b0a32e0cSBarry Smith PetscLogInfo(mat,"MatSNESMFMult_Private:Current differencing parameter: %15.12e\n",h); 268a4d4d686SBarry Smith #endif 269a4d4d686SBarry Smith if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) { 27085614651SBarry Smith ctx->historyh[ctx->ncurrenth] = h; 271a4d4d686SBarry Smith } 27285614651SBarry Smith ctx->ncurrenth++; 273a4d4d686SBarry Smith 27485614651SBarry Smith /* w = u + ha */ 275a4d4d686SBarry Smith ierr = VecWAXPY(&h,a,U,w);CHKERRQ(ierr); 27685614651SBarry Smith 277b0a32e0cSBarry Smith if (ctx->usesnes) { 27885614651SBarry Smith if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 27985614651SBarry Smith eval_fct = SNESComputeFunction; 28085614651SBarry Smith } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 28185614651SBarry Smith eval_fct = SNESComputeGradient; 28229bbc08cSBarry Smith } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class"); 2831d1367b7SBarry Smith F = ctx->current_f; 28429bbc08cSBarry Smith if (!F) SETERRQ(1,"You must call MatAssembly() even on matrix-free matrices"); 28539903ad8SBarry Smith ierr = (*eval_fct)(snes,w,y);CHKERRQ(ierr); 28685614651SBarry Smith } else { 28785614651SBarry Smith F = ctx->funcvec; 28885614651SBarry Smith /* compute func(U) as base for differencing */ 28985614651SBarry Smith if (ctx->ncurrenth == 1) { 29085614651SBarry Smith ierr = (*ctx->func)(snes,U,F,ctx->funcctx);CHKERRQ(ierr); 29185614651SBarry Smith } 29285614651SBarry Smith ierr = (*ctx->func)(snes,w,y,ctx->funcctx);CHKERRQ(ierr); 29385614651SBarry Smith } 294a4d4d686SBarry Smith 295a4d4d686SBarry Smith ierr = VecAXPY(&mone,F,y);CHKERRQ(ierr); 296a4d4d686SBarry Smith h = 1.0/h; 297a4d4d686SBarry Smith ierr = VecScale(&h,y);CHKERRQ(ierr); 29874637425SBarry Smith if (ctx->sp) {ierr = MatNullSpaceRemove(ctx->sp,y,PETSC_NULL);CHKERRQ(ierr);} 299a4d4d686SBarry Smith 300b0a32e0cSBarry Smith ierr = PetscLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);CHKERRQ(ierr); 301a4d4d686SBarry Smith PetscFunctionReturn(0); 302a4d4d686SBarry Smith } 303a4d4d686SBarry Smith 3044a2ae208SSatish Balay #undef __FUNCT__ 305*cf57b110SBarry Smith #define __FUNCT__ "MatSNESMFGetDiagonal_Private" 306*cf57b110SBarry Smith /* 307*cf57b110SBarry Smith MatSNESMFGetDiagonal_Private - Gets the diagonal for a matrix free matrix 308*cf57b110SBarry Smith 309*cf57b110SBarry Smith y ~= (F(u + ha) - F(u))/h, 310*cf57b110SBarry Smith where F = nonlinear function, as set by SNESSetFunction() 311*cf57b110SBarry Smith u = current iterate 312*cf57b110SBarry Smith h = difference interval 313*cf57b110SBarry Smith */ 314*cf57b110SBarry Smith int MatSNESMFGetDiagonal_Private(Mat mat,Vec a) 315*cf57b110SBarry Smith { 316*cf57b110SBarry Smith MatSNESMFCtx ctx; 317*cf57b110SBarry Smith Scalar h,h1,mone = -1.0,*aa,*ww,v,epsilon = 1.e-8,umin = 1.e-6; 318*cf57b110SBarry Smith Vec w,U,F; 319*cf57b110SBarry Smith int i,ierr,rstart,rend; 320*cf57b110SBarry Smith 321*cf57b110SBarry Smith PetscFunctionBegin; 322*cf57b110SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 323*cf57b110SBarry Smith if (!ctx->funci) { 324*cf57b110SBarry Smith SETERRQ(1,"Requirers calling MatSNESMFSetFunctioni() first"); 325*cf57b110SBarry Smith } 326*cf57b110SBarry Smith 327*cf57b110SBarry Smith w = ctx->w; 328*cf57b110SBarry Smith U = ctx->current_u; 329*cf57b110SBarry Smith ierr = (*ctx->func)(0,U,a,ctx->funcctx);CHKERRQ(ierr); 330*cf57b110SBarry Smith ierr = (*ctx->funcisetbase)(U,ctx->funcctx);CHKERRQ(ierr); 331*cf57b110SBarry Smith ierr = VecCopy(U,w);CHKERRQ(ierr); 332*cf57b110SBarry Smith 333*cf57b110SBarry Smith ierr = VecGetOwnershipRange(a,&rstart,&rend);CHKERRQ(ierr); 334*cf57b110SBarry Smith ierr = VecGetArray(a,&aa);CHKERRQ(ierr); 335*cf57b110SBarry Smith for (i=rstart; i<rend; i++) { 336*cf57b110SBarry Smith ierr = VecGetArray(w,&ww);CHKERRQ(ierr); 337*cf57b110SBarry Smith h = ww[i-rstart]; 338*cf57b110SBarry Smith if (h == 0.0) h = 1.0; 339*cf57b110SBarry Smith #if !defined(PETSC_USE_COMPLEX) 340*cf57b110SBarry Smith if (h < umin && h >= 0.0) h = umin; 341*cf57b110SBarry Smith else if (h < 0.0 && h > -umin) h = -umin; 342*cf57b110SBarry Smith #else 343*cf57b110SBarry Smith if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0) h = umin; 344*cf57b110SBarry Smith else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin; 345*cf57b110SBarry Smith #endif 346*cf57b110SBarry Smith h *= epsilon; 347*cf57b110SBarry Smith 348*cf57b110SBarry Smith ww[i-rstart] += h; 349*cf57b110SBarry Smith ierr = VecRestoreArray(w,&ww);CHKERRQ(ierr); 350*cf57b110SBarry Smith ierr = (*ctx->funci)(i,w,&v,ctx->funcctx);CHKERRQ(ierr); 351*cf57b110SBarry Smith aa[i-rstart] = (v - aa[i-rstart])/h; 352*cf57b110SBarry Smith ierr = VecGetArray(w,&ww);CHKERRQ(ierr); 353*cf57b110SBarry Smith ww[i-rstart] -= h; 354*cf57b110SBarry Smith ierr = VecRestoreArray(w,&ww);CHKERRQ(ierr); 355*cf57b110SBarry Smith } 356*cf57b110SBarry Smith ierr = VecRestoreArray(a,&aa);CHKERRQ(ierr); 357*cf57b110SBarry Smith PetscFunctionReturn(0); 358*cf57b110SBarry Smith } 359*cf57b110SBarry Smith 360*cf57b110SBarry Smith #undef __FUNCT__ 3614a2ae208SSatish Balay #define __FUNCT__ "MatCreateSNESMF" 362a4d4d686SBarry Smith /*@C 36365f2ba5bSLois Curfman McInnes MatCreateSNESMF - Creates a matrix-free matrix context for use with 36465f2ba5bSLois Curfman McInnes a SNES solver. This matrix can be used as the Jacobian argument for 36565f2ba5bSLois Curfman McInnes the routine SNESSetJacobian(). 366a4d4d686SBarry Smith 367a4d4d686SBarry Smith Collective on SNES and Vec 368a4d4d686SBarry Smith 369a4d4d686SBarry Smith Input Parameters: 370a4d4d686SBarry Smith + snes - the SNES context 371a4d4d686SBarry Smith - x - vector where SNES solution is to be stored. 372a4d4d686SBarry Smith 373a4d4d686SBarry Smith Output Parameter: 374a4d4d686SBarry Smith . J - the matrix-free matrix 375a4d4d686SBarry Smith 37615091d37SBarry Smith Level: advanced 37715091d37SBarry Smith 378a4d4d686SBarry Smith Notes: 379a4d4d686SBarry Smith The matrix-free matrix context merely contains the function pointers 380a4d4d686SBarry Smith and work space for performing finite difference approximations of 38165f2ba5bSLois Curfman McInnes Jacobian-vector products, F'(u)*a, 3829a6cb015SBarry Smith 3839a6cb015SBarry Smith The default code uses the following approach to compute h 384a4d4d686SBarry Smith 385a4d4d686SBarry Smith .vb 38665f2ba5bSLois Curfman McInnes F'(u)*a = [F(u+h*a) - F(u)]/h where 387a4d4d686SBarry Smith h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 388a4d4d686SBarry Smith = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 389a4d4d686SBarry Smith where 390a4d4d686SBarry Smith error_rel = square root of relative error in function evaluation 391a4d4d686SBarry Smith umin = minimum iterate parameter 392a4d4d686SBarry Smith .ve 393a4d4d686SBarry Smith 3945a655dc6SBarry Smith The user can set the error_rel via MatSNESMFSetFunctionError() and 39565f2ba5bSLois Curfman McInnes umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 39665f2ba5bSLois Curfman McInnes of the users manual for details. 397a4d4d686SBarry Smith 398a4d4d686SBarry Smith The user should call MatDestroy() when finished with the matrix-free 399a4d4d686SBarry Smith matrix context. 400a4d4d686SBarry Smith 401a4d4d686SBarry Smith Options Database Keys: 402a4d4d686SBarry Smith + -snes_mf_err <error_rel> - Sets error_rel 4039a6cb015SBarry Smith . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 404a4d4d686SBarry Smith - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 405a4d4d686SBarry Smith 406a4d4d686SBarry Smith .keywords: SNES, default, matrix-free, create, matrix 407a4d4d686SBarry Smith 4085a655dc6SBarry Smith .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin() 4091d1367b7SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateMF(), 410fed8bd04SBarry Smith MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic), MatSNESMFComputeJacobian() 411a4d4d686SBarry Smith 412a4d4d686SBarry Smith @*/ 4135a655dc6SBarry Smith int MatCreateSNESMF(SNES snes,Vec x,Mat *J) 414a4d4d686SBarry Smith { 4151d1367b7SBarry Smith MatSNESMFCtx mfctx; 4161d1367b7SBarry Smith int ierr; 4171d1367b7SBarry Smith 4181d1367b7SBarry Smith PetscFunctionBegin; 4191d1367b7SBarry Smith ierr = MatCreateMF(x,J);CHKERRQ(ierr); 4201d1367b7SBarry Smith ierr = MatShellGetContext(*J,(void **)&mfctx);CHKERRQ(ierr); 4211d1367b7SBarry Smith mfctx->snes = snes; 422b0a32e0cSBarry Smith mfctx->usesnes = PETSC_TRUE; 423b0a32e0cSBarry Smith PetscLogObjectParent(snes,*J); 4241d1367b7SBarry Smith PetscFunctionReturn(0); 4251d1367b7SBarry Smith } 4261d1367b7SBarry Smith 427cf3bea43SBarry Smith EXTERN_C_BEGIN 428cf3bea43SBarry Smith #undef __FUNCT__ 429cf3bea43SBarry Smith #define __FUNCT__ "MatSNESMFSetBase_FD" 430cf3bea43SBarry Smith int MatSNESMFSetBase_FD(Mat J,Vec U) 431cf3bea43SBarry Smith { 432cf3bea43SBarry Smith int ierr; 433cf3bea43SBarry Smith MatSNESMFCtx ctx; 434cf3bea43SBarry Smith 435cf3bea43SBarry Smith PetscFunctionBegin; 436cf3bea43SBarry Smith ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr); 437cf3bea43SBarry Smith ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 438cf3bea43SBarry Smith ctx->current_u = U; 439cf3bea43SBarry Smith ctx->usesnes = PETSC_FALSE; 440cf3bea43SBarry Smith PetscFunctionReturn(0); 441cf3bea43SBarry Smith } 442cf3bea43SBarry Smith EXTERN_C_END 443cf3bea43SBarry Smith 4444a2ae208SSatish Balay #undef __FUNCT__ 4454a2ae208SSatish Balay #define __FUNCT__ "MatCreateMF" 4461d1367b7SBarry Smith /*@C 4471d1367b7SBarry Smith MatCreateMF - Creates a matrix-free matrix. See also MatCreateSNESMF() 4481d1367b7SBarry Smith 4491d1367b7SBarry Smith Collective on Vec 4501d1367b7SBarry Smith 4511d1367b7SBarry Smith Input Parameters: 4521d1367b7SBarry Smith . x - vector that defines layout of the vectors and matrices 4531d1367b7SBarry Smith 4541d1367b7SBarry Smith Output Parameter: 4551d1367b7SBarry Smith . J - the matrix-free matrix 4561d1367b7SBarry Smith 4571d1367b7SBarry Smith Level: advanced 4581d1367b7SBarry Smith 4591d1367b7SBarry Smith Notes: 4601d1367b7SBarry Smith The matrix-free matrix context merely contains the function pointers 4611d1367b7SBarry Smith and work space for performing finite difference approximations of 4621d1367b7SBarry Smith Jacobian-vector products, F'(u)*a, 4631d1367b7SBarry Smith 4641d1367b7SBarry Smith The default code uses the following approach to compute h 4651d1367b7SBarry Smith 4661d1367b7SBarry Smith .vb 4671d1367b7SBarry Smith F'(u)*a = [F(u+h*a) - F(u)]/h where 4681d1367b7SBarry Smith h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 4691d1367b7SBarry Smith = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 4701d1367b7SBarry Smith where 4711d1367b7SBarry Smith error_rel = square root of relative error in function evaluation 4721d1367b7SBarry Smith umin = minimum iterate parameter 4731d1367b7SBarry Smith .ve 4741d1367b7SBarry Smith 4751d1367b7SBarry Smith The user can set the error_rel via MatSNESMFSetFunctionError() and 4761d1367b7SBarry Smith umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 4771d1367b7SBarry Smith of the users manual for details. 4781d1367b7SBarry Smith 4791d1367b7SBarry Smith The user should call MatDestroy() when finished with the matrix-free 4801d1367b7SBarry Smith matrix context. 4811d1367b7SBarry Smith 4821d1367b7SBarry Smith Options Database Keys: 4831d1367b7SBarry Smith + -snes_mf_err <error_rel> - Sets error_rel 4841d1367b7SBarry Smith . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 4851d1367b7SBarry Smith - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 4861d1367b7SBarry Smith 4871d1367b7SBarry Smith .keywords: default, matrix-free, create, matrix 4881d1367b7SBarry Smith 4891d1367b7SBarry Smith .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin() 4901d1367b7SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateSNESMF(), 491fed8bd04SBarry Smith MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic),, MatSNESMFComputeJacobian() 4921d1367b7SBarry Smith 4931d1367b7SBarry Smith @*/ 4941d1367b7SBarry Smith int MatCreateMF(Vec x,Mat *J) 4951d1367b7SBarry Smith { 496a4d4d686SBarry Smith MPI_Comm comm; 4975a655dc6SBarry Smith MatSNESMFCtx mfctx; 4989a6cb015SBarry Smith int n,nloc,ierr; 499a4d4d686SBarry Smith 500a4d4d686SBarry Smith PetscFunctionBegin; 5011d1367b7SBarry Smith ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); 5021d1367b7SBarry Smith PetscHeaderCreate(mfctx,_p_MatSNESMFCtx,struct _MFOps,MATSNESMFCTX_COOKIE,0,"SNESMF",comm,MatSNESMFDestroy_Private,MatSNESMFView_Private); 503b0a32e0cSBarry Smith PetscLogObjectCreate(mfctx); 504a4d4d686SBarry Smith mfctx->sp = 0; 5051d1367b7SBarry Smith mfctx->snes = 0; 506329f5518SBarry Smith mfctx->error_rel = 1.e-8; /* assumes PetscReal precision */ 507329f5518SBarry Smith mfctx->recomputeperiod = 1; 508329f5518SBarry Smith mfctx->count = 0; 509a4d4d686SBarry Smith mfctx->currenth = 0.0; 510a4d4d686SBarry Smith mfctx->historyh = PETSC_NULL; 511a4d4d686SBarry Smith mfctx->ncurrenth = 0; 512a4d4d686SBarry Smith mfctx->maxcurrenth = 0; 5136831982aSBarry Smith mfctx->type_name = 0; 514b0a32e0cSBarry Smith mfctx->usesnes = PETSC_FALSE; 515a4d4d686SBarry Smith 5169a6cb015SBarry Smith /* 5179a6cb015SBarry Smith Create the empty data structure to contain compute-h routines. 5189a6cb015SBarry Smith These will be filled in below from the command line options or 5195a655dc6SBarry Smith a later call with MatSNESMFSetType() or if that is not called 5205a655dc6SBarry Smith then it will default in the first use of MatSNESMFMult_private() 5219a6cb015SBarry Smith */ 5229a6cb015SBarry Smith mfctx->ops->compute = 0; 5239a6cb015SBarry Smith mfctx->ops->destroy = 0; 5249a6cb015SBarry Smith mfctx->ops->view = 0; 5259a6cb015SBarry Smith mfctx->ops->setfromoptions = 0; 5269a6cb015SBarry Smith mfctx->hctx = 0; 5279a6cb015SBarry Smith 52885614651SBarry Smith mfctx->func = 0; 52985614651SBarry Smith mfctx->funcctx = 0; 53085614651SBarry Smith mfctx->funcvec = 0; 53185614651SBarry Smith 532a4d4d686SBarry Smith ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr); 5331d1367b7SBarry Smith ierr = VecGetSize(mfctx->w,&n);CHKERRQ(ierr); 5341d1367b7SBarry Smith ierr = VecGetLocalSize(mfctx->w,&nloc);CHKERRQ(ierr); 535ffa0fd9eSBarry Smith ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr); 53637bd1cefSSatish Balay ierr = MatShellSetOperation(*J,MATOP_MULT,(void(*)())MatSNESMFMult_Private);CHKERRQ(ierr); 53737bd1cefSSatish Balay ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void(*)())MatSNESMFDestroy_Private);CHKERRQ(ierr); 53837bd1cefSSatish Balay ierr = MatShellSetOperation(*J,MATOP_VIEW,(void(*)())MatSNESMFView_Private);CHKERRQ(ierr); 53937bd1cefSSatish Balay ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void(*)())MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr); 540*cf57b110SBarry Smith ierr = MatShellSetOperation(*J,MATOP_GET_DIAGONAL,(void(*)())MatSNESMFGetDiagonal_Private);CHKERRQ(ierr); 541cf3bea43SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)*J,"MatSNESMFSetBase_C","MatSNESMFSetBase_FD",MatSNESMFSetBase_FD);CHKERRQ(ierr); 542b0a32e0cSBarry Smith PetscLogObjectParent(*J,mfctx->w); 5439a6cb015SBarry Smith 5449a6cb015SBarry Smith mfctx->mat = *J; 5459a6cb015SBarry Smith PetscFunctionReturn(0); 5469a6cb015SBarry Smith } 5479a6cb015SBarry Smith 5484a2ae208SSatish Balay #undef __FUNCT__ 5494a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetFromOptions" 5509a6cb015SBarry Smith /*@ 5515a655dc6SBarry Smith MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line 5529a6cb015SBarry Smith parameter. 5539a6cb015SBarry Smith 5549a6cb015SBarry Smith Collective on Mat 5559a6cb015SBarry Smith 5569a6cb015SBarry Smith Input Parameters: 5575a655dc6SBarry Smith . mat - the matrix obtained with MatCreateSNESMF() 5585a655dc6SBarry Smith 5595a655dc6SBarry Smith Options Database Keys: 5605a655dc6SBarry Smith + -snes_mf_type - <default,wp> 5615a655dc6SBarry Smith - -snes_mf_err - square root of estimated relative error in function evaluation 562329f5518SBarry Smith - -snes_mf_period - how often h is recomputed, defaults to 1, everytime 5639a6cb015SBarry Smith 56415091d37SBarry Smith Level: advanced 56515091d37SBarry Smith 5669a6cb015SBarry Smith .keywords: SNES, matrix-free, parameters 5679a6cb015SBarry Smith 5685a655dc6SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 5695a655dc6SBarry Smith MatSNESMFResetHHistory(), MatSNESMFKSPMonitor() 5709a6cb015SBarry Smith @*/ 5715a655dc6SBarry Smith int MatSNESMFSetFromOptions(Mat mat) 5729a6cb015SBarry Smith { 5735a655dc6SBarry Smith MatSNESMFCtx mfctx; 574f1af5d2fSBarry Smith int ierr; 575f1af5d2fSBarry Smith PetscTruth flg; 576186905e3SBarry Smith char ftype[256]; 5779a6cb015SBarry Smith 5789a6cb015SBarry Smith PetscFunctionBegin; 5799a6cb015SBarry Smith ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr); 5809a6cb015SBarry Smith if (mfctx) { 581186905e3SBarry Smith if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 582186905e3SBarry Smith 583b0a32e0cSBarry Smith ierr = PetscOptionsBegin(mfctx->comm,mfctx->prefix,"Set matrix free computation parameters","MatSNESMF");CHKERRQ(ierr); 584b0a32e0cSBarry Smith ierr = PetscOptionsList("-snes_mf_type","Matrix free type","MatSNESMFSetType",MatSNESMPetscFList,mfctx->type_name,ftype,256,&flg);CHKERRQ(ierr); 5859a6cb015SBarry Smith if (flg) { 5865a655dc6SBarry Smith ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 5879a6cb015SBarry Smith } 5889a6cb015SBarry Smith 589b0a32e0cSBarry Smith ierr = PetscOptionsDouble("-snes_mf_err","set sqrt relative error in function","MatSNESMFSetFunctionError",mfctx->error_rel,&mfctx->error_rel,0);CHKERRQ(ierr); 590b0a32e0cSBarry Smith ierr = PetscOptionsInt("-snes_mf_period","how often h is recomputed","MatSNESMFSetPeriod",mfctx->recomputeperiod,&mfctx->recomputeperiod,0);CHKERRQ(ierr); 591186905e3SBarry Smith if (mfctx->snes) { 592b0a32e0cSBarry Smith ierr = PetscOptionsName("-snes_mf_ksp_monitor","Monitor matrix-free parameters","MatSNESMFKSPMonitor",&flg);CHKERRQ(ierr); 593186905e3SBarry Smith if (flg) { 594186905e3SBarry Smith SLES sles; 595186905e3SBarry Smith KSP ksp; 596186905e3SBarry Smith ierr = SNESGetSLES(mfctx->snes,&sles);CHKERRQ(ierr); 597186905e3SBarry Smith ierr = SLESGetKSP(sles,&ksp);CHKERRQ(ierr); 598186905e3SBarry Smith ierr = KSPSetMonitor(ksp,MatSNESMFKSPMonitor,PETSC_NULL,0);CHKERRQ(ierr); 599186905e3SBarry Smith } 600186905e3SBarry Smith } 6019a6cb015SBarry Smith if (mfctx->ops->setfromoptions) { 6029a6cb015SBarry Smith ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 6039a6cb015SBarry Smith } 604b0a32e0cSBarry Smith ierr = PetscOptionsEnd();CHKERRQ(ierr); 6054bbc92c1SBarry Smith 6069a6cb015SBarry Smith } 607a4d4d686SBarry Smith PetscFunctionReturn(0); 608a4d4d686SBarry Smith } 609a4d4d686SBarry Smith 6104a2ae208SSatish Balay #undef __FUNCT__ 6114a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFGetH" 612a4d4d686SBarry Smith /*@ 61365f2ba5bSLois Curfman McInnes MatSNESMFGetH - Gets the last value that was used as the differencing 614a4d4d686SBarry Smith parameter. 615a4d4d686SBarry Smith 616a4d4d686SBarry Smith Not Collective 617a4d4d686SBarry Smith 618a4d4d686SBarry Smith Input Parameters: 6195a655dc6SBarry Smith . mat - the matrix obtained with MatCreateSNESMF() 620a4d4d686SBarry Smith 621a4d4d686SBarry Smith Output Paramter: 622a4d4d686SBarry Smith . h - the differencing step size 623a4d4d686SBarry Smith 62415091d37SBarry Smith Level: advanced 62515091d37SBarry Smith 626a4d4d686SBarry Smith .keywords: SNES, matrix-free, parameters 627a4d4d686SBarry Smith 6285a655dc6SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 6295a655dc6SBarry Smith MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 630a4d4d686SBarry Smith @*/ 6315a655dc6SBarry Smith int MatSNESMFGetH(Mat mat,Scalar *h) 632a4d4d686SBarry Smith { 6335a655dc6SBarry Smith MatSNESMFCtx ctx; 634a4d4d686SBarry Smith int ierr; 635a4d4d686SBarry Smith 636a4d4d686SBarry Smith PetscFunctionBegin; 637a4d4d686SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 638a4d4d686SBarry Smith if (ctx) { 639a4d4d686SBarry Smith *h = ctx->currenth; 640a4d4d686SBarry Smith } 641a4d4d686SBarry Smith PetscFunctionReturn(0); 642a4d4d686SBarry Smith } 643a4d4d686SBarry Smith 6444a2ae208SSatish Balay #undef __FUNCT__ 6454a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFKSPMonitor" 646a4d4d686SBarry Smith /* 6475a655dc6SBarry Smith MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc 64865f2ba5bSLois Curfman McInnes SNES matrix free routines. Prints the differencing parameter used at 64965f2ba5bSLois Curfman McInnes each step. 650a4d4d686SBarry Smith */ 651329f5518SBarry Smith int MatSNESMFKSPMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy) 652a4d4d686SBarry Smith { 653a4d4d686SBarry Smith PC pc; 6545a655dc6SBarry Smith MatSNESMFCtx ctx; 655a4d4d686SBarry Smith int ierr; 656a4d4d686SBarry Smith Mat mat; 657a4d4d686SBarry Smith MPI_Comm comm; 658a4d4d686SBarry Smith PetscTruth nonzeroinitialguess; 659a4d4d686SBarry Smith 660a4d4d686SBarry Smith PetscFunctionBegin; 661a4d4d686SBarry Smith ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 662a4d4d686SBarry Smith ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 663a4d4d686SBarry Smith ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 664a4d4d686SBarry Smith ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 665a4d4d686SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 6669a6cb015SBarry Smith if (!ctx) { 66729bbc08cSBarry Smith SETERRQ(1,"Matrix is not a matrix free shell matrix"); 6689a6cb015SBarry Smith } 669a4d4d686SBarry Smith if (n > 0 || nonzeroinitialguess) { 670aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 671d132466eSBarry Smith ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 672329f5518SBarry Smith PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));CHKERRQ(ierr); 673a4d4d686SBarry Smith #else 674d132466eSBarry Smith ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr); 675a4d4d686SBarry Smith #endif 676a4d4d686SBarry Smith } else { 677d132466eSBarry Smith ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); 678a4d4d686SBarry Smith } 679a4d4d686SBarry Smith PetscFunctionReturn(0); 680a4d4d686SBarry Smith } 681a4d4d686SBarry Smith 6824a2ae208SSatish Balay #undef __FUNCT__ 6834a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetFunction" 68485614651SBarry Smith /*@C 68585614651SBarry Smith MatSNESMFSetFunction - Sets the function used in applying the matrix free. 68685614651SBarry Smith 68785614651SBarry Smith Collective on Mat 68885614651SBarry Smith 68985614651SBarry Smith Input Parameters: 69085614651SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 69185614651SBarry Smith . v - workspace vector 69285614651SBarry Smith . func - the function to use 69385614651SBarry Smith - funcctx - optional function context passed to function 69485614651SBarry Smith 69585614651SBarry Smith Level: advanced 69685614651SBarry Smith 69785614651SBarry Smith Notes: 69885614651SBarry Smith If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 69985614651SBarry Smith matrix inside your compute Jacobian routine 70085614651SBarry Smith 70185614651SBarry Smith If this is not set then it will use the function set with SNESSetFunction() 70285614651SBarry Smith 70385614651SBarry Smith .keywords: SNES, matrix-free, function 70485614651SBarry Smith 70585614651SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 70685614651SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 70785614651SBarry Smith MatSNESMFKSPMonitor(), SNESetFunction() 70885614651SBarry Smith @*/ 70985614651SBarry Smith int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx) 71085614651SBarry Smith { 71185614651SBarry Smith MatSNESMFCtx ctx; 71285614651SBarry Smith int ierr; 71385614651SBarry Smith 71485614651SBarry Smith PetscFunctionBegin; 71585614651SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 71685614651SBarry Smith if (ctx) { 71785614651SBarry Smith ctx->func = func; 71885614651SBarry Smith ctx->funcctx = funcctx; 71985614651SBarry Smith ctx->funcvec = v; 72085614651SBarry Smith } 72185614651SBarry Smith PetscFunctionReturn(0); 72285614651SBarry Smith } 72385614651SBarry Smith 724*cf57b110SBarry Smith #undef __FUNCT__ 725*cf57b110SBarry Smith #define __FUNCT__ "MatSNESMFSetFunctioni" 726*cf57b110SBarry Smith /*@C 727*cf57b110SBarry Smith MatSNESMFSetFunctioni - Sets the function for a single component 728*cf57b110SBarry Smith 729*cf57b110SBarry Smith Collective on Mat 730*cf57b110SBarry Smith 731*cf57b110SBarry Smith Input Parameters: 732*cf57b110SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 733*cf57b110SBarry Smith - funci - the function to use 734*cf57b110SBarry Smith 735*cf57b110SBarry Smith Level: advanced 736*cf57b110SBarry Smith 737*cf57b110SBarry Smith Notes: 738*cf57b110SBarry Smith If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 739*cf57b110SBarry Smith matrix inside your compute Jacobian routine 740*cf57b110SBarry Smith 741*cf57b110SBarry Smith 742*cf57b110SBarry Smith .keywords: SNES, matrix-free, function 743*cf57b110SBarry Smith 744*cf57b110SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 745*cf57b110SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 746*cf57b110SBarry Smith MatSNESMFKSPMonitor(), SNESetFunction() 747*cf57b110SBarry Smith @*/ 748*cf57b110SBarry Smith int MatSNESMFSetFunctioni(Mat mat,int (*funci)(int,Vec,Scalar*,void *)) 749*cf57b110SBarry Smith { 750*cf57b110SBarry Smith MatSNESMFCtx ctx; 751*cf57b110SBarry Smith int ierr; 752*cf57b110SBarry Smith 753*cf57b110SBarry Smith PetscFunctionBegin; 754*cf57b110SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 755*cf57b110SBarry Smith if (ctx) { 756*cf57b110SBarry Smith ctx->funci = funci; 757*cf57b110SBarry Smith } 758*cf57b110SBarry Smith PetscFunctionReturn(0); 759*cf57b110SBarry Smith } 760*cf57b110SBarry Smith 761*cf57b110SBarry Smith #undef __FUNCT__ 762*cf57b110SBarry Smith #define __FUNCT__ "MatSNESMFSetFunctioniBase" 763*cf57b110SBarry Smith /*@C 764*cf57b110SBarry Smith MatSNESMFSetFunctioniBase - Sets the base vector for a single component function evaluation 765*cf57b110SBarry Smith 766*cf57b110SBarry Smith Collective on Mat 767*cf57b110SBarry Smith 768*cf57b110SBarry Smith Input Parameters: 769*cf57b110SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 770*cf57b110SBarry Smith - func - the function to use 771*cf57b110SBarry Smith 772*cf57b110SBarry Smith Level: advanced 773*cf57b110SBarry Smith 774*cf57b110SBarry Smith Notes: 775*cf57b110SBarry Smith If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 776*cf57b110SBarry Smith matrix inside your compute Jacobian routine 777*cf57b110SBarry Smith 778*cf57b110SBarry Smith 779*cf57b110SBarry Smith .keywords: SNES, matrix-free, function 780*cf57b110SBarry Smith 781*cf57b110SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 782*cf57b110SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 783*cf57b110SBarry Smith MatSNESMFKSPMonitor(), SNESetFunction() 784*cf57b110SBarry Smith @*/ 785*cf57b110SBarry Smith int MatSNESMFSetFunctioniBase(Mat mat,int (*func)(Vec,void *)) 786*cf57b110SBarry Smith { 787*cf57b110SBarry Smith MatSNESMFCtx ctx; 788*cf57b110SBarry Smith int ierr; 789*cf57b110SBarry Smith 790*cf57b110SBarry Smith PetscFunctionBegin; 791*cf57b110SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 792*cf57b110SBarry Smith if (ctx) { 793*cf57b110SBarry Smith ctx->funcisetbase = func; 794*cf57b110SBarry Smith } 795*cf57b110SBarry Smith PetscFunctionReturn(0); 796*cf57b110SBarry Smith } 797*cf57b110SBarry Smith 79885614651SBarry Smith 7994a2ae208SSatish Balay #undef __FUNCT__ 8004a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetPeriod" 801329f5518SBarry Smith /*@ 802329f5518SBarry Smith MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime 803329f5518SBarry Smith 804329f5518SBarry Smith Collective on Mat 805329f5518SBarry Smith 806329f5518SBarry Smith Input Parameters: 807329f5518SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 808329f5518SBarry Smith - period - 1 for everytime, 2 for every second etc 809329f5518SBarry Smith 810329f5518SBarry Smith Options Database Keys: 811329f5518SBarry Smith + -snes_mf_period <period> 812329f5518SBarry Smith 813329f5518SBarry Smith Level: advanced 814329f5518SBarry Smith 815329f5518SBarry Smith 816329f5518SBarry Smith .keywords: SNES, matrix-free, parameters 817329f5518SBarry Smith 818329f5518SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 819329f5518SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 820329f5518SBarry Smith MatSNESMFKSPMonitor() 821329f5518SBarry Smith @*/ 822329f5518SBarry Smith int MatSNESMFSetPeriod(Mat mat,int period) 823329f5518SBarry Smith { 824329f5518SBarry Smith MatSNESMFCtx ctx; 825329f5518SBarry Smith int ierr; 826329f5518SBarry Smith 827329f5518SBarry Smith PetscFunctionBegin; 828329f5518SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 829329f5518SBarry Smith if (ctx) { 830329f5518SBarry Smith ctx->recomputeperiod = period; 831329f5518SBarry Smith } 832329f5518SBarry Smith PetscFunctionReturn(0); 833329f5518SBarry Smith } 834329f5518SBarry Smith 8354a2ae208SSatish Balay #undef __FUNCT__ 8364a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetFunctionError" 837a4d4d686SBarry Smith /*@ 8385a655dc6SBarry Smith MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 839a4d4d686SBarry Smith matrix-vector products using finite differences. 840a4d4d686SBarry Smith 841a4d4d686SBarry Smith Collective on Mat 842a4d4d686SBarry Smith 843a4d4d686SBarry Smith Input Parameters: 8445a655dc6SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 8459a6cb015SBarry Smith - error_rel - relative error (should be set to the square root of 846a4d4d686SBarry Smith the relative error in the function evaluations) 847a4d4d686SBarry Smith 84815091d37SBarry Smith Options Database Keys: 84915091d37SBarry Smith + -snes_mf_err <error_rel> - Sets error_rel 85015091d37SBarry Smith 85115091d37SBarry Smith Level: advanced 85215091d37SBarry Smith 853a4d4d686SBarry Smith Notes: 854a4d4d686SBarry Smith The default matrix-free matrix-vector product routine computes 855a4d4d686SBarry Smith .vb 85665f2ba5bSLois Curfman McInnes F'(u)*a = [F(u+h*a) - F(u)]/h where 857a4d4d686SBarry Smith h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 858a4d4d686SBarry Smith = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 859a4d4d686SBarry Smith .ve 860a4d4d686SBarry Smith 861a4d4d686SBarry Smith .keywords: SNES, matrix-free, parameters 862a4d4d686SBarry Smith 8635a655dc6SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 8645a655dc6SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 8655a655dc6SBarry Smith MatSNESMFKSPMonitor() 866a4d4d686SBarry Smith @*/ 867329f5518SBarry Smith int MatSNESMFSetFunctionError(Mat mat,PetscReal error) 868a4d4d686SBarry Smith { 8695a655dc6SBarry Smith MatSNESMFCtx ctx; 870a4d4d686SBarry Smith int ierr; 871a4d4d686SBarry Smith 872a4d4d686SBarry Smith PetscFunctionBegin; 873a4d4d686SBarry Smith ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 874a4d4d686SBarry Smith if (ctx) { 875a4d4d686SBarry Smith if (error != PETSC_DEFAULT) ctx->error_rel = error; 876a4d4d686SBarry Smith } 877a4d4d686SBarry Smith PetscFunctionReturn(0); 878a4d4d686SBarry Smith } 879a4d4d686SBarry Smith 8804a2ae208SSatish Balay #undef __FUNCT__ 8814a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFAddNullSpace" 882a4d4d686SBarry Smith /*@ 88365f2ba5bSLois Curfman McInnes MatSNESMFAddNullSpace - Provides a null space that an operator is 88465f2ba5bSLois Curfman McInnes supposed to have. Since roundoff will create a small component in 88565f2ba5bSLois Curfman McInnes the null space, if you know the null space you may have it 88665f2ba5bSLois Curfman McInnes automatically removed. 887a4d4d686SBarry Smith 888a4d4d686SBarry Smith Collective on Mat 889a4d4d686SBarry Smith 890a4d4d686SBarry Smith Input Parameters: 891a4d4d686SBarry Smith + J - the matrix-free matrix context 89274637425SBarry Smith - nullsp - object created with MatNullSpaceCreate() 893a4d4d686SBarry Smith 89415091d37SBarry Smith Level: advanced 89515091d37SBarry Smith 896a4d4d686SBarry Smith .keywords: SNES, matrix-free, null space 897a4d4d686SBarry Smith 89874637425SBarry Smith .seealso: MatNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(), 8995a655dc6SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 9005a655dc6SBarry Smith MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 901a4d4d686SBarry Smith @*/ 90274637425SBarry Smith int MatSNESMFAddNullSpace(Mat J,MatNullSpace nullsp) 903a4d4d686SBarry Smith { 904a4d4d686SBarry Smith int ierr; 9055a655dc6SBarry Smith MatSNESMFCtx ctx; 906a4d4d686SBarry Smith MPI_Comm comm; 907a4d4d686SBarry Smith 908a4d4d686SBarry Smith PetscFunctionBegin; 9092d0c0e3bSBarry Smith ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 910a4d4d686SBarry Smith 911a4d4d686SBarry Smith ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 912a4d4d686SBarry Smith /* no context indicates that it is not the "matrix free" matrix type */ 913a4d4d686SBarry Smith if (!ctx) PetscFunctionReturn(0); 91485614651SBarry Smith ctx->sp = nullsp; 91585614651SBarry Smith ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 916a4d4d686SBarry Smith PetscFunctionReturn(0); 917a4d4d686SBarry Smith } 918a4d4d686SBarry Smith 9194a2ae208SSatish Balay #undef __FUNCT__ 9204a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetHHistory" 921a4d4d686SBarry Smith /*@ 92265f2ba5bSLois Curfman McInnes MatSNESMFSetHHistory - Sets an array to collect a history of the 92365f2ba5bSLois Curfman McInnes differencing values (h) computed for the matrix-free product. 924a4d4d686SBarry Smith 925a4d4d686SBarry Smith Collective on Mat 926a4d4d686SBarry Smith 927a4d4d686SBarry Smith Input Parameters: 928a4d4d686SBarry Smith + J - the matrix-free matrix context 92965f2ba5bSLois Curfman McInnes . histroy - space to hold the history 93065f2ba5bSLois Curfman McInnes - nhistory - number of entries in history, if more entries are generated than 93165f2ba5bSLois Curfman McInnes nhistory, then the later ones are discarded 932a4d4d686SBarry Smith 93315091d37SBarry Smith Level: advanced 93415091d37SBarry Smith 935a4d4d686SBarry Smith Notes: 93665f2ba5bSLois Curfman McInnes Use MatSNESMFResetHHistory() to reset the history counter and collect 93765f2ba5bSLois Curfman McInnes a new batch of differencing parameters, h. 938a4d4d686SBarry Smith 939a4d4d686SBarry Smith .keywords: SNES, matrix-free, h history, differencing history 940a4d4d686SBarry Smith 9415a655dc6SBarry Smith .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 9425a655dc6SBarry Smith MatSNESMFResetHHistory(), 9435a655dc6SBarry Smith MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 944a4d4d686SBarry Smith 945a4d4d686SBarry Smith @*/ 9465a655dc6SBarry Smith int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory) 947a4d4d686SBarry Smith { 948a4d4d686SBarry Smith int ierr; 9495a655dc6SBarry Smith MatSNESMFCtx ctx; 950a4d4d686SBarry Smith 951a4d4d686SBarry Smith PetscFunctionBegin; 952a4d4d686SBarry Smith 953a4d4d686SBarry Smith ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 954a4d4d686SBarry Smith /* no context indicates that it is not the "matrix free" matrix type */ 955a4d4d686SBarry Smith if (!ctx) PetscFunctionReturn(0); 956a4d4d686SBarry Smith ctx->historyh = history; 957a4d4d686SBarry Smith ctx->maxcurrenth = nhistory; 958a4d4d686SBarry Smith ctx->currenth = 0; 959a4d4d686SBarry Smith 960a4d4d686SBarry Smith PetscFunctionReturn(0); 961a4d4d686SBarry Smith } 962a4d4d686SBarry Smith 9634a2ae208SSatish Balay #undef __FUNCT__ 9644a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFResetHHistory" 965a4d4d686SBarry Smith /*@ 9665a655dc6SBarry Smith MatSNESMFResetHHistory - Resets the counter to zero to begin 967a4d4d686SBarry Smith collecting a new set of differencing histories. 968a4d4d686SBarry Smith 969a4d4d686SBarry Smith Collective on Mat 970a4d4d686SBarry Smith 971a4d4d686SBarry Smith Input Parameters: 972a4d4d686SBarry Smith . J - the matrix-free matrix context 973a4d4d686SBarry Smith 97415091d37SBarry Smith Level: advanced 97515091d37SBarry Smith 976a4d4d686SBarry Smith Notes: 97765f2ba5bSLois Curfman McInnes Use MatSNESMFSetHHistory() to create the original history counter. 978a4d4d686SBarry Smith 979a4d4d686SBarry Smith .keywords: SNES, matrix-free, h history, differencing history 980a4d4d686SBarry Smith 9815a655dc6SBarry Smith .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 9825a655dc6SBarry Smith MatSNESMFSetHHistory(), 9835a655dc6SBarry Smith MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 984a4d4d686SBarry Smith 985a4d4d686SBarry Smith @*/ 9865a655dc6SBarry Smith int MatSNESMFResetHHistory(Mat J) 987a4d4d686SBarry Smith { 988a4d4d686SBarry Smith int ierr; 9895a655dc6SBarry Smith MatSNESMFCtx ctx; 990a4d4d686SBarry Smith 991a4d4d686SBarry Smith PetscFunctionBegin; 992a4d4d686SBarry Smith 993a4d4d686SBarry Smith ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 994a4d4d686SBarry Smith /* no context indicates that it is not the "matrix free" matrix type */ 995a4d4d686SBarry Smith if (!ctx) PetscFunctionReturn(0); 996be726c96SBarry Smith ctx->ncurrenth = 0; 997a4d4d686SBarry Smith 998a4d4d686SBarry Smith PetscFunctionReturn(0); 999a4d4d686SBarry Smith } 1000a4d4d686SBarry Smith 10014a2ae208SSatish Balay #undef __FUNCT__ 1002fed8bd04SBarry Smith #define __FUNCT__ "MatSNESMFComputeJacobian" 1003fed8bd04SBarry Smith int MatSNESMFComputeJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy) 10041d1367b7SBarry Smith { 10051d1367b7SBarry Smith int ierr; 10061d1367b7SBarry Smith PetscFunctionBegin; 10071d1367b7SBarry Smith ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10081d1367b7SBarry Smith ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10091d1367b7SBarry Smith PetscFunctionReturn(0); 10101d1367b7SBarry Smith } 10111d1367b7SBarry Smith 10124a2ae208SSatish Balay #undef __FUNCT__ 10134a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetBase" 10141d1367b7SBarry Smith int MatSNESMFSetBase(Mat J,Vec U) 10151d1367b7SBarry Smith { 10163a7fca6bSBarry Smith int ierr,(*f)(Mat,Vec); 10171d1367b7SBarry Smith 10181d1367b7SBarry Smith PetscFunctionBegin; 10191d1367b7SBarry Smith PetscValidHeaderSpecific(J,MAT_COOKIE); 10201d1367b7SBarry Smith PetscValidHeaderSpecific(U,VEC_COOKIE); 1021cf3bea43SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)J,"MatSNESMFSetBase_C",(void (**)())&f);CHKERRQ(ierr); 1022cf3bea43SBarry Smith if (f) { 1023cf3bea43SBarry Smith ierr = (*f)(J,U);CHKERRQ(ierr); 102449d4803aSBarry Smith } 10251d1367b7SBarry Smith PetscFunctionReturn(0); 10261d1367b7SBarry Smith } 1027*cf57b110SBarry Smith 1028*cf57b110SBarry Smith 1029*cf57b110SBarry Smith 1030*cf57b110SBarry Smith 1031*cf57b110SBarry Smith 1032*cf57b110SBarry Smith 1033*cf57b110SBarry Smith 1034*cf57b110SBarry Smith 1035*cf57b110SBarry Smith 1036