Actual source code: wp.c
1: #define PETSCSNES_DLL
3: /*MC
4: MATSNESMF_WP - Implements an alternative approach for computing the differencing parameter
5: h used with the finite difference based matrix-free Jacobian. This code
6: implements the strategy of M. Pernice and H. Walker:
8: h = error_rel * sqrt(1 + ||U||) / ||a||
10: Notes:
11: 1) || U || does not change between linear iterations so is reused
12: 2) In GMRES || a || == 1 and so does not need to ever be computed except at restart
13: when it is recomputed.
15: Reference: M. Pernice and H. F. Walker, "NITSOL: A Newton Iterative
16: Solver for Nonlinear Systems", SIAM J. Sci. Stat. Comput.", 1998,
17: vol 19, pp. 302--318.
19: Options Database Keys:
20: . -snes_mf_compute_normu -Compute the norm of u everytime see MatSNESMFWPSetComputeNormU()
23: Level: intermediate
25: Notes: Requires no global collectives when used with GMRES
27: Formula used:
28: F'(u)*a = [F(u+h*a) - F(u)]/h where
30: .seealso: MATMFFD, MatCreateMF(), MatCreateSNESMF(), MATSNESMF_DS
32: M*/
34: /*
35: This include file defines the data structure MatSNESMF that
36: includes information about the computation of h. It is shared by
37: all implementations that people provide.
39: See snesmfjdef.c for a full set of comments on the routines below.
40: */
41: #include include/private/matimpl.h
42: #include src/snes/mf/snesmfj.h
44: typedef struct {
45: PetscReal normUfact; /* previous sqrt(1.0 + || U ||) */
46: PetscTruth computenorma,computenormU;
47: } MatSNESMFWP;
51: /*
52: MatSNESMFCompute_WP - Standard PETSc code for
53: computing h with matrix-free finite differences.
55: Input Parameters:
56: + ctx - the matrix free context
57: . U - the location at which you want the Jacobian
58: - a - the direction you want the derivative
60: Output Parameter:
61: . h - the scale computed
63: */
64: static PetscErrorCode MatSNESMFCompute_WP(MatSNESMFCtx ctx,Vec U,Vec a,PetscScalar *h,PetscTruth *zeroa)
65: {
66: MatSNESMFWP *hctx = (MatSNESMFWP*)ctx->hctx;
67: PetscReal normU,norma = 1.0;
72: if (!(ctx->count % ctx->recomputeperiod)) {
73: if (hctx->computenorma && (hctx->computenormU || !ctx->ncurrenth)) {
74: VecNormBegin(U,NORM_2,&normU);
75: VecNormBegin(a,NORM_2,&norma);
76: VecNormEnd(U,NORM_2,&normU);
77: VecNormEnd(a,NORM_2,&norma);
78: hctx->normUfact = sqrt(1.0+normU);
79: } else if (hctx->computenormU || !ctx->ncurrenth) {
80: VecNorm(U,NORM_2,&normU);
81: hctx->normUfact = sqrt(1.0+normU);
82: } else if (hctx->computenorma) {
83: VecNorm(a,NORM_2,&norma);
84: }
85: if (norma == 0.0) {
86: *zeroa = PETSC_TRUE;
87: return(0);
88: }
89: *zeroa = PETSC_FALSE;
90: *h = ctx->error_rel*hctx->normUfact/norma;
91: } else {
92: *h = ctx->currenth;
93: }
94: return(0);
95: }
99: /*
100: MatSNESMFView_WP - Prints information about this particular
101: method for computing h. Note that this does not print the general
102: information about the matrix free, that is printed by the calling
103: routine.
105: Input Parameters:
106: + ctx - the matrix free context
107: - viewer - the PETSc viewer
109: */
110: static PetscErrorCode MatSNESMFView_WP(MatSNESMFCtx ctx,PetscViewer viewer)
111: {
112: MatSNESMFWP *hctx = (MatSNESMFWP *)ctx->hctx;
114: PetscTruth iascii;
117: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
118: if (iascii) {
119: if (hctx->computenorma){PetscViewerASCIIPrintf(viewer," Computes normA\n");}
120: else { PetscViewerASCIIPrintf(viewer," Does not compute normA\n");}
121: if (hctx->computenormU){ PetscViewerASCIIPrintf(viewer," Computes normU\n");}
122: else { PetscViewerASCIIPrintf(viewer," Does not compute normU\n");}
123: } else {
124: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for SNES matrix-free WP",((PetscObject)viewer)->type_name);
125: }
126: return(0);
127: }
131: /*
132: MatSNESMFSetFromOptions_WP - Looks in the options database for
133: any options appropriate for this method
135: Input Parameter:
136: . ctx - the matrix free context
138: */
139: static PetscErrorCode MatSNESMFSetFromOptions_WP(MatSNESMFCtx ctx)
140: {
142: MatSNESMFWP *hctx = (MatSNESMFWP*)ctx->hctx;
145: PetscOptionsHead("Walker-Pernice options");
146: PetscOptionsTruth("-snes_mf_compute_normu","Compute the norm of u","MatSNESMFWPSetComputeNormU",
147: hctx->computenorma,&hctx->computenorma,0);
148: PetscOptionsTail();
149: return(0);
150: }
154: /*
155: MatSNESMFDestroy_WP - Frees the space allocated by
156: MatSNESMFCreate_WP().
158: Input Parameter:
159: . ctx - the matrix free context
161: Notes: does not free the ctx, that is handled by the calling routine
163: */
164: static PetscErrorCode MatSNESMFDestroy_WP(MatSNESMFCtx ctx)
165: {
168: PetscFree(ctx->hctx);
169: return(0);
170: }
175: PetscErrorCode MatSNESMFWPSetComputeNormU_P(Mat mat,PetscTruth flag)
176: {
177: MatSNESMFCtx ctx = (MatSNESMFCtx)mat->data;
178: MatSNESMFWP *hctx;
181: hctx = (MatSNESMFWP*)ctx->hctx;
182: hctx->computenormU = flag;
183: return(0);
184: }
189: /*@
190: MatSNESMFWPSetComputeNormU - Sets whether it computes the ||U|| used by the WP
191: PETSc routine for computing h. With any Krylov solver this need only
192: be computed during the first iteration and kept for later.
194: Input Parameters:
195: + A - the matrix created with MatCreateSNESMF()
196: - flag - PETSC_TRUE causes it to compute ||U||, PETSC_FALSE uses the previous value
198: Options Database Key:
199: . -snes_mf_compute_normu <true,false> - true by default, false can save calculations but you
200: must be sure that ||U|| has not changed in the mean time.
202: Level: advanced
204: Notes:
205: See the manual page for MATSNESMF_WP for a complete description of the
206: algorithm used to compute h.
208: .seealso: MatSNESMFSetFunctionError(), MatCreateSNESMF()
210: @*/
211: PetscErrorCode MatSNESMFWPSetComputeNormU(Mat A,PetscTruth flag)
212: {
213: PetscErrorCode ierr,(*f)(Mat,PetscTruth);
217: PetscObjectQueryFunction((PetscObject)A,"MatSNESMFWPSetComputeNormU_C",(void (**)(void))&f);
218: if (f) {
219: (*f)(A,flag);
220: }
221: return(0);
222: }
227: /*
228: MatSNESMFCreate_WP - Standard PETSc code for
229: computing h with matrix-free finite differences.
231: Input Parameter:
232: . ctx - the matrix free context created by MatSNESMFCreate()
234: */
235: PetscErrorCode MatSNESMFCreate_WP(MatSNESMFCtx ctx)
236: {
238: MatSNESMFWP *hctx;
242: /* allocate my own private data structure */
243: PetscNew(MatSNESMFWP,&hctx);
244: ctx->hctx = (void*)hctx;
245: hctx->computenormU = PETSC_FALSE;
246: hctx->computenorma = PETSC_TRUE;
248: /* set the functions I am providing */
249: ctx->ops->compute = MatSNESMFCompute_WP;
250: ctx->ops->destroy = MatSNESMFDestroy_WP;
251: ctx->ops->view = MatSNESMFView_WP;
252: ctx->ops->setfromoptions = MatSNESMFSetFromOptions_WP;
254: PetscObjectComposeFunctionDynamic((PetscObject)ctx->mat,"MatSNESMFWPSetComputeNormU_C",
255: "MatSNESMFWPSetComputeNormU_P",
256: MatSNESMFWPSetComputeNormU_P);
258: return(0);
259: }