1 2 /*MC 3 MATMFFD_WP - Implements an alternative approach for computing the differencing parameter 4 h used with the finite difference based matrix-free Jacobian. This code 5 implements the strategy of M. Pernice and H. Walker: 6 7 h = error_rel * sqrt(1 + ||U||) / ||a|| 8 9 Notes: 10 1) || U || does not change between linear iterations so is reused 11 2) In GMRES || a || == 1 and so does not need to ever be computed except at restart 12 when it is recomputed. 13 14 Reference: M. Pernice and H. F. Walker, "NITSOL: A Newton Iterative 15 Solver for Nonlinear Systems", SIAM J. Sci. Stat. Comput.", 1998, 16 vol 19, pp. 302--318. 17 18 Options Database Keys: 19 . -mat_mffd_compute_normu -Compute the norm of u everytime see MatMFFDWPSetComputeNormU() 20 21 22 Level: intermediate 23 24 Notes: Requires no global collectives when used with GMRES 25 26 Formula used: 27 F'(u)*a = [F(u+h*a) - F(u)]/h where 28 29 .seealso: MATMFFD, MatCreateMFFD(), MatCreateSNESMF(), MATMFFD_DS 30 31 M*/ 32 33 /* 34 This include file defines the data structure MatMFFD that 35 includes information about the computation of h. It is shared by 36 all implementations that people provide. 37 38 See snesmfjdef.c for a full set of comments on the routines below. 39 */ 40 #include "private/matimpl.h" 41 #include "../src/mat/impls/mffd/mffdimpl.h" /*I "petscmat.h" I*/ 42 43 typedef struct { 44 PetscReal normUfact; /* previous sqrt(1.0 + || U ||) */ 45 PetscBool computenormU; 46 } MatMFFD_WP; 47 48 #undef __FUNCT__ 49 #define __FUNCT__ "MatMFFDCompute_WP" 50 /* 51 MatMFFDCompute_WP - Standard PETSc code for 52 computing h with matrix-free finite differences. 53 54 Input Parameters: 55 + ctx - the matrix free context 56 . U - the location at which you want the Jacobian 57 - a - the direction you want the derivative 58 59 Output Parameter: 60 . h - the scale computed 61 62 */ 63 static PetscErrorCode MatMFFDCompute_WP(MatMFFD ctx,Vec U,Vec a,PetscScalar *h,PetscBool *zeroa) 64 { 65 MatMFFD_WP *hctx = (MatMFFD_WP*)ctx->hctx; 66 PetscReal normU,norma; 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 if (!(ctx->count % ctx->recomputeperiod)) { 71 if (hctx->computenormU || !ctx->ncurrenth) { 72 ierr = VecNorm(U,NORM_2,&normU);CHKERRQ(ierr); 73 hctx->normUfact = sqrt(1.0+normU); 74 } 75 ierr = VecNorm(a,NORM_2,&norma);CHKERRQ(ierr); 76 if (norma == 0.0) { 77 *zeroa = PETSC_TRUE; 78 PetscFunctionReturn(0); 79 } 80 *zeroa = PETSC_FALSE; 81 *h = ctx->error_rel*hctx->normUfact/norma; 82 } else { 83 *h = ctx->currenth; 84 } 85 PetscFunctionReturn(0); 86 } 87 88 #undef __FUNCT__ 89 #define __FUNCT__ "MatMFFDView_WP" 90 /* 91 MatMFFDView_WP - Prints information about this particular 92 method for computing h. Note that this does not print the general 93 information about the matrix free, that is printed by the calling 94 routine. 95 96 Input Parameters: 97 + ctx - the matrix free context 98 - viewer - the PETSc viewer 99 100 */ 101 static PetscErrorCode MatMFFDView_WP(MatMFFD ctx,PetscViewer viewer) 102 { 103 MatMFFD_WP *hctx = (MatMFFD_WP *)ctx->hctx; 104 PetscErrorCode ierr; 105 PetscBool iascii; 106 107 PetscFunctionBegin; 108 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 109 if (iascii) { 110 if (hctx->computenormU){ierr = PetscViewerASCIIPrintf(viewer," Computes normU\n");CHKERRQ(ierr);} 111 else {ierr = PetscViewerASCIIPrintf(viewer," Does not compute normU\n");CHKERRQ(ierr);} 112 } else { 113 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES matrix-free WP",((PetscObject)viewer)->type_name); 114 } 115 PetscFunctionReturn(0); 116 } 117 118 #undef __FUNCT__ 119 #define __FUNCT__ "MatMFFDSetFromOptions_WP" 120 /* 121 MatMFFDSetFromOptions_WP - Looks in the options database for 122 any options appropriate for this method 123 124 Input Parameter: 125 . ctx - the matrix free context 126 127 */ 128 static PetscErrorCode MatMFFDSetFromOptions_WP(MatMFFD ctx) 129 { 130 PetscErrorCode ierr; 131 MatMFFD_WP *hctx = (MatMFFD_WP*)ctx->hctx; 132 133 PetscFunctionBegin; 134 ierr = PetscOptionsHead("Walker-Pernice options");CHKERRQ(ierr); 135 ierr = PetscOptionsBool("-mat_mffd_compute_normu","Compute the norm of u","MatMFFDWPSetComputeNormU", 136 hctx->computenormU,&hctx->computenormU,0);CHKERRQ(ierr); 137 ierr = PetscOptionsTail();CHKERRQ(ierr); 138 PetscFunctionReturn(0); 139 } 140 141 #undef __FUNCT__ 142 #define __FUNCT__ "MatMFFDDestroy_WP" 143 /* 144 MatMFFDDestroy_WP - Frees the space allocated by 145 MatCreateMFFD_WP(). 146 147 Input Parameter: 148 . ctx - the matrix free context 149 150 Notes: does not free the ctx, that is handled by the calling routine 151 152 */ 153 static PetscErrorCode MatMFFDDestroy_WP(MatMFFD ctx) 154 { 155 PetscErrorCode ierr; 156 PetscFunctionBegin; 157 ierr = PetscFree(ctx->hctx);CHKERRQ(ierr); 158 PetscFunctionReturn(0); 159 } 160 161 EXTERN_C_BEGIN 162 #undef __FUNCT__ 163 #define __FUNCT__ "MatMFFDWPSetComputeNormU_P" 164 PetscErrorCode MatMFFDWPSetComputeNormU_P(Mat mat,PetscBool flag) 165 { 166 MatMFFD ctx = (MatMFFD)mat->data; 167 MatMFFD_WP *hctx = (MatMFFD_WP*)ctx->hctx; 168 169 PetscFunctionBegin; 170 hctx->computenormU = flag; 171 PetscFunctionReturn(0); 172 } 173 EXTERN_C_END 174 175 #undef __FUNCT__ 176 #define __FUNCT__ "MatMFFDWPSetComputeNormU" 177 /*@ 178 MatMFFDWPSetComputeNormU - Sets whether it computes the ||U|| used by the WP 179 PETSc routine for computing h. With any Krylov solver this need only 180 be computed during the first iteration and kept for later. 181 182 Input Parameters: 183 + A - the matrix created with MatCreateSNESMF() 184 - flag - PETSC_TRUE causes it to compute ||U||, PETSC_FALSE uses the previous value 185 186 Options Database Key: 187 . -mat_mffd_compute_normu <true,false> - true by default, false can save calculations but you 188 must be sure that ||U|| has not changed in the mean time. 189 190 Level: advanced 191 192 Notes: 193 See the manual page for MATMFFD_WP for a complete description of the 194 algorithm used to compute h. 195 196 .seealso: MatMFFDSetFunctionError(), MatCreateSNESMF() 197 198 @*/ 199 PetscErrorCode MatMFFDWPSetComputeNormU(Mat A,PetscBool flag) 200 { 201 PetscErrorCode ierr; 202 203 PetscFunctionBegin; 204 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 205 ierr = PetscTryMethod(A,"MatMFFDWPSetComputeNormU_C",(Mat,PetscBool),(A,flag));CHKERRQ(ierr); 206 PetscFunctionReturn(0); 207 } 208 209 EXTERN_C_BEGIN 210 #undef __FUNCT__ 211 #define __FUNCT__ "MatCreateMFFD_WP" 212 /* 213 MatCreateMFFD_WP - Standard PETSc code for 214 computing h with matrix-free finite differences. 215 216 Input Parameter: 217 . ctx - the matrix free context created by MatCreateMFFD() 218 219 */ 220 PetscErrorCode MatCreateMFFD_WP(MatMFFD ctx) 221 { 222 PetscErrorCode ierr; 223 MatMFFD_WP *hctx; 224 225 PetscFunctionBegin; 226 227 /* allocate my own private data structure */ 228 ierr = PetscNewLog(ctx,MatMFFD_WP,&hctx);CHKERRQ(ierr); 229 ctx->hctx = (void*)hctx; 230 hctx->computenormU = PETSC_FALSE; 231 232 /* set the functions I am providing */ 233 ctx->ops->compute = MatMFFDCompute_WP; 234 ctx->ops->destroy = MatMFFDDestroy_WP; 235 ctx->ops->view = MatMFFDView_WP; 236 ctx->ops->setfromoptions = MatMFFDSetFromOptions_WP; 237 238 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ctx->mat,"MatMFFDWPSetComputeNormU_C", 239 "MatMFFDWPSetComputeNormU_P", 240 MatMFFDWPSetComputeNormU_P);CHKERRQ(ierr); 241 242 PetscFunctionReturn(0); 243 } 244 EXTERN_C_END 245 246 247 248