1e884886fSBarry Smith 2e884886fSBarry Smith /*MC 3e884886fSBarry Smith MATMFFD_WP - Implements an alternative approach for computing the differencing parameter 4e884886fSBarry Smith h used with the finite difference based matrix-free Jacobian. This code 5e884886fSBarry Smith implements the strategy of M. Pernice and H. Walker: 6e884886fSBarry Smith 7e884886fSBarry Smith h = error_rel * sqrt(1 + ||U||) / ||a|| 8e884886fSBarry Smith 9e884886fSBarry Smith Notes: 10e884886fSBarry Smith 1) || U || does not change between linear iterations so is reused 11e884886fSBarry Smith 2) In GMRES || a || == 1 and so does not need to ever be computed except at restart 12e884886fSBarry Smith when it is recomputed. 13e884886fSBarry Smith 14e884886fSBarry Smith Reference: M. Pernice and H. F. Walker, "NITSOL: A Newton Iterative 15e884886fSBarry Smith Solver for Nonlinear Systems", SIAM J. Sci. Stat. Comput.", 1998, 16e884886fSBarry Smith vol 19, pp. 302--318. 17e884886fSBarry Smith 18e884886fSBarry Smith Options Database Keys: 19e884886fSBarry Smith . -mat_mffd_compute_normu -Compute the norm of u every time see MatMFFDWPSetComputeNormU() 20e884886fSBarry Smith 21e884886fSBarry Smith Level: intermediate 22e884886fSBarry Smith 2395452b02SPatrick Sanan Notes: 2495452b02SPatrick Sanan Requires no global collectives when used with GMRES 25e884886fSBarry Smith 26e884886fSBarry Smith Formula used: 27e884886fSBarry Smith F'(u)*a = [F(u+h*a) - F(u)]/h where 28e884886fSBarry Smith 29db781477SPatrick Sanan .seealso: `MATMFFD`, `MatCreateMFFD()`, `MatCreateSNESMF()`, `MATMFFD_DS` 30e884886fSBarry Smith 31e884886fSBarry Smith M*/ 32e884886fSBarry Smith 33e884886fSBarry Smith /* 34e884886fSBarry Smith This include file defines the data structure MatMFFD that 35e884886fSBarry Smith includes information about the computation of h. It is shared by 36e884886fSBarry Smith all implementations that people provide. 37e884886fSBarry Smith 38e884886fSBarry Smith See snesmfjdef.c for a full set of comments on the routines below. 39e884886fSBarry Smith */ 40af0996ceSBarry Smith #include <petsc/private/matimpl.h> 41c6db04a5SJed Brown #include <../src/mat/impls/mffd/mffdimpl.h> /*I "petscmat.h" I*/ 42e884886fSBarry Smith 43e884886fSBarry Smith typedef struct { 44e884886fSBarry Smith PetscReal normUfact; /* previous sqrt(1.0 + || U ||) */ 45ace3abfcSBarry Smith PetscBool computenormU; 46e884886fSBarry Smith } MatMFFD_WP; 47e884886fSBarry Smith 48e884886fSBarry Smith /* 49e884886fSBarry Smith MatMFFDCompute_WP - Standard PETSc code for 50e884886fSBarry Smith computing h with matrix-free finite differences. 51e884886fSBarry Smith 52e884886fSBarry Smith Input Parameters: 53e884886fSBarry Smith + ctx - the matrix free context 54e884886fSBarry Smith . U - the location at which you want the Jacobian 55e884886fSBarry Smith - a - the direction you want the derivative 56e884886fSBarry Smith 57e884886fSBarry Smith Output Parameter: 58e884886fSBarry Smith . h - the scale computed 59e884886fSBarry Smith 60e884886fSBarry Smith */ 61*9371c9d4SSatish Balay static PetscErrorCode MatMFFDCompute_WP(MatMFFD ctx, Vec U, Vec a, PetscScalar *h, PetscBool *zeroa) { 62e884886fSBarry Smith MatMFFD_WP *hctx = (MatMFFD_WP *)ctx->hctx; 6351a79602SBarry Smith PetscReal normU, norma; 64e884886fSBarry Smith 65e884886fSBarry Smith PetscFunctionBegin; 66e884886fSBarry Smith if (!(ctx->count % ctx->recomputeperiod)) { 6751a79602SBarry Smith if (hctx->computenormU || !ctx->ncurrenth) { 689566063dSJacob Faibussowitsch PetscCall(VecNorm(U, NORM_2, &normU)); 698f1a2a5eSBarry Smith hctx->normUfact = PetscSqrtReal(1.0 + normU); 70e884886fSBarry Smith } 719566063dSJacob Faibussowitsch PetscCall(VecNorm(a, NORM_2, &norma)); 72e884886fSBarry Smith if (norma == 0.0) { 73e884886fSBarry Smith *zeroa = PETSC_TRUE; 74e884886fSBarry Smith PetscFunctionReturn(0); 75e884886fSBarry Smith } 76e884886fSBarry Smith *zeroa = PETSC_FALSE; 77e884886fSBarry Smith *h = ctx->error_rel * hctx->normUfact / norma; 78e884886fSBarry Smith } else { 79e884886fSBarry Smith *h = ctx->currenth; 80e884886fSBarry Smith } 81e884886fSBarry Smith PetscFunctionReturn(0); 82e884886fSBarry Smith } 83e884886fSBarry Smith 84e884886fSBarry Smith /* 85e884886fSBarry Smith MatMFFDView_WP - Prints information about this particular 86e884886fSBarry Smith method for computing h. Note that this does not print the general 87e884886fSBarry Smith information about the matrix free, that is printed by the calling 88e884886fSBarry Smith routine. 89e884886fSBarry Smith 90e884886fSBarry Smith Input Parameters: 91e884886fSBarry Smith + ctx - the matrix free context 92e884886fSBarry Smith - viewer - the PETSc viewer 93e884886fSBarry Smith 94e884886fSBarry Smith */ 95*9371c9d4SSatish Balay static PetscErrorCode MatMFFDView_WP(MatMFFD ctx, PetscViewer viewer) { 96e884886fSBarry Smith MatMFFD_WP *hctx = (MatMFFD_WP *)ctx->hctx; 97ace3abfcSBarry Smith PetscBool iascii; 98e884886fSBarry Smith 99e884886fSBarry Smith PetscFunctionBegin; 1009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 101e884886fSBarry Smith if (iascii) { 1022205254eSKarl Rupp if (hctx->computenormU) { 1039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Computes normU\n")); 1042205254eSKarl Rupp } else { 1059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Does not compute normU\n")); 1062205254eSKarl Rupp } 10711aeaf0aSBarry Smith } 108e884886fSBarry Smith PetscFunctionReturn(0); 109e884886fSBarry Smith } 110e884886fSBarry Smith 111e884886fSBarry Smith /* 112e884886fSBarry Smith MatMFFDSetFromOptions_WP - Looks in the options database for 113e884886fSBarry Smith any options appropriate for this method 114e884886fSBarry Smith 115e884886fSBarry Smith Input Parameter: 116e884886fSBarry Smith . ctx - the matrix free context 117e884886fSBarry Smith 118e884886fSBarry Smith */ 119*9371c9d4SSatish Balay static PetscErrorCode MatMFFDSetFromOptions_WP(MatMFFD ctx, PetscOptionItems *PetscOptionsObject) { 120e884886fSBarry Smith MatMFFD_WP *hctx = (MatMFFD_WP *)ctx->hctx; 121e884886fSBarry Smith 122e884886fSBarry Smith PetscFunctionBegin; 123d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Walker-Pernice options"); 1249566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-mat_mffd_compute_normu", "Compute the norm of u", "MatMFFDWPSetComputeNormU", hctx->computenormU, &hctx->computenormU, NULL)); 125d0609cedSBarry Smith PetscOptionsHeadEnd(); 126e884886fSBarry Smith PetscFunctionReturn(0); 127e884886fSBarry Smith } 128e884886fSBarry Smith 129e884886fSBarry Smith /* 130e884886fSBarry Smith MatMFFDDestroy_WP - Frees the space allocated by 1311d0fab5eSBarry Smith MatCreateMFFD_WP(). 132e884886fSBarry Smith 133e884886fSBarry Smith Input Parameter: 134e884886fSBarry Smith . ctx - the matrix free context 135e884886fSBarry Smith 13695452b02SPatrick Sanan Notes: 13795452b02SPatrick Sanan does not free the ctx, that is handled by the calling routine 138e884886fSBarry Smith 139e884886fSBarry Smith */ 140*9371c9d4SSatish Balay static PetscErrorCode MatMFFDDestroy_WP(MatMFFD ctx) { 141e884886fSBarry Smith PetscFunctionBegin; 1422e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)ctx->mat, "MatMFFDWPSetComputeNormU_C", NULL)); 1439566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->hctx)); 144e884886fSBarry Smith PetscFunctionReturn(0); 145e884886fSBarry Smith } 146e884886fSBarry Smith 147*9371c9d4SSatish Balay PetscErrorCode MatMFFDWPSetComputeNormU_P(Mat mat, PetscBool flag) { 148e884886fSBarry Smith MatMFFD ctx = (MatMFFD)mat->data; 149e884886fSBarry Smith MatMFFD_WP *hctx = (MatMFFD_WP *)ctx->hctx; 150e884886fSBarry Smith 151e884886fSBarry Smith PetscFunctionBegin; 152e884886fSBarry Smith hctx->computenormU = flag; 153e884886fSBarry Smith PetscFunctionReturn(0); 154e884886fSBarry Smith } 155e884886fSBarry Smith 156e884886fSBarry Smith /*@ 157e884886fSBarry Smith MatMFFDWPSetComputeNormU - Sets whether it computes the ||U|| used by the WP 158e884886fSBarry Smith PETSc routine for computing h. With any Krylov solver this need only 159e884886fSBarry Smith be computed during the first iteration and kept for later. 160e884886fSBarry Smith 161e884886fSBarry Smith Input Parameters: 162e884886fSBarry Smith + A - the matrix created with MatCreateSNESMF() 163e884886fSBarry Smith - flag - PETSC_TRUE causes it to compute ||U||, PETSC_FALSE uses the previous value 164e884886fSBarry Smith 165e884886fSBarry Smith Options Database Key: 166e884886fSBarry Smith . -mat_mffd_compute_normu <true,false> - true by default, false can save calculations but you 167e884886fSBarry Smith must be sure that ||U|| has not changed in the mean time. 168e884886fSBarry Smith 169e884886fSBarry Smith Level: advanced 170e884886fSBarry Smith 171e884886fSBarry Smith Notes: 172e884886fSBarry Smith See the manual page for MATMFFD_WP for a complete description of the 173e884886fSBarry Smith algorithm used to compute h. 174e884886fSBarry Smith 175db781477SPatrick Sanan .seealso: `MatMFFDSetFunctionError()`, `MatCreateSNESMF()` 176e884886fSBarry Smith 177e884886fSBarry Smith @*/ 178*9371c9d4SSatish Balay PetscErrorCode MatMFFDWPSetComputeNormU(Mat A, PetscBool flag) { 179e884886fSBarry Smith PetscFunctionBegin; 1800700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 181cac4c232SBarry Smith PetscTryMethod(A, "MatMFFDWPSetComputeNormU_C", (Mat, PetscBool), (A, flag)); 182e884886fSBarry Smith PetscFunctionReturn(0); 183e884886fSBarry Smith } 184e884886fSBarry Smith 185e884886fSBarry Smith /* 1861d0fab5eSBarry Smith MatCreateMFFD_WP - Standard PETSc code for 187e884886fSBarry Smith computing h with matrix-free finite differences. 188e884886fSBarry Smith 189e884886fSBarry Smith Input Parameter: 1901d0fab5eSBarry Smith . ctx - the matrix free context created by MatCreateMFFD() 191e884886fSBarry Smith 192e884886fSBarry Smith */ 193*9371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreateMFFD_WP(MatMFFD ctx) { 194e884886fSBarry Smith MatMFFD_WP *hctx; 195e884886fSBarry Smith 196e884886fSBarry Smith PetscFunctionBegin; 197e884886fSBarry Smith /* allocate my own private data structure */ 1989566063dSJacob Faibussowitsch PetscCall(PetscNewLog(ctx, &hctx)); 199e884886fSBarry Smith ctx->hctx = (void *)hctx; 200e884886fSBarry Smith hctx->computenormU = PETSC_FALSE; 201e884886fSBarry Smith 202e884886fSBarry Smith /* set the functions I am providing */ 203e884886fSBarry Smith ctx->ops->compute = MatMFFDCompute_WP; 204e884886fSBarry Smith ctx->ops->destroy = MatMFFDDestroy_WP; 205e884886fSBarry Smith ctx->ops->view = MatMFFDView_WP; 206e884886fSBarry Smith ctx->ops->setfromoptions = MatMFFDSetFromOptions_WP; 207e884886fSBarry Smith 2089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)ctx->mat, "MatMFFDWPSetComputeNormU_C", MatMFFDWPSetComputeNormU_P)); 209e884886fSBarry Smith PetscFunctionReturn(0); 210e884886fSBarry Smith } 211