163dd3a1aSKris Buschelman #define PETSCSNES_DLL 281e6777dSBarry Smith 3b9147fbbSdalcinl #include "include/private/matimpl.h" 4325e03aeSBarry Smith #include "src/snes/mf/snesmfj.h" /*I "petscsnes.h" I*/ 581e6777dSBarry Smith 6*e884886fSBarry Smith #undef __FUNCT__ 7*e884886fSBarry Smith #define __FUNCT__ "MatMFFDComputeJacobian" 8*e884886fSBarry Smith /*@ 9*e884886fSBarry Smith MatMFFDComputeJacobian - Tells the matrix-free Jacobian object the new location at which 10*e884886fSBarry Smith Jacobian matrix vector products will be computed at, i.e. J(x) * a. 11*e884886fSBarry Smith 12*e884886fSBarry Smith Collective on SNES 13*e884886fSBarry Smith 14*e884886fSBarry Smith Input Parameters: 15*e884886fSBarry Smith + snes - the nonlinear solver context 16*e884886fSBarry Smith . x - the point at which the Jacobian vector products will be performed 17*e884886fSBarry Smith . jac - the matrix-free Jacobian object 18*e884886fSBarry Smith . B - either the same as jac or another matrix type (ignored) 19*e884886fSBarry Smith . flag - not relevent for matrix-free form 20*e884886fSBarry Smith - dummy - the user context (ignored) 21*e884886fSBarry Smith 22*e884886fSBarry Smith Level: developer 23*e884886fSBarry Smith 24*e884886fSBarry Smith Notes: 25*e884886fSBarry Smith This can be passed into SNESSetJacobian() when using a completely matrix-free solver, 26*e884886fSBarry Smith that is the B matrix is also the same matrix operator. This is used when you select 27*e884886fSBarry Smith -mat_mffd but rarely used directly by users. 28*e884886fSBarry Smith 29*e884886fSBarry Smith .seealso: MatMFFDGetH(), MatCreateSNESMF(), 30*e884886fSBarry Smith MatMFFDSetHHistory(), 31*e884886fSBarry Smith MatMFFDKSPMonitor(), MatMFFDSetFunctionError(), MatMFFDCreate(), SNESSetJacobian() 32*e884886fSBarry Smith 33*e884886fSBarry Smith @*/ 34*e884886fSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatMFFDComputeJacobian(SNES *snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy) 35*e884886fSBarry Smith { 36*e884886fSBarry Smith PetscErrorCode ierr; 37*e884886fSBarry Smith PetscFunctionBegin; 38*e884886fSBarry Smith ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 39*e884886fSBarry Smith ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 40*e884886fSBarry Smith PetscFunctionReturn(0); 41*e884886fSBarry Smith } 42*e884886fSBarry Smith 43b0a32e0cSBarry Smith PetscFList MatSNESMPetscFList = 0; 444c49b128SBarry Smith PetscTruth MatSNESMFRegisterAllCalled = PETSC_FALSE; 45a4d4d686SBarry Smith 4663dd3a1aSKris Buschelman PetscCookie PETSCSNES_DLLEXPORT MATSNESMFCTX_COOKIE = 0; 4746129b97SKris Buschelman PetscEvent MATSNESMF_Mult = 0; 4846129b97SKris Buschelman 494a2ae208SSatish Balay #undef __FUNCT__ 504a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetType" 51fd4bdd07SBarry Smith /*@C 5265f2ba5bSLois Curfman McInnes MatSNESMFSetType - Sets the method that is used to compute the 53b0a32e0cSBarry Smith differencing parameter for finite differene matrix-free formulations. 549a6cb015SBarry Smith 559a6cb015SBarry Smith Input Parameters: 567e9d5209SBarry Smith + mat - the "matrix-free" matrix created via MatCreateSNESMF(), or MatCreateMF() 577e9d5209SBarry Smith or MatSetType(mat,MATMFFD); 58efb30889SBarry Smith - ftype - the type requested, either MATSNESMF_WP or MATSNESMF_DS 599a6cb015SBarry Smith 6015091d37SBarry Smith Level: advanced 6115091d37SBarry Smith 6265f2ba5bSLois Curfman McInnes Notes: 6365f2ba5bSLois Curfman McInnes For example, such routines can compute h for use in 6465f2ba5bSLois Curfman McInnes Jacobian-vector products of the form 6565f2ba5bSLois Curfman McInnes 6665f2ba5bSLois Curfman McInnes F(x+ha) - F(x) 67ef4ad1fdSLois Curfman McInnes F'(u)a ~= ---------------- 6865f2ba5bSLois Curfman McInnes h 6965f2ba5bSLois Curfman McInnes 70f1af5d2fSBarry Smith .seealso: MatCreateSNESMF(), MatSNESMFRegisterDynamic) 719a6cb015SBarry Smith @*/ 722e90c967SHong Zhang PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetType(Mat mat,MatSNESMFType ftype) 73b9fa9cd0SBarry Smith { 7478392ef1SBarry Smith PetscErrorCode ierr,(*r)(MatSNESMF); 7578392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 766831982aSBarry Smith PetscTruth match; 77a4d4d686SBarry Smith 78a4d4d686SBarry Smith PetscFunctionBegin; 794482741eSBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 804482741eSBarry Smith PetscValidCharPointer(ftype,2); 810f5bd95cSBarry Smith 829a6cb015SBarry Smith /* already set, so just return */ 836831982aSBarry Smith ierr = PetscTypeCompare((PetscObject)ctx,ftype,&match);CHKERRQ(ierr); 840f5bd95cSBarry Smith if (match) PetscFunctionReturn(0); 85a4d4d686SBarry Smith 869a6cb015SBarry Smith /* destroy the old one if it exists */ 879a6cb015SBarry Smith if (ctx->ops->destroy) { 889a6cb015SBarry Smith ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr); 899a6cb015SBarry Smith } 909a6cb015SBarry Smith 91b9617806SBarry Smith ierr = PetscFListFind(ctx->comm,MatSNESMPetscFList,ftype,(void (**)(void)) &r);CHKERRQ(ierr); 92958c9bccSBarry Smith if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown MatSNESMF type %s given",ftype); 939a6cb015SBarry Smith ierr = (*r)(ctx);CHKERRQ(ierr); 946831982aSBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)ctx,ftype);CHKERRQ(ierr); 959a6cb015SBarry Smith PetscFunctionReturn(0); 969a6cb015SBarry Smith } 979a6cb015SBarry Smith 986849ba73SBarry Smith typedef PetscErrorCode (*FCN1)(Vec,void*); /* force argument to next function to not be extern C*/ 99c5c390f1SBarry Smith EXTERN_C_BEGIN 10087828ca2SBarry Smith #undef __FUNCT__ 10187828ca2SBarry Smith #define __FUNCT__ "MatSNESMFSetFunctioniBase_FD" 10263dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetFunctioniBase_FD(Mat mat,FCN1 func) 10387828ca2SBarry Smith { 10478392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 10587828ca2SBarry Smith 10687828ca2SBarry Smith PetscFunctionBegin; 10787828ca2SBarry Smith ctx->funcisetbase = func; 10887828ca2SBarry Smith PetscFunctionReturn(0); 10987828ca2SBarry Smith } 110c5c390f1SBarry Smith EXTERN_C_END 11187828ca2SBarry Smith 112a7cc72afSBarry Smith typedef PetscErrorCode (*FCN2)(PetscInt,Vec,PetscScalar*,void*); /* force argument to next function to not be extern C*/ 113c5c390f1SBarry Smith EXTERN_C_BEGIN 11487828ca2SBarry Smith #undef __FUNCT__ 11587828ca2SBarry Smith #define __FUNCT__ "MatSNESMFSetFunctioni_FD" 11663dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetFunctioni_FD(Mat mat,FCN2 funci) 11787828ca2SBarry Smith { 11878392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 11987828ca2SBarry Smith 12087828ca2SBarry Smith PetscFunctionBegin; 12187828ca2SBarry Smith ctx->funci = funci; 12287828ca2SBarry Smith PetscFunctionReturn(0); 12387828ca2SBarry Smith } 124c5c390f1SBarry Smith EXTERN_C_END 12587828ca2SBarry Smith 1269a6cb015SBarry Smith 1274a2ae208SSatish Balay #undef __FUNCT__ 1284a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFRegister" 12978392ef1SBarry Smith PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(MatSNESMF)) 1309a6cb015SBarry Smith { 131dfbe8321SBarry Smith PetscErrorCode ierr; 132e2d1d2b7SBarry Smith char fullname[PETSC_MAX_PATH_LEN]; 1339a6cb015SBarry Smith 1349a6cb015SBarry Smith PetscFunctionBegin; 135b0a32e0cSBarry Smith ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 136c134de8dSSatish Balay ierr = PetscFListAdd(&MatSNESMPetscFList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr); 1379a6cb015SBarry Smith PetscFunctionReturn(0); 1389a6cb015SBarry Smith } 1399a6cb015SBarry Smith 1409a6cb015SBarry Smith 1414a2ae208SSatish Balay #undef __FUNCT__ 1424a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFRegisterDestroy" 1439a6cb015SBarry Smith /*@C 1445a655dc6SBarry Smith MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were 145f1af5d2fSBarry Smith registered by MatSNESMFRegisterDynamic). 1469a6cb015SBarry Smith 1479a6cb015SBarry Smith Not Collective 1489a6cb015SBarry Smith 14915091d37SBarry Smith Level: developer 15015091d37SBarry Smith 1515a655dc6SBarry Smith .keywords: MatSNESMF, register, destroy 1529a6cb015SBarry Smith 153f1af5d2fSBarry Smith .seealso: MatSNESMFRegisterDynamic), MatSNESMFRegisterAll() 1549a6cb015SBarry Smith @*/ 15563dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFRegisterDestroy(void) 1569a6cb015SBarry Smith { 157dfbe8321SBarry Smith PetscErrorCode ierr; 1589a6cb015SBarry Smith 1599a6cb015SBarry Smith PetscFunctionBegin; 1601441b1d3SBarry Smith ierr = PetscFListDestroy(&MatSNESMPetscFList);CHKERRQ(ierr); 1614c49b128SBarry Smith MatSNESMFRegisterAllCalled = PETSC_FALSE; 1629a6cb015SBarry Smith PetscFunctionReturn(0); 1639a6cb015SBarry Smith } 1649a6cb015SBarry Smith 1659a6cb015SBarry Smith /* ----------------------------------------------------------------------------------------*/ 1664a2ae208SSatish Balay #undef __FUNCT__ 1678a124369SBarry Smith #define __FUNCT__ "MatDestroy_MFFD" 168dfbe8321SBarry Smith PetscErrorCode MatDestroy_MFFD(Mat mat) 169a4d4d686SBarry Smith { 170dfbe8321SBarry Smith PetscErrorCode ierr; 17178392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 172fae171e0SBarry Smith 1733a40ed3dSBarry Smith PetscFunctionBegin; 174abc0a331SBarry Smith if (ctx->w) { 175b9fa9cd0SBarry Smith ierr = VecDestroy(ctx->w);CHKERRQ(ierr); 176ba6a83e5SMatthew Knepley } 1779a6cb015SBarry Smith if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);} 17874637425SBarry Smith if (ctx->sp) {ierr = MatNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);} 179d38fa0fbSBarry Smith ierr = PetscHeaderDestroy(ctx);CHKERRQ(ierr); 180901853e0SKris Buschelman 181901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatSNESMFSetBase_C","",PETSC_NULL);CHKERRQ(ierr); 182901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatSNESMFSetFunctioniBase_C","",PETSC_NULL);CHKERRQ(ierr); 183901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatSNESMFSetFunctioni_C","",PETSC_NULL);CHKERRQ(ierr); 184901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatSNESMFSetCheckh_C","",PETSC_NULL);CHKERRQ(ierr); 185901853e0SKris Buschelman 1863a40ed3dSBarry Smith PetscFunctionReturn(0); 187b9fa9cd0SBarry Smith } 18850361f65SLois Curfman McInnes 1894a2ae208SSatish Balay #undef __FUNCT__ 1908a124369SBarry Smith #define __FUNCT__ "MatView_MFFD" 19139e2f89bSBarry Smith /* 1928a124369SBarry Smith MatSNESMFView_MFFD - Views matrix-free parameters. 1938f6e3e37SBarry Smith 19439e2f89bSBarry Smith */ 195dfbe8321SBarry Smith PetscErrorCode MatView_MFFD(Mat J,PetscViewer viewer) 196eb9086c3SLois Curfman McInnes { 197dfbe8321SBarry Smith PetscErrorCode ierr; 19878392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)J->data; 19932077d6dSBarry Smith PetscTruth iascii; 200eb9086c3SLois Curfman McInnes 2013a40ed3dSBarry Smith PetscFunctionBegin; 20232077d6dSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 20332077d6dSBarry Smith if (iascii) { 204b0a32e0cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," SNES matrix-free approximation:\n");CHKERRQ(ierr); 205a83599f4SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," err=%G (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr); 206473c83c3SBarry Smith if (!ctx->type_name) { 207b0a32e0cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," The compute h routine has not yet been set\n");CHKERRQ(ierr); 208473c83c3SBarry Smith } else { 209b0a32e0cSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using %s compute h routine\n",ctx->type_name);CHKERRQ(ierr); 210473c83c3SBarry Smith } 2119a6cb015SBarry Smith if (ctx->ops->view) { 2129a6cb015SBarry Smith ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr); 2139a6cb015SBarry Smith } 2145cd90555SBarry Smith } else { 21579a5c55eSBarry Smith SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for SNES matrix free matrix",((PetscObject)viewer)->type_name); 216eb9086c3SLois Curfman McInnes } 2173a40ed3dSBarry Smith PetscFunctionReturn(0); 218eb9086c3SLois Curfman McInnes } 219eb9086c3SLois Curfman McInnes 2204a2ae208SSatish Balay #undef __FUNCT__ 2218a124369SBarry Smith #define __FUNCT__ "MatAssemblyEnd_MFFD" 222be726c96SBarry Smith /* 22332dfb669SBarry Smith MatAssemblyEnd_MFFD - Resets the ctx->ncurrenth to zero. This 22465f2ba5bSLois Curfman McInnes allows the user to indicate the beginning of a new linear solve by calling 225be726c96SBarry Smith MatAssemblyXXX() on the matrix free matrix. This then allows the 22665f2ba5bSLois Curfman McInnes MatSNESMFCreate_WP() to properly compute ||U|| only the first time 22765f2ba5bSLois Curfman McInnes in the linear solver rather than every time. 228be726c96SBarry Smith */ 229dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_MFFD(Mat J,MatAssemblyType mt) 230be726c96SBarry Smith { 231dfbe8321SBarry Smith PetscErrorCode ierr; 23278392ef1SBarry Smith MatSNESMF j = (MatSNESMF)J->data; 233be726c96SBarry Smith 234be726c96SBarry Smith PetscFunctionBegin; 2355a655dc6SBarry Smith ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr); 236b0a32e0cSBarry Smith if (j->usesnes) { 2371d1367b7SBarry Smith ierr = SNESGetSolution(j->snes,&j->current_u);CHKERRQ(ierr); 2381d1367b7SBarry Smith ierr = SNESGetFunction(j->snes,&j->current_f,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 239958c9bccSBarry Smith if (!j->w) { 2402740c1caSMatthew Knepley ierr = VecDuplicate(j->current_u, &j->w);CHKERRQ(ierr); 2412740c1caSMatthew Knepley } 2421d1367b7SBarry Smith } 243c5c390f1SBarry Smith j->vshift = 0.0; 244c5c390f1SBarry Smith j->vscale = 1.0; 245be726c96SBarry Smith PetscFunctionReturn(0); 246be726c96SBarry Smith } 247be726c96SBarry Smith 2484a2ae208SSatish Balay #undef __FUNCT__ 2498a124369SBarry Smith #define __FUNCT__ "MatMult_MFFD" 250eb9086c3SLois Curfman McInnes /* 251adb62b0dSMatthew Knepley MatMult_MFFD - Default matrix-free form for Jacobian-vector product, y = F'(u)*a: 252a4d4d686SBarry Smith 2539a6cb015SBarry Smith y ~= (F(u + ha) - F(u))/h, 254eb9086c3SLois Curfman McInnes where F = nonlinear function, as set by SNESSetFunction() 255eb9086c3SLois Curfman McInnes u = current iterate 256eb9086c3SLois Curfman McInnes h = difference interval 257eb9086c3SLois Curfman McInnes */ 258dfbe8321SBarry Smith PetscErrorCode MatMult_MFFD(Mat mat,Vec a,Vec y) 25939e2f89bSBarry Smith { 26078392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 261fae171e0SBarry Smith SNES snes; 262efb30889SBarry Smith PetscScalar h; 263fae171e0SBarry Smith Vec w,U,F; 264dfbe8321SBarry Smith PetscErrorCode ierr,(*eval_fct)(SNES,Vec,Vec)=0; 2654dc4c822SBarry Smith PetscTruth zeroa; 26639e2f89bSBarry Smith 2673a40ed3dSBarry Smith PetscFunctionBegin; 2689a6cb015SBarry Smith /* We log matrix-free matrix-vector products separately, so that we can 2699a6cb015SBarry Smith separate the performance monitoring from the cases that use conventional 2709a6cb015SBarry Smith storage. We may eventually modify event logging to associate events 2719a6cb015SBarry Smith with particular objects, hence alleviating the more general problem. */ 27246129b97SKris Buschelman ierr = PetscLogEventBegin(MATSNESMF_Mult,a,y,0,0);CHKERRQ(ierr); 27356cd22aeSBarry Smith 274fae171e0SBarry Smith snes = ctx->snes; 275fae171e0SBarry Smith w = ctx->w; 2761d1367b7SBarry Smith U = ctx->current_u; 27750361f65SLois Curfman McInnes 27885614651SBarry Smith /* 27985614651SBarry Smith Compute differencing parameter 28085614651SBarry Smith */ 2819a6cb015SBarry Smith if (!ctx->ops->compute) { 2822f859189SBarry Smith ierr = MatSNESMFSetType(mat,MATSNESMF_WP);CHKERRQ(ierr); 2835a655dc6SBarry Smith ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr); 2849a6cb015SBarry Smith } 2854dc4c822SBarry Smith ierr = (*ctx->ops->compute)(ctx,U,a,&h,&zeroa);CHKERRQ(ierr); 2864dc4c822SBarry Smith if (zeroa) { 28719bdad02SBarry Smith ierr = VecSet(y,0.0);CHKERRQ(ierr); 2884dc4c822SBarry Smith PetscFunctionReturn(0); 2894dc4c822SBarry Smith } 290a4d4d686SBarry Smith 2915b7f0c42SBarry Smith if (ctx->checkh) { 2925b7f0c42SBarry Smith ierr = (*ctx->checkh)(U,a,&h,ctx->checkhctx);CHKERRQ(ierr); 2935b7f0c42SBarry Smith } 2945b7f0c42SBarry Smith 295a4d4d686SBarry Smith /* keep a record of the current differencing parameter h */ 296a4d4d686SBarry Smith ctx->currenth = h; 297aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 298ae15b995SBarry Smith ierr = PetscInfo2(mat,"Current differencing parameter: %G + %G i\n",PetscRealPart(h),PetscImaginaryPart(h));CHKERRQ(ierr); 299a4d4d686SBarry Smith #else 300ae15b995SBarry Smith ierr = PetscInfo1(mat,"Current differencing parameter: %15.12e\n",h);CHKERRQ(ierr); 301a4d4d686SBarry Smith #endif 302a4d4d686SBarry Smith if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) { 30385614651SBarry Smith ctx->historyh[ctx->ncurrenth] = h; 304a4d4d686SBarry Smith } 30585614651SBarry Smith ctx->ncurrenth++; 306a4d4d686SBarry Smith 30785614651SBarry Smith /* w = u + ha */ 3082dcb1b2aSMatthew Knepley ierr = VecWAXPY(w,h,a,U);CHKERRQ(ierr); 30985614651SBarry Smith 310b0a32e0cSBarry Smith if (ctx->usesnes) { 31185614651SBarry Smith eval_fct = SNESComputeFunction; 3121d1367b7SBarry Smith F = ctx->current_f; 3131302d50aSBarry Smith if (!F) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"You must call MatAssembly() even on matrix-free matrices"); 31439903ad8SBarry Smith ierr = (*eval_fct)(snes,w,y);CHKERRQ(ierr); 31585614651SBarry Smith } else { 31685614651SBarry Smith F = ctx->funcvec; 31785614651SBarry Smith /* compute func(U) as base for differencing */ 31885614651SBarry Smith if (ctx->ncurrenth == 1) { 31985614651SBarry Smith ierr = (*ctx->func)(snes,U,F,ctx->funcctx);CHKERRQ(ierr); 32085614651SBarry Smith } 32185614651SBarry Smith ierr = (*ctx->func)(snes,w,y,ctx->funcctx);CHKERRQ(ierr); 32285614651SBarry Smith } 323a4d4d686SBarry Smith 324efb30889SBarry Smith ierr = VecAXPY(y,-1.0,F);CHKERRQ(ierr); 325efb30889SBarry Smith ierr = VecScale(y,1.0/h);CHKERRQ(ierr); 326c5c390f1SBarry Smith 3272dcb1b2aSMatthew Knepley ierr = VecAXPBY(y,ctx->vshift,ctx->vscale,a);CHKERRQ(ierr); 328c5c390f1SBarry Smith 32974637425SBarry Smith if (ctx->sp) {ierr = MatNullSpaceRemove(ctx->sp,y,PETSC_NULL);CHKERRQ(ierr);} 330a4d4d686SBarry Smith 33146129b97SKris Buschelman ierr = PetscLogEventEnd(MATSNESMF_Mult,a,y,0,0);CHKERRQ(ierr); 332a4d4d686SBarry Smith PetscFunctionReturn(0); 333a4d4d686SBarry Smith } 334a4d4d686SBarry Smith 3354a2ae208SSatish Balay #undef __FUNCT__ 3368a124369SBarry Smith #define __FUNCT__ "MatGetDiagonal_MFFD" 337cf57b110SBarry Smith /* 3388a124369SBarry Smith MatGetDiagonal_MFFD - Gets the diagonal for a matrix free matrix 339cf57b110SBarry Smith 340cf57b110SBarry Smith y ~= (F(u + ha) - F(u))/h, 341cf57b110SBarry Smith where F = nonlinear function, as set by SNESSetFunction() 342cf57b110SBarry Smith u = current iterate 343cf57b110SBarry Smith h = difference interval 344cf57b110SBarry Smith */ 345dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_MFFD(Mat mat,Vec a) 346cf57b110SBarry Smith { 34778392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 348ea709b57SSatish Balay PetscScalar h,*aa,*ww,v; 34977d8c4bbSBarry Smith PetscReal epsilon = PETSC_SQRT_MACHINE_EPSILON,umin = 100.0*PETSC_SQRT_MACHINE_EPSILON; 35065df01d8SBarry Smith Vec w,U; 3516849ba73SBarry Smith PetscErrorCode ierr; 352a7cc72afSBarry Smith PetscInt i,rstart,rend; 353cf57b110SBarry Smith 354cf57b110SBarry Smith PetscFunctionBegin; 355cf57b110SBarry Smith if (!ctx->funci) { 3561302d50aSBarry Smith SETERRQ(PETSC_ERR_ORDER,"Requires calling MatSNESMFSetFunctioni() first"); 357cf57b110SBarry Smith } 358cf57b110SBarry Smith 359cf57b110SBarry Smith w = ctx->w; 360cf57b110SBarry Smith U = ctx->current_u; 361cf57b110SBarry Smith ierr = (*ctx->func)(0,U,a,ctx->funcctx);CHKERRQ(ierr); 362cf57b110SBarry Smith ierr = (*ctx->funcisetbase)(U,ctx->funcctx);CHKERRQ(ierr); 363cf57b110SBarry Smith ierr = VecCopy(U,w);CHKERRQ(ierr); 364cf57b110SBarry Smith 365cf57b110SBarry Smith ierr = VecGetOwnershipRange(a,&rstart,&rend);CHKERRQ(ierr); 366cf57b110SBarry Smith ierr = VecGetArray(a,&aa);CHKERRQ(ierr); 367cf57b110SBarry Smith for (i=rstart; i<rend; i++) { 368cf57b110SBarry Smith ierr = VecGetArray(w,&ww);CHKERRQ(ierr); 369cf57b110SBarry Smith h = ww[i-rstart]; 370cf57b110SBarry Smith if (h == 0.0) h = 1.0; 371cf57b110SBarry Smith #if !defined(PETSC_USE_COMPLEX) 372cf57b110SBarry Smith if (h < umin && h >= 0.0) h = umin; 373cf57b110SBarry Smith else if (h < 0.0 && h > -umin) h = -umin; 374cf57b110SBarry Smith #else 375cf57b110SBarry Smith if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0) h = umin; 376cf57b110SBarry Smith else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin; 377cf57b110SBarry Smith #endif 378cf57b110SBarry Smith h *= epsilon; 379cf57b110SBarry Smith 380cf57b110SBarry Smith ww[i-rstart] += h; 381cf57b110SBarry Smith ierr = VecRestoreArray(w,&ww);CHKERRQ(ierr); 382cf57b110SBarry Smith ierr = (*ctx->funci)(i,w,&v,ctx->funcctx);CHKERRQ(ierr); 383cf57b110SBarry Smith aa[i-rstart] = (v - aa[i-rstart])/h; 384c5c390f1SBarry Smith 385c5c390f1SBarry Smith /* possibly shift and scale result */ 386c5c390f1SBarry Smith aa[i - rstart] = ctx->vshift + ctx->vscale*aa[i-rstart]; 387c5c390f1SBarry Smith 388cf57b110SBarry Smith ierr = VecGetArray(w,&ww);CHKERRQ(ierr); 389cf57b110SBarry Smith ww[i-rstart] -= h; 390cf57b110SBarry Smith ierr = VecRestoreArray(w,&ww);CHKERRQ(ierr); 391cf57b110SBarry Smith } 392cf57b110SBarry Smith ierr = VecRestoreArray(a,&aa);CHKERRQ(ierr); 393cf57b110SBarry Smith PetscFunctionReturn(0); 394cf57b110SBarry Smith } 395cf57b110SBarry Smith 396cf57b110SBarry Smith #undef __FUNCT__ 397c5c390f1SBarry Smith #define __FUNCT__ "MatShift_MFFD" 398f4df32b1SMatthew Knepley PetscErrorCode MatShift_MFFD(Mat Y,PetscScalar a) 399c5c390f1SBarry Smith { 40078392ef1SBarry Smith MatSNESMF shell = (MatSNESMF)Y->data; 401c5c390f1SBarry Smith PetscFunctionBegin; 402f4df32b1SMatthew Knepley shell->vshift += a; 403c5c390f1SBarry Smith PetscFunctionReturn(0); 404c5c390f1SBarry Smith } 405c5c390f1SBarry Smith 406c5c390f1SBarry Smith #undef __FUNCT__ 407c5c390f1SBarry Smith #define __FUNCT__ "MatScale_MFFD" 408f4df32b1SMatthew Knepley PetscErrorCode MatScale_MFFD(Mat Y,PetscScalar a) 409c5c390f1SBarry Smith { 41078392ef1SBarry Smith MatSNESMF shell = (MatSNESMF)Y->data; 411c5c390f1SBarry Smith PetscFunctionBegin; 412f4df32b1SMatthew Knepley shell->vscale *= a; 413c5c390f1SBarry Smith PetscFunctionReturn(0); 414c5c390f1SBarry Smith } 415c5c390f1SBarry Smith 416c5c390f1SBarry Smith 417c5c390f1SBarry Smith #undef __FUNCT__ 4184a2ae208SSatish Balay #define __FUNCT__ "MatCreateSNESMF" 41952baeb72SSatish Balay /*@ 42065f2ba5bSLois Curfman McInnes MatCreateSNESMF - Creates a matrix-free matrix context for use with 42165f2ba5bSLois Curfman McInnes a SNES solver. This matrix can be used as the Jacobian argument for 42265f2ba5bSLois Curfman McInnes the routine SNESSetJacobian(). 423a4d4d686SBarry Smith 424a4d4d686SBarry Smith Collective on SNES and Vec 425a4d4d686SBarry Smith 426a4d4d686SBarry Smith Input Parameters: 427a4d4d686SBarry Smith + snes - the SNES context 428a4d4d686SBarry Smith - x - vector where SNES solution is to be stored. 429a4d4d686SBarry Smith 430a4d4d686SBarry Smith Output Parameter: 431a4d4d686SBarry Smith . J - the matrix-free matrix 432a4d4d686SBarry Smith 43315091d37SBarry Smith Level: advanced 43415091d37SBarry Smith 435a4d4d686SBarry Smith Notes: 436a4d4d686SBarry Smith The matrix-free matrix context merely contains the function pointers 437a4d4d686SBarry Smith and work space for performing finite difference approximations of 43865f2ba5bSLois Curfman McInnes Jacobian-vector products, F'(u)*a, 4399a6cb015SBarry Smith 4409a6cb015SBarry Smith The default code uses the following approach to compute h 441a4d4d686SBarry Smith 442a4d4d686SBarry Smith .vb 44365f2ba5bSLois Curfman McInnes F'(u)*a = [F(u+h*a) - F(u)]/h where 444a4d4d686SBarry Smith h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 445a4d4d686SBarry Smith = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 446a4d4d686SBarry Smith where 447a4d4d686SBarry Smith error_rel = square root of relative error in function evaluation 448a4d4d686SBarry Smith umin = minimum iterate parameter 449a4d4d686SBarry Smith .ve 450efb30889SBarry Smith (see MATSNESMF_WP or MATSNESMF_DS) 451a4d4d686SBarry Smith 4525a655dc6SBarry Smith The user can set the error_rel via MatSNESMFSetFunctionError() and 45365f2ba5bSLois Curfman McInnes umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 45465f2ba5bSLois Curfman McInnes of the users manual for details. 455a4d4d686SBarry Smith 456a4d4d686SBarry Smith The user should call MatDestroy() when finished with the matrix-free 457a4d4d686SBarry Smith matrix context. 458a4d4d686SBarry Smith 459a4d4d686SBarry Smith Options Database Keys: 460a4d4d686SBarry Smith + -snes_mf_err <error_rel> - Sets error_rel 461efb30889SBarry Smith + -snes_mf_type - wp or ds (see MATSNESMF_WP or MATSNESMF_DS) 4629a6cb015SBarry Smith . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 463a4d4d686SBarry Smith - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 464a4d4d686SBarry Smith 465a4d4d686SBarry Smith .keywords: SNES, default, matrix-free, create, matrix 466a4d4d686SBarry Smith 4675a655dc6SBarry Smith .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin() 4681d1367b7SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateMF(), 469fed8bd04SBarry Smith MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic), MatSNESMFComputeJacobian() 470a4d4d686SBarry Smith 471a4d4d686SBarry Smith @*/ 47263dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatCreateSNESMF(SNES snes,Vec x,Mat *J) 473a4d4d686SBarry Smith { 47478392ef1SBarry Smith MatSNESMF mfctx; 475dfbe8321SBarry Smith PetscErrorCode ierr; 4761d1367b7SBarry Smith 4771d1367b7SBarry Smith PetscFunctionBegin; 4781d1367b7SBarry Smith ierr = MatCreateMF(x,J);CHKERRQ(ierr); 4797e9d5209SBarry Smith 48078392ef1SBarry Smith mfctx = (MatSNESMF)(*J)->data; 4811d1367b7SBarry Smith mfctx->snes = snes; 482b0a32e0cSBarry Smith mfctx->usesnes = PETSC_TRUE; 48352e6d16bSBarry Smith ierr = PetscLogObjectParent(snes,*J);CHKERRQ(ierr); 4841d1367b7SBarry Smith PetscFunctionReturn(0); 4851d1367b7SBarry Smith } 4861d1367b7SBarry Smith 487cf3bea43SBarry Smith EXTERN_C_BEGIN 488cf3bea43SBarry Smith #undef __FUNCT__ 489cf3bea43SBarry Smith #define __FUNCT__ "MatSNESMFSetBase_FD" 49063dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetBase_FD(Mat J,Vec U) 491cf3bea43SBarry Smith { 492dfbe8321SBarry Smith PetscErrorCode ierr; 49378392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)J->data; 494cf3bea43SBarry Smith 495cf3bea43SBarry Smith PetscFunctionBegin; 496cf3bea43SBarry Smith ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr); 497cf3bea43SBarry Smith ctx->current_u = U; 498cf3bea43SBarry Smith ctx->usesnes = PETSC_FALSE; 499958c9bccSBarry Smith if (!ctx->w) { 500ba6a83e5SMatthew Knepley ierr = VecDuplicate(ctx->current_u, &ctx->w);CHKERRQ(ierr); 501ba6a83e5SMatthew Knepley } 50232dfb669SBarry Smith J->assembled = PETSC_TRUE; 503cf3bea43SBarry Smith PetscFunctionReturn(0); 504cf3bea43SBarry Smith } 505cf3bea43SBarry Smith EXTERN_C_END 5066849ba73SBarry Smith typedef PetscErrorCode (*FCN3)(Vec,Vec,PetscScalar*,void*); /* force argument to next function to not be extern C*/ 5075b7f0c42SBarry Smith EXTERN_C_BEGIN 5085b7f0c42SBarry Smith #undef __FUNCT__ 5095b7f0c42SBarry Smith #define __FUNCT__ "MatSNESMFSetCheckh_FD" 51063dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetCheckh_FD(Mat J,FCN3 fun,void*ectx) 5115b7f0c42SBarry Smith { 51278392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)J->data; 5135b7f0c42SBarry Smith 5145b7f0c42SBarry Smith PetscFunctionBegin; 5155b7f0c42SBarry Smith ctx->checkh = fun; 5165b7f0c42SBarry Smith ctx->checkhctx = ectx; 5175b7f0c42SBarry Smith PetscFunctionReturn(0); 5185b7f0c42SBarry Smith } 5195b7f0c42SBarry Smith EXTERN_C_END 5205b7f0c42SBarry Smith 5214a2ae208SSatish Balay #undef __FUNCT__ 5227e9d5209SBarry Smith #define __FUNCT__ "MatSNESMFSetFromOptions" 5237e9d5209SBarry Smith /*@ 5247e9d5209SBarry Smith MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line 5257e9d5209SBarry Smith parameter. 5267e9d5209SBarry Smith 5277e9d5209SBarry Smith Collective on Mat 5287e9d5209SBarry Smith 5297e9d5209SBarry Smith Input Parameters: 5307e9d5209SBarry Smith . mat - the matrix obtained with MatCreateSNESMF() 5317e9d5209SBarry Smith 5327e9d5209SBarry Smith Options Database Keys: 533efb30889SBarry Smith + -snes_mf_type - wp or ds (see MATSNESMF_WP or MATSNESMF_DS) 5347e9d5209SBarry Smith - -snes_mf_err - square root of estimated relative error in function evaluation 5357e9d5209SBarry Smith - -snes_mf_period - how often h is recomputed, defaults to 1, everytime 5367e9d5209SBarry Smith 5377e9d5209SBarry Smith Level: advanced 5387e9d5209SBarry Smith 5397e9d5209SBarry Smith .keywords: SNES, matrix-free, parameters 5407e9d5209SBarry Smith 5417e9d5209SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 5427e9d5209SBarry Smith MatSNESMFResetHHistory(), MatSNESMFKSPMonitor() 5437e9d5209SBarry Smith @*/ 54463dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetFromOptions(Mat mat) 5457e9d5209SBarry Smith { 54678392ef1SBarry Smith MatSNESMF mfctx = (MatSNESMF)mat->data; 547dfbe8321SBarry Smith PetscErrorCode ierr; 5487e9d5209SBarry Smith PetscTruth flg; 5497e9d5209SBarry Smith char ftype[256]; 5507e9d5209SBarry Smith 5517e9d5209SBarry Smith PetscFunctionBegin; 5527e9d5209SBarry Smith if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 5537e9d5209SBarry Smith 5547e9d5209SBarry Smith ierr = PetscOptionsBegin(mfctx->comm,mfctx->prefix,"Set matrix free computation parameters","MatSNESMF");CHKERRQ(ierr); 5557e9d5209SBarry Smith ierr = PetscOptionsList("-snes_mf_type","Matrix free type","MatSNESMFSetType",MatSNESMPetscFList,mfctx->type_name,ftype,256,&flg);CHKERRQ(ierr); 5567e9d5209SBarry Smith if (flg) { 5577e9d5209SBarry Smith ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 5587e9d5209SBarry Smith } 5597e9d5209SBarry Smith 56087828ca2SBarry Smith ierr = PetscOptionsReal("-snes_mf_err","set sqrt relative error in function","MatSNESMFSetFunctionError",mfctx->error_rel,&mfctx->error_rel,0);CHKERRQ(ierr); 5617e9d5209SBarry Smith ierr = PetscOptionsInt("-snes_mf_period","how often h is recomputed","MatSNESMFSetPeriod",mfctx->recomputeperiod,&mfctx->recomputeperiod,0);CHKERRQ(ierr); 5627e9d5209SBarry Smith if (mfctx->snes) { 5637e9d5209SBarry Smith ierr = PetscOptionsName("-snes_mf_ksp_monitor","Monitor matrix-free parameters","MatSNESMFKSPMonitor",&flg);CHKERRQ(ierr); 5647e9d5209SBarry Smith if (flg) { 5657e9d5209SBarry Smith KSP ksp; 56694b7f48cSBarry Smith ierr = SNESGetKSP(mfctx->snes,&ksp);CHKERRQ(ierr); 567a6570f20SBarry Smith ierr = KSPMonitorSet(ksp,MatSNESMFKSPMonitor,PETSC_NULL,0);CHKERRQ(ierr); 5687e9d5209SBarry Smith } 5697e9d5209SBarry Smith } 5705b7f0c42SBarry Smith ierr = PetscOptionsName("-snes_mf_check_positivity","Insure that U + h*a is nonnegative","MatSNESMFSetCheckh",&flg);CHKERRQ(ierr); 5715b7f0c42SBarry Smith if (flg) { 5725b7f0c42SBarry Smith ierr = MatSNESMFSetCheckh(mat,MatSNESMFCheckPositivity,0);CHKERRQ(ierr); 5735b7f0c42SBarry Smith } 5747e9d5209SBarry Smith if (mfctx->ops->setfromoptions) { 5757e9d5209SBarry Smith ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 5767e9d5209SBarry Smith } 5777e9d5209SBarry Smith ierr = PetscOptionsEnd();CHKERRQ(ierr); 5787e9d5209SBarry Smith PetscFunctionReturn(0); 5797e9d5209SBarry Smith } 5807e9d5209SBarry Smith 5810bad9183SKris Buschelman /*MC 582fafad747SKris Buschelman MATMFFD - MATMFFD = "mffd" - A matrix free matrix type. 5830bad9183SKris Buschelman 5840bad9183SKris Buschelman Level: advanced 5850bad9183SKris Buschelman 5868bc8193eSBarry Smith .seealso: MatCreateMF(), MatCreateSNESMF() 5870bad9183SKris Buschelman M*/ 588fe93831dSBarry Smith EXTERN_C_BEGIN 5897e9d5209SBarry Smith #undef __FUNCT__ 5907e9d5209SBarry Smith #define __FUNCT__ "MatCreate_MFFD" 59163dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatCreate_MFFD(Mat A) 5927e9d5209SBarry Smith { 59378392ef1SBarry Smith MatSNESMF mfctx; 594dfbe8321SBarry Smith PetscErrorCode ierr; 5957e9d5209SBarry Smith 5967e9d5209SBarry Smith PetscFunctionBegin; 5976e087cb5SMatthew Knepley #ifndef PETSC_USE_DYNAMIC_LIBRARIES 5986e087cb5SMatthew Knepley ierr = SNESInitializePackage(PETSC_NULL);CHKERRQ(ierr); 5996e087cb5SMatthew Knepley #endif 6006e087cb5SMatthew Knepley 60178392ef1SBarry Smith ierr = PetscHeaderCreate(mfctx,_p_MatSNESMF,struct _MFOps,MATSNESMFCTX_COOKIE,0,"SNESMF",A->comm,MatDestroy_MFFD,MatView_MFFD);CHKERRQ(ierr); 6027e9d5209SBarry Smith mfctx->sp = 0; 6037e9d5209SBarry Smith mfctx->snes = 0; 60477d8c4bbSBarry Smith mfctx->error_rel = PETSC_SQRT_MACHINE_EPSILON; 6057e9d5209SBarry Smith mfctx->recomputeperiod = 1; 6067e9d5209SBarry Smith mfctx->count = 0; 6077e9d5209SBarry Smith mfctx->currenth = 0.0; 6087e9d5209SBarry Smith mfctx->historyh = PETSC_NULL; 6097e9d5209SBarry Smith mfctx->ncurrenth = 0; 6107e9d5209SBarry Smith mfctx->maxcurrenth = 0; 6117e9d5209SBarry Smith mfctx->type_name = 0; 6127e9d5209SBarry Smith mfctx->usesnes = PETSC_FALSE; 6137e9d5209SBarry Smith 614c5c390f1SBarry Smith mfctx->vshift = 0.0; 615c5c390f1SBarry Smith mfctx->vscale = 1.0; 616c5c390f1SBarry Smith 6177e9d5209SBarry Smith /* 6187e9d5209SBarry Smith Create the empty data structure to contain compute-h routines. 6197e9d5209SBarry Smith These will be filled in below from the command line options or 6207e9d5209SBarry Smith a later call with MatSNESMFSetType() or if that is not called 6218a124369SBarry Smith then it will default in the first use of MatMult_MFFD() 6227e9d5209SBarry Smith */ 6237e9d5209SBarry Smith mfctx->ops->compute = 0; 6247e9d5209SBarry Smith mfctx->ops->destroy = 0; 6257e9d5209SBarry Smith mfctx->ops->view = 0; 6267e9d5209SBarry Smith mfctx->ops->setfromoptions = 0; 6277e9d5209SBarry Smith mfctx->hctx = 0; 6287e9d5209SBarry Smith 6297e9d5209SBarry Smith mfctx->func = 0; 6307e9d5209SBarry Smith mfctx->funcctx = 0; 6317e9d5209SBarry Smith mfctx->funcvec = 0; 632ba6a83e5SMatthew Knepley mfctx->w = PETSC_NULL; 6337e9d5209SBarry Smith 63465df01d8SBarry Smith A->data = mfctx; 6357e9d5209SBarry Smith 6368a124369SBarry Smith A->ops->mult = MatMult_MFFD; 6378a124369SBarry Smith A->ops->destroy = MatDestroy_MFFD; 6388a124369SBarry Smith A->ops->view = MatView_MFFD; 6398a124369SBarry Smith A->ops->assemblyend = MatAssemblyEnd_MFFD; 6408a124369SBarry Smith A->ops->getdiagonal = MatGetDiagonal_MFFD; 641c5c390f1SBarry Smith A->ops->scale = MatScale_MFFD; 642c5c390f1SBarry Smith A->ops->shift = MatShift_MFFD; 64365df01d8SBarry Smith A->ops->setfromoptions = MatSNESMFSetFromOptions; 64432dfb669SBarry Smith A->assembled = PETSC_TRUE; 6457e9d5209SBarry Smith 64665df01d8SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSNESMFSetBase_C","MatSNESMFSetBase_FD",MatSNESMFSetBase_FD);CHKERRQ(ierr); 647c5c390f1SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSNESMFSetFunctioniBase_C","MatSNESMFSetFunctioniBase_FD",MatSNESMFSetFunctioniBase_FD);CHKERRQ(ierr); 64887828ca2SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSNESMFSetFunctioni_C","MatSNESMFSetFunctioni_FD",MatSNESMFSetFunctioni_FD);CHKERRQ(ierr); 6495b7f0c42SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSNESMFSetCheckh_C","MatSNESMFSetCheckh_FD",MatSNESMFSetCheckh_FD);CHKERRQ(ierr); 65065df01d8SBarry Smith mfctx->mat = A; 65117667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)A,MATMFFD);CHKERRQ(ierr); 6527e9d5209SBarry Smith PetscFunctionReturn(0); 6537e9d5209SBarry Smith } 654fe93831dSBarry Smith EXTERN_C_END 6557e9d5209SBarry Smith 6567e9d5209SBarry Smith #undef __FUNCT__ 6574a2ae208SSatish Balay #define __FUNCT__ "MatCreateMF" 65852baeb72SSatish Balay /*@ 6591d1367b7SBarry Smith MatCreateMF - Creates a matrix-free matrix. See also MatCreateSNESMF() 6601d1367b7SBarry Smith 6611d1367b7SBarry Smith Collective on Vec 6621d1367b7SBarry Smith 6631d1367b7SBarry Smith Input Parameters: 6641d1367b7SBarry Smith . x - vector that defines layout of the vectors and matrices 6651d1367b7SBarry Smith 6661d1367b7SBarry Smith Output Parameter: 6671d1367b7SBarry Smith . J - the matrix-free matrix 6681d1367b7SBarry Smith 6691d1367b7SBarry Smith Level: advanced 6701d1367b7SBarry Smith 6711d1367b7SBarry Smith Notes: 6721d1367b7SBarry Smith The matrix-free matrix context merely contains the function pointers 6731d1367b7SBarry Smith and work space for performing finite difference approximations of 6741d1367b7SBarry Smith Jacobian-vector products, F'(u)*a, 6751d1367b7SBarry Smith 6761d1367b7SBarry Smith The default code uses the following approach to compute h 6771d1367b7SBarry Smith 6781d1367b7SBarry Smith .vb 6791d1367b7SBarry Smith F'(u)*a = [F(u+h*a) - F(u)]/h where 6801d1367b7SBarry Smith h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 6811d1367b7SBarry Smith = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 6821d1367b7SBarry Smith where 6831d1367b7SBarry Smith error_rel = square root of relative error in function evaluation 6841d1367b7SBarry Smith umin = minimum iterate parameter 6851d1367b7SBarry Smith .ve 6861d1367b7SBarry Smith 6871d1367b7SBarry Smith The user can set the error_rel via MatSNESMFSetFunctionError() and 6881d1367b7SBarry Smith umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 6891d1367b7SBarry Smith of the users manual for details. 6901d1367b7SBarry Smith 6911d1367b7SBarry Smith The user should call MatDestroy() when finished with the matrix-free 6921d1367b7SBarry Smith matrix context. 6931d1367b7SBarry Smith 6941d1367b7SBarry Smith Options Database Keys: 6951d1367b7SBarry Smith + -snes_mf_err <error_rel> - Sets error_rel 6961d1367b7SBarry Smith . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 6975b7f0c42SBarry Smith . -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 6985b7f0c42SBarry Smith - -snes_mf_check_positivity 6991d1367b7SBarry Smith 7001d1367b7SBarry Smith .keywords: default, matrix-free, create, matrix 7011d1367b7SBarry Smith 7026ce558aeSBarry Smith .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin(), MatSNESMFSetFunction() 7031d1367b7SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateSNESMF(), 704fed8bd04SBarry Smith MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic),, MatSNESMFComputeJacobian() 7051d1367b7SBarry Smith 7061d1367b7SBarry Smith @*/ 70763dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatCreateMF(Vec x,Mat *J) 7081d1367b7SBarry Smith { 709a4d4d686SBarry Smith MPI_Comm comm; 7106849ba73SBarry Smith PetscErrorCode ierr; 711a7cc72afSBarry Smith PetscInt n,nloc; 712a4d4d686SBarry Smith 713a4d4d686SBarry Smith PetscFunctionBegin; 7141d1367b7SBarry Smith ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); 71565df01d8SBarry Smith ierr = VecGetSize(x,&n);CHKERRQ(ierr); 71665df01d8SBarry Smith ierr = VecGetLocalSize(x,&nloc);CHKERRQ(ierr); 717f69a0ea3SMatthew Knepley ierr = MatCreate(comm,J);CHKERRQ(ierr); 718f69a0ea3SMatthew Knepley ierr = MatSetSizes(*J,nloc,nloc,n,n);CHKERRQ(ierr); 719e56c5435SBarry Smith ierr = MatRegisterDynamic(MATMFFD,0,"MatCreate_MFFD",MatCreate_MFFD);CHKERRQ(ierr); 72065df01d8SBarry Smith ierr = MatSetType(*J,MATMFFD);CHKERRQ(ierr); 7219a6cb015SBarry Smith PetscFunctionReturn(0); 7229a6cb015SBarry Smith } 7239a6cb015SBarry Smith 724a4d4d686SBarry Smith 7254a2ae208SSatish Balay #undef __FUNCT__ 7264a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFGetH" 727a4d4d686SBarry Smith /*@ 72865f2ba5bSLois Curfman McInnes MatSNESMFGetH - Gets the last value that was used as the differencing 729a4d4d686SBarry Smith parameter. 730a4d4d686SBarry Smith 731a4d4d686SBarry Smith Not Collective 732a4d4d686SBarry Smith 733a4d4d686SBarry Smith Input Parameters: 7345a655dc6SBarry Smith . mat - the matrix obtained with MatCreateSNESMF() 735a4d4d686SBarry Smith 736a4d4d686SBarry Smith Output Paramter: 737a4d4d686SBarry Smith . h - the differencing step size 738a4d4d686SBarry Smith 73915091d37SBarry Smith Level: advanced 74015091d37SBarry Smith 741a4d4d686SBarry Smith .keywords: SNES, matrix-free, parameters 742a4d4d686SBarry Smith 7435a655dc6SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 7445a655dc6SBarry Smith MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 745a4d4d686SBarry Smith @*/ 74663dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFGetH(Mat mat,PetscScalar *h) 747a4d4d686SBarry Smith { 74878392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 749a4d4d686SBarry Smith 750a4d4d686SBarry Smith PetscFunctionBegin; 751a4d4d686SBarry Smith *h = ctx->currenth; 752a4d4d686SBarry Smith PetscFunctionReturn(0); 753a4d4d686SBarry Smith } 754a4d4d686SBarry Smith 7554a2ae208SSatish Balay #undef __FUNCT__ 7564a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFKSPMonitor" 757906ed7ccSBarry Smith /*@C 758906ed7ccSBarry Smith MatSNESMFKSPMonitor - A KSP monitor for use with the PETSc 75965f2ba5bSLois Curfman McInnes SNES matrix free routines. Prints the differencing parameter used at 76065f2ba5bSLois Curfman McInnes each step. 761906ed7ccSBarry Smith 762906ed7ccSBarry Smith Collective on KSP 763906ed7ccSBarry Smith 764906ed7ccSBarry Smith Input Parameters: 765906ed7ccSBarry Smith + ksp - the Krylov solver object 766906ed7ccSBarry Smith . n - the current iteration 767906ed7ccSBarry Smith . rnorm - the current residual norm (may be preconditioned or not depending on solver and options 768906ed7ccSBarry Smith _ dummy - unused argument 769906ed7ccSBarry Smith 770906ed7ccSBarry Smith Options Database: 771906ed7ccSBarry Smith . -snes_mf_ksp_monitor - turn this monitor on 772906ed7ccSBarry Smith 773a6570f20SBarry Smith Notes: Use KSPMonitorSet(ksp,MatSNESMFKSPMonitor,PETSC_NULL,PETSC_NULL); 774906ed7ccSBarry Smith 775a6570f20SBarry Smith .seealso: KSPMonitorSet() 776906ed7ccSBarry Smith 777906ed7ccSBarry Smith @*/ 77863dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFKSPMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy) 779a4d4d686SBarry Smith { 78078392ef1SBarry Smith MatSNESMF ctx; 781dfbe8321SBarry Smith PetscErrorCode ierr; 782a4d4d686SBarry Smith Mat mat; 783a4d4d686SBarry Smith MPI_Comm comm; 784a4d4d686SBarry Smith PetscTruth nonzeroinitialguess; 785a4d4d686SBarry Smith 786a4d4d686SBarry Smith PetscFunctionBegin; 787a4d4d686SBarry Smith ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 788a4d4d686SBarry Smith ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 789906ed7ccSBarry Smith ierr = KSPGetOperators(ksp,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 79078392ef1SBarry Smith ctx = (MatSNESMF)mat->data; 7917e9d5209SBarry Smith 792a4d4d686SBarry Smith if (n > 0 || nonzeroinitialguess) { 793aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 794a83599f4SBarry Smith ierr = PetscPrintf(comm,"%D KSP Residual norm %14.12e h %G + %G i\n",n,rnorm, 795329f5518SBarry Smith PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));CHKERRQ(ierr); 796a4d4d686SBarry Smith #else 797a83599f4SBarry Smith ierr = PetscPrintf(comm,"%D KSP Residual norm %14.12e h %G \n",n,rnorm,ctx->currenth);CHKERRQ(ierr); 798a4d4d686SBarry Smith #endif 799a4d4d686SBarry Smith } else { 80077431f27SBarry Smith ierr = PetscPrintf(comm,"%D KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); 801a4d4d686SBarry Smith } 802a4d4d686SBarry Smith PetscFunctionReturn(0); 803a4d4d686SBarry Smith } 804a4d4d686SBarry Smith 8054a2ae208SSatish Balay #undef __FUNCT__ 8064a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetFunction" 80785614651SBarry Smith /*@C 80885614651SBarry Smith MatSNESMFSetFunction - Sets the function used in applying the matrix free. 80985614651SBarry Smith 81085614651SBarry Smith Collective on Mat 81185614651SBarry Smith 81285614651SBarry Smith Input Parameters: 81385614651SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 81485614651SBarry Smith . v - workspace vector 81585614651SBarry Smith . func - the function to use 81685614651SBarry Smith - funcctx - optional function context passed to function 81785614651SBarry Smith 81885614651SBarry Smith Level: advanced 81985614651SBarry Smith 82085614651SBarry Smith Notes: 82185614651SBarry Smith If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 82285614651SBarry Smith matrix inside your compute Jacobian routine 82385614651SBarry Smith 82485614651SBarry Smith If this is not set then it will use the function set with SNESSetFunction() 82585614651SBarry Smith 82685614651SBarry Smith .keywords: SNES, matrix-free, function 82785614651SBarry Smith 82885614651SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 82985614651SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 83085614651SBarry Smith MatSNESMFKSPMonitor(), SNESetFunction() 83185614651SBarry Smith @*/ 83263dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetFunction(Mat mat,Vec v,PetscErrorCode (*func)(SNES,Vec,Vec,void *),void *funcctx) 83385614651SBarry Smith { 83478392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 83585614651SBarry Smith 83685614651SBarry Smith PetscFunctionBegin; 83785614651SBarry Smith ctx->func = func; 83885614651SBarry Smith ctx->funcctx = funcctx; 83985614651SBarry Smith ctx->funcvec = v; 84085614651SBarry Smith PetscFunctionReturn(0); 84185614651SBarry Smith } 84285614651SBarry Smith 843cf57b110SBarry Smith #undef __FUNCT__ 844cf57b110SBarry Smith #define __FUNCT__ "MatSNESMFSetFunctioni" 845cf57b110SBarry Smith /*@C 846cf57b110SBarry Smith MatSNESMFSetFunctioni - Sets the function for a single component 847cf57b110SBarry Smith 848cf57b110SBarry Smith Collective on Mat 849cf57b110SBarry Smith 850cf57b110SBarry Smith Input Parameters: 851cf57b110SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 852cf57b110SBarry Smith - funci - the function to use 853cf57b110SBarry Smith 854cf57b110SBarry Smith Level: advanced 855cf57b110SBarry Smith 856cf57b110SBarry Smith Notes: 857cf57b110SBarry Smith If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 858cf57b110SBarry Smith matrix inside your compute Jacobian routine 859cf57b110SBarry Smith 860cf57b110SBarry Smith 861cf57b110SBarry Smith .keywords: SNES, matrix-free, function 862cf57b110SBarry Smith 863cf57b110SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 864cf57b110SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 865cf57b110SBarry Smith MatSNESMFKSPMonitor(), SNESetFunction() 866cf57b110SBarry Smith @*/ 86763dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetFunctioni(Mat mat,PetscErrorCode (*funci)(PetscInt,Vec,PetscScalar*,void *)) 868cf57b110SBarry Smith { 869a7cc72afSBarry Smith PetscErrorCode ierr,(*f)(Mat,PetscErrorCode (*)(PetscInt,Vec,PetscScalar*,void *)); 870cf57b110SBarry Smith 871cf57b110SBarry Smith PetscFunctionBegin; 8724482741eSBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 873c134de8dSSatish Balay ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSNESMFSetFunctioni_C",(void (**)(void))&f);CHKERRQ(ierr); 87487828ca2SBarry Smith if (f) { 87587828ca2SBarry Smith ierr = (*f)(mat,funci);CHKERRQ(ierr); 87687828ca2SBarry Smith } 877cf57b110SBarry Smith PetscFunctionReturn(0); 878cf57b110SBarry Smith } 879cf57b110SBarry Smith 88087828ca2SBarry Smith 881cf57b110SBarry Smith #undef __FUNCT__ 882cf57b110SBarry Smith #define __FUNCT__ "MatSNESMFSetFunctioniBase" 883cf57b110SBarry Smith /*@C 884cf57b110SBarry Smith MatSNESMFSetFunctioniBase - Sets the base vector for a single component function evaluation 885cf57b110SBarry Smith 886cf57b110SBarry Smith Collective on Mat 887cf57b110SBarry Smith 888cf57b110SBarry Smith Input Parameters: 889cf57b110SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 890cf57b110SBarry Smith - func - the function to use 891cf57b110SBarry Smith 892cf57b110SBarry Smith Level: advanced 893cf57b110SBarry Smith 894cf57b110SBarry Smith Notes: 895cf57b110SBarry Smith If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 896cf57b110SBarry Smith matrix inside your compute Jacobian routine 897cf57b110SBarry Smith 898cf57b110SBarry Smith 899cf57b110SBarry Smith .keywords: SNES, matrix-free, function 900cf57b110SBarry Smith 901cf57b110SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 902cf57b110SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 903cf57b110SBarry Smith MatSNESMFKSPMonitor(), SNESetFunction() 904cf57b110SBarry Smith @*/ 90563dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetFunctioniBase(Mat mat,PetscErrorCode (*func)(Vec,void *)) 906cf57b110SBarry Smith { 9076849ba73SBarry Smith PetscErrorCode ierr,(*f)(Mat,PetscErrorCode (*)(Vec,void *)); 908cf57b110SBarry Smith 909cf57b110SBarry Smith PetscFunctionBegin; 9104482741eSBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 911c134de8dSSatish Balay ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSNESMFSetFunctioniBase_C",(void (**)(void))&f);CHKERRQ(ierr); 91287828ca2SBarry Smith if (f) { 91387828ca2SBarry Smith ierr = (*f)(mat,func);CHKERRQ(ierr); 91487828ca2SBarry Smith } 915cf57b110SBarry Smith PetscFunctionReturn(0); 916cf57b110SBarry Smith } 917cf57b110SBarry Smith 91885614651SBarry Smith 9194a2ae208SSatish Balay #undef __FUNCT__ 9204a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetPeriod" 921329f5518SBarry Smith /*@ 922329f5518SBarry Smith MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime 923329f5518SBarry Smith 924329f5518SBarry Smith Collective on Mat 925329f5518SBarry Smith 926329f5518SBarry Smith Input Parameters: 927329f5518SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 928329f5518SBarry Smith - period - 1 for everytime, 2 for every second etc 929329f5518SBarry Smith 930329f5518SBarry Smith Options Database Keys: 931329f5518SBarry Smith + -snes_mf_period <period> 932329f5518SBarry Smith 933329f5518SBarry Smith Level: advanced 934329f5518SBarry Smith 935329f5518SBarry Smith 936329f5518SBarry Smith .keywords: SNES, matrix-free, parameters 937329f5518SBarry Smith 938329f5518SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 939329f5518SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 940329f5518SBarry Smith MatSNESMFKSPMonitor() 941329f5518SBarry Smith @*/ 94263dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetPeriod(Mat mat,PetscInt period) 943329f5518SBarry Smith { 94478392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 945329f5518SBarry Smith 946329f5518SBarry Smith PetscFunctionBegin; 947329f5518SBarry Smith ctx->recomputeperiod = period; 948329f5518SBarry Smith PetscFunctionReturn(0); 949329f5518SBarry Smith } 950329f5518SBarry Smith 9514a2ae208SSatish Balay #undef __FUNCT__ 9524a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetFunctionError" 953a4d4d686SBarry Smith /*@ 9545a655dc6SBarry Smith MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 955a4d4d686SBarry Smith matrix-vector products using finite differences. 956a4d4d686SBarry Smith 957a4d4d686SBarry Smith Collective on Mat 958a4d4d686SBarry Smith 959a4d4d686SBarry Smith Input Parameters: 9605a655dc6SBarry Smith + mat - the matrix free matrix created via MatCreateSNESMF() 9619a6cb015SBarry Smith - error_rel - relative error (should be set to the square root of 962a4d4d686SBarry Smith the relative error in the function evaluations) 963a4d4d686SBarry Smith 96415091d37SBarry Smith Options Database Keys: 96515091d37SBarry Smith + -snes_mf_err <error_rel> - Sets error_rel 96615091d37SBarry Smith 96715091d37SBarry Smith Level: advanced 96815091d37SBarry Smith 969a4d4d686SBarry Smith Notes: 970a4d4d686SBarry Smith The default matrix-free matrix-vector product routine computes 971a4d4d686SBarry Smith .vb 97265f2ba5bSLois Curfman McInnes F'(u)*a = [F(u+h*a) - F(u)]/h where 973a4d4d686SBarry Smith h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 974a4d4d686SBarry Smith = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 975a4d4d686SBarry Smith .ve 976a4d4d686SBarry Smith 977a4d4d686SBarry Smith .keywords: SNES, matrix-free, parameters 978a4d4d686SBarry Smith 9795a655dc6SBarry Smith .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 9805a655dc6SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 9815a655dc6SBarry Smith MatSNESMFKSPMonitor() 982a4d4d686SBarry Smith @*/ 98363dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetFunctionError(Mat mat,PetscReal error) 984a4d4d686SBarry Smith { 98578392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)mat->data; 986a4d4d686SBarry Smith 987a4d4d686SBarry Smith PetscFunctionBegin; 988a4d4d686SBarry Smith if (error != PETSC_DEFAULT) ctx->error_rel = error; 989a4d4d686SBarry Smith PetscFunctionReturn(0); 990a4d4d686SBarry Smith } 991a4d4d686SBarry Smith 9924a2ae208SSatish Balay #undef __FUNCT__ 9934a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFAddNullSpace" 994a4d4d686SBarry Smith /*@ 99565f2ba5bSLois Curfman McInnes MatSNESMFAddNullSpace - Provides a null space that an operator is 99665f2ba5bSLois Curfman McInnes supposed to have. Since roundoff will create a small component in 99765f2ba5bSLois Curfman McInnes the null space, if you know the null space you may have it 99865f2ba5bSLois Curfman McInnes automatically removed. 999a4d4d686SBarry Smith 1000a4d4d686SBarry Smith Collective on Mat 1001a4d4d686SBarry Smith 1002a4d4d686SBarry Smith Input Parameters: 1003a4d4d686SBarry Smith + J - the matrix-free matrix context 100474637425SBarry Smith - nullsp - object created with MatNullSpaceCreate() 1005a4d4d686SBarry Smith 100615091d37SBarry Smith Level: advanced 100715091d37SBarry Smith 1008a4d4d686SBarry Smith .keywords: SNES, matrix-free, null space 1009a4d4d686SBarry Smith 101074637425SBarry Smith .seealso: MatNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(), 10115a655dc6SBarry Smith MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 10125a655dc6SBarry Smith MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 1013a4d4d686SBarry Smith @*/ 101463dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFAddNullSpace(Mat J,MatNullSpace nullsp) 1015a4d4d686SBarry Smith { 1016dfbe8321SBarry Smith PetscErrorCode ierr; 101778392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)J->data; 1018a4d4d686SBarry Smith 1019a4d4d686SBarry Smith PetscFunctionBegin; 102085614651SBarry Smith ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 1021c3122656SLisandro Dalcin if (ctx->sp) { ierr = MatNullSpaceDestroy(ctx->sp);CHKERRQ(ierr); } 1022c3122656SLisandro Dalcin ctx->sp = nullsp; 1023a4d4d686SBarry Smith PetscFunctionReturn(0); 1024a4d4d686SBarry Smith } 1025a4d4d686SBarry Smith 10264a2ae208SSatish Balay #undef __FUNCT__ 10274a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetHHistory" 1028a4d4d686SBarry Smith /*@ 102965f2ba5bSLois Curfman McInnes MatSNESMFSetHHistory - Sets an array to collect a history of the 103065f2ba5bSLois Curfman McInnes differencing values (h) computed for the matrix-free product. 1031a4d4d686SBarry Smith 1032a4d4d686SBarry Smith Collective on Mat 1033a4d4d686SBarry Smith 1034a4d4d686SBarry Smith Input Parameters: 1035a4d4d686SBarry Smith + J - the matrix-free matrix context 103665f2ba5bSLois Curfman McInnes . histroy - space to hold the history 103765f2ba5bSLois Curfman McInnes - nhistory - number of entries in history, if more entries are generated than 103865f2ba5bSLois Curfman McInnes nhistory, then the later ones are discarded 1039a4d4d686SBarry Smith 104015091d37SBarry Smith Level: advanced 104115091d37SBarry Smith 1042a4d4d686SBarry Smith Notes: 104365f2ba5bSLois Curfman McInnes Use MatSNESMFResetHHistory() to reset the history counter and collect 104465f2ba5bSLois Curfman McInnes a new batch of differencing parameters, h. 1045a4d4d686SBarry Smith 1046a4d4d686SBarry Smith .keywords: SNES, matrix-free, h history, differencing history 1047a4d4d686SBarry Smith 10485a655dc6SBarry Smith .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 10495a655dc6SBarry Smith MatSNESMFResetHHistory(), 10505a655dc6SBarry Smith MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 1051a4d4d686SBarry Smith 1052a4d4d686SBarry Smith @*/ 105363dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetHHistory(Mat J,PetscScalar history[],PetscInt nhistory) 1054a4d4d686SBarry Smith { 105578392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)J->data; 1056a4d4d686SBarry Smith 1057a4d4d686SBarry Smith PetscFunctionBegin; 1058a4d4d686SBarry Smith ctx->historyh = history; 1059a4d4d686SBarry Smith ctx->maxcurrenth = nhistory; 1060a4d4d686SBarry Smith ctx->currenth = 0; 1061a4d4d686SBarry Smith PetscFunctionReturn(0); 1062a4d4d686SBarry Smith } 1063a4d4d686SBarry Smith 10644a2ae208SSatish Balay #undef __FUNCT__ 10654a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFResetHHistory" 1066a4d4d686SBarry Smith /*@ 10675a655dc6SBarry Smith MatSNESMFResetHHistory - Resets the counter to zero to begin 1068a4d4d686SBarry Smith collecting a new set of differencing histories. 1069a4d4d686SBarry Smith 1070a4d4d686SBarry Smith Collective on Mat 1071a4d4d686SBarry Smith 1072a4d4d686SBarry Smith Input Parameters: 1073a4d4d686SBarry Smith . J - the matrix-free matrix context 1074a4d4d686SBarry Smith 107515091d37SBarry Smith Level: advanced 107615091d37SBarry Smith 1077a4d4d686SBarry Smith Notes: 107865f2ba5bSLois Curfman McInnes Use MatSNESMFSetHHistory() to create the original history counter. 1079a4d4d686SBarry Smith 1080a4d4d686SBarry Smith .keywords: SNES, matrix-free, h history, differencing history 1081a4d4d686SBarry Smith 10825a655dc6SBarry Smith .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 10835a655dc6SBarry Smith MatSNESMFSetHHistory(), 10845a655dc6SBarry Smith MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 1085a4d4d686SBarry Smith 1086a4d4d686SBarry Smith @*/ 108763dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFResetHHistory(Mat J) 1088a4d4d686SBarry Smith { 108978392ef1SBarry Smith MatSNESMF ctx = (MatSNESMF)J->data; 1090a4d4d686SBarry Smith 1091a4d4d686SBarry Smith PetscFunctionBegin; 1092be726c96SBarry Smith ctx->ncurrenth = 0; 1093a4d4d686SBarry Smith PetscFunctionReturn(0); 1094a4d4d686SBarry Smith } 1095a4d4d686SBarry Smith 10964a2ae208SSatish Balay #undef __FUNCT__ 1097fed8bd04SBarry Smith #define __FUNCT__ "MatSNESMFComputeJacobian" 10983960baedSBarry Smith /*@ 10993960baedSBarry Smith MatSNESMFComputeJacobian - Tells the matrix-free Jacobian object the new location at which 11003960baedSBarry Smith Jacobian matrix vector products will be computed at, i.e. J(x) * a. 11013960baedSBarry Smith 11023960baedSBarry Smith Collective on SNES 11033960baedSBarry Smith 11043960baedSBarry Smith Input Parameters: 11053960baedSBarry Smith + snes - the nonlinear solver context 11063960baedSBarry Smith . x - the point at which the Jacobian vector products will be performed 11073960baedSBarry Smith . jac - the matrix-free Jacobian object 11083960baedSBarry Smith . B - either the same as jac or another matrix type (ignored) 11093960baedSBarry Smith . flag - not relevent for matrix-free form 11103960baedSBarry Smith - dummy - the user context (ignored) 11113960baedSBarry Smith 11123960baedSBarry Smith Level: developer 11133960baedSBarry Smith 11143960baedSBarry Smith Notes: 11153960baedSBarry Smith This can be passed into SNESSetJacobian() when using a completely matrix-free solver, 11163960baedSBarry Smith that is the B matrix is also the same matrix operator. This is used when you select 11173960baedSBarry Smith -snes_mf but rarely used directly by users. 11183960baedSBarry Smith 11193960baedSBarry Smith .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 11203960baedSBarry Smith MatSNESMFSetHHistory(), 11213960baedSBarry Smith MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError(), MatSNESMFCreate(), SNESSetJacobian() 11223960baedSBarry Smith 11233960baedSBarry Smith @*/ 112463dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFComputeJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy) 11251d1367b7SBarry Smith { 1126dfbe8321SBarry Smith PetscErrorCode ierr; 11271d1367b7SBarry Smith PetscFunctionBegin; 11281d1367b7SBarry Smith ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11291d1367b7SBarry Smith ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11301d1367b7SBarry Smith PetscFunctionReturn(0); 11311d1367b7SBarry Smith } 11321d1367b7SBarry Smith 11334a2ae208SSatish Balay #undef __FUNCT__ 11344a2ae208SSatish Balay #define __FUNCT__ "MatSNESMFSetBase" 11355b7f0c42SBarry Smith /*@ 11365b7f0c42SBarry Smith MatSNESMFSetBase - Sets the vector U at which matrix vector products of the 11375b7f0c42SBarry Smith Jacobian are computed 11385b7f0c42SBarry Smith 11395b7f0c42SBarry Smith Collective on Mat 11405b7f0c42SBarry Smith 11415b7f0c42SBarry Smith Input Parameters: 11425b7f0c42SBarry Smith + J - the MatSNESMF matrix 11435b7f0c42SBarry Smith - U - the vector 11445b7f0c42SBarry Smith 11455b7f0c42SBarry Smith Notes: This is rarely used directly 11465b7f0c42SBarry Smith 11475b7f0c42SBarry Smith Level: advanced 11485b7f0c42SBarry Smith 11495b7f0c42SBarry Smith @*/ 115063dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetBase(Mat J,Vec U) 11511d1367b7SBarry Smith { 1152dfbe8321SBarry Smith PetscErrorCode ierr,(*f)(Mat,Vec); 11531d1367b7SBarry Smith 11541d1367b7SBarry Smith PetscFunctionBegin; 11554482741eSBarry Smith PetscValidHeaderSpecific(J,MAT_COOKIE,1); 11564482741eSBarry Smith PetscValidHeaderSpecific(U,VEC_COOKIE,2); 1157c134de8dSSatish Balay ierr = PetscObjectQueryFunction((PetscObject)J,"MatSNESMFSetBase_C",(void (**)(void))&f);CHKERRQ(ierr); 1158cf3bea43SBarry Smith if (f) { 1159cf3bea43SBarry Smith ierr = (*f)(J,U);CHKERRQ(ierr); 116049d4803aSBarry Smith } 11611d1367b7SBarry Smith PetscFunctionReturn(0); 11621d1367b7SBarry Smith } 1163cf57b110SBarry Smith 11645b7f0c42SBarry Smith #undef __FUNCT__ 11655b7f0c42SBarry Smith #define __FUNCT__ "MatSNESMFSetCheckh" 116661860be5SBarry Smith /*@C 11675b7f0c42SBarry Smith MatSNESMFSetCheckh - Sets a function that checks the computed h and adjusts 11685b7f0c42SBarry Smith it to satisfy some criteria 1169cf57b110SBarry Smith 11705b7f0c42SBarry Smith Collective on Mat 11715b7f0c42SBarry Smith 11725b7f0c42SBarry Smith Input Parameters: 11735b7f0c42SBarry Smith + J - the MatSNESMF matrix 11745b7f0c42SBarry Smith . fun - the function that checks h 11755b7f0c42SBarry Smith - ctx - any context needed by the function 11765b7f0c42SBarry Smith 11775b7f0c42SBarry Smith Options Database Keys: 11785b7f0c42SBarry Smith . -snes_mf_check_positivity 11795b7f0c42SBarry Smith 11805b7f0c42SBarry Smith Level: advanced 11815b7f0c42SBarry Smith 11825b7f0c42SBarry Smith Notes: For example, MatSNESMFSetCheckPositivity() insures that all entries 11835b7f0c42SBarry Smith of U + h*a are non-negative 11845b7f0c42SBarry Smith 11855b7f0c42SBarry Smith .seealso: MatSNESMFSetCheckPositivity() 11865b7f0c42SBarry Smith @*/ 118763dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFSetCheckh(Mat J,PetscErrorCode (*fun)(Vec,Vec,PetscScalar*,void*),void* ctx) 11885b7f0c42SBarry Smith { 11896849ba73SBarry Smith PetscErrorCode ierr,(*f)(Mat,PetscErrorCode (*)(Vec,Vec,PetscScalar*,void*),void*); 11905b7f0c42SBarry Smith 11915b7f0c42SBarry Smith PetscFunctionBegin; 11924482741eSBarry Smith PetscValidHeaderSpecific(J,MAT_COOKIE,1); 11935b7f0c42SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)J,"MatSNESMFSetCheckh_C",(void (**)(void))&f);CHKERRQ(ierr); 11945b7f0c42SBarry Smith if (f) { 11955b7f0c42SBarry Smith ierr = (*f)(J,fun,ctx);CHKERRQ(ierr); 11965b7f0c42SBarry Smith } 11975b7f0c42SBarry Smith PetscFunctionReturn(0); 11985b7f0c42SBarry Smith } 11995b7f0c42SBarry Smith 12005b7f0c42SBarry Smith #undef __FUNCT__ 12015b7f0c42SBarry Smith #define __FUNCT__ "MatSNESMFSetCheckPositivity" 12025b7f0c42SBarry Smith /*@ 12035b7f0c42SBarry Smith MatSNESMFCheckPositivity - Checks that all entries in U + h*a are positive or 12045b7f0c42SBarry Smith zero, decreases h until this is satisfied. 12055b7f0c42SBarry Smith 12065b7f0c42SBarry Smith Collective on Vec 12075b7f0c42SBarry Smith 12085b7f0c42SBarry Smith Input Parameters: 12095b7f0c42SBarry Smith + U - base vector that is added to 12105b7f0c42SBarry Smith . a - vector that is added 12115b7f0c42SBarry Smith . h - scaling factor on a 12125b7f0c42SBarry Smith - dummy - context variable (unused) 12135b7f0c42SBarry Smith 12145b7f0c42SBarry Smith Options Database Keys: 12155b7f0c42SBarry Smith . -snes_mf_check_positivity 12165b7f0c42SBarry Smith 12175b7f0c42SBarry Smith Level: advanced 12185b7f0c42SBarry Smith 12195b7f0c42SBarry Smith Notes: This is rarely used directly, rather it is passed as an argument to 12205b7f0c42SBarry Smith MatSNESMFSetCheckh() 12215b7f0c42SBarry Smith 12225b7f0c42SBarry Smith .seealso: MatSNESMFSetCheckh() 12235b7f0c42SBarry Smith @*/ 122463dd3a1aSKris Buschelman PetscErrorCode PETSCSNES_DLLEXPORT MatSNESMFCheckPositivity(Vec U,Vec a,PetscScalar *h,void *dummy) 12255b7f0c42SBarry Smith { 12265b7f0c42SBarry Smith PetscReal val, minval; 12275b7f0c42SBarry Smith PetscScalar *u_vec, *a_vec; 1228dfbe8321SBarry Smith PetscErrorCode ierr; 1229a7cc72afSBarry Smith PetscInt i,n; 12305b7f0c42SBarry Smith MPI_Comm comm; 12315b7f0c42SBarry Smith 12325b7f0c42SBarry Smith PetscFunctionBegin; 12335b7f0c42SBarry Smith ierr = PetscObjectGetComm((PetscObject)U,&comm);CHKERRQ(ierr); 12345b7f0c42SBarry Smith ierr = VecGetArray(U,&u_vec);CHKERRQ(ierr); 12355b7f0c42SBarry Smith ierr = VecGetArray(a,&a_vec);CHKERRQ(ierr); 1236a7cc72afSBarry Smith ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr); 123761860be5SBarry Smith minval = PetscAbsScalar(*h*1.01); 1238a7cc72afSBarry Smith for(i=0;i<n;i++) { 123961860be5SBarry Smith if (PetscRealPart(u_vec[i] + *h*a_vec[i]) <= 0.0) { 124061860be5SBarry Smith val = PetscAbsScalar(u_vec[i]/a_vec[i]); 12415b7f0c42SBarry Smith if (val < minval) minval = val; 12425b7f0c42SBarry Smith } 12435b7f0c42SBarry Smith } 12445b7f0c42SBarry Smith ierr = VecRestoreArray(U,&u_vec);CHKERRQ(ierr); 12455b7f0c42SBarry Smith ierr = VecRestoreArray(a,&a_vec);CHKERRQ(ierr); 12465b7f0c42SBarry Smith ierr = PetscGlobalMin(&minval,&val,comm);CHKERRQ(ierr); 124761860be5SBarry Smith if (val <= PetscAbsScalar(*h)) { 1248ae15b995SBarry Smith ierr = PetscInfo2(U,"Scaling back h from %G to %G\n",PetscRealPart(*h),.99*val);CHKERRQ(ierr); 124961860be5SBarry Smith if (PetscRealPart(*h) > 0.0) *h = 0.99*val; 12505b7f0c42SBarry Smith else *h = -0.99*val; 12515b7f0c42SBarry Smith } 12525b7f0c42SBarry Smith PetscFunctionReturn(0); 12535b7f0c42SBarry Smith } 1254cf57b110SBarry Smith 1255cf57b110SBarry Smith 1256cf57b110SBarry Smith 1257cf57b110SBarry Smith 1258cf57b110SBarry Smith 1259cf57b110SBarry Smith 1260cf57b110SBarry Smith 1261