xref: /petsc/src/mat/impls/mffd/wp.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
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 <petsc/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 /*
49      MatMFFDCompute_WP - Standard PETSc code for
50    computing h with matrix-free finite differences.
51 
52   Input Parameters:
53 +   ctx - the matrix free context
54 .   U - the location at which you want the Jacobian
55 -   a - the direction you want the derivative
56 
57   Output Parameter:
58 .   h - the scale computed
59 
60 */
61 static PetscErrorCode MatMFFDCompute_WP(MatMFFD ctx,Vec U,Vec a,PetscScalar *h,PetscBool  *zeroa)
62 {
63   MatMFFD_WP     *hctx = (MatMFFD_WP*)ctx->hctx;
64   PetscReal      normU,norma;
65   PetscErrorCode ierr;
66 
67   PetscFunctionBegin;
68   if (!(ctx->count % ctx->recomputeperiod)) {
69     if (hctx->computenormU || !ctx->ncurrenth) {
70       ierr            = VecNorm(U,NORM_2,&normU);CHKERRQ(ierr);
71       hctx->normUfact = PetscSqrtReal(1.0+normU);
72     }
73     ierr = VecNorm(a,NORM_2,&norma);CHKERRQ(ierr);
74     if (norma == 0.0) {
75       *zeroa = PETSC_TRUE;
76       PetscFunctionReturn(0);
77     }
78     *zeroa = PETSC_FALSE;
79     *h     = ctx->error_rel*hctx->normUfact/norma;
80   } else {
81     *h = ctx->currenth;
82   }
83   PetscFunctionReturn(0);
84 }
85 
86 /*
87    MatMFFDView_WP - Prints information about this particular
88      method for computing h. Note that this does not print the general
89      information about the matrix free, that is printed by the calling
90      routine.
91 
92   Input Parameters:
93 +   ctx - the matrix free context
94 -   viewer - the PETSc viewer
95 
96 */
97 static PetscErrorCode MatMFFDView_WP(MatMFFD ctx,PetscViewer viewer)
98 {
99   MatMFFD_WP     *hctx = (MatMFFD_WP*)ctx->hctx;
100   PetscErrorCode ierr;
101   PetscBool      iascii;
102 
103   PetscFunctionBegin;
104   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
105   if (iascii) {
106     if (hctx->computenormU) {
107       ierr =  PetscViewerASCIIPrintf(viewer,"    Computes normU\n");CHKERRQ(ierr);
108     } else {
109       ierr =  PetscViewerASCIIPrintf(viewer,"    Does not compute normU\n");CHKERRQ(ierr);
110     }
111   }
112   PetscFunctionReturn(0);
113 }
114 
115 /*
116    MatMFFDSetFromOptions_WP - Looks in the options database for
117      any options appropriate for this method
118 
119   Input Parameter:
120 .  ctx - the matrix free context
121 
122 */
123 static PetscErrorCode MatMFFDSetFromOptions_WP(PetscOptionItems *PetscOptionsObject,MatMFFD ctx)
124 {
125   PetscErrorCode ierr;
126   MatMFFD_WP     *hctx = (MatMFFD_WP*)ctx->hctx;
127 
128   PetscFunctionBegin;
129   ierr = PetscOptionsHead(PetscOptionsObject,"Walker-Pernice options");CHKERRQ(ierr);
130   ierr = PetscOptionsBool("-mat_mffd_compute_normu","Compute the norm of u","MatMFFDWPSetComputeNormU", hctx->computenormU,&hctx->computenormU,NULL);CHKERRQ(ierr);
131   ierr = PetscOptionsTail();CHKERRQ(ierr);
132   PetscFunctionReturn(0);
133 }
134 
135 /*
136    MatMFFDDestroy_WP - Frees the space allocated by
137        MatCreateMFFD_WP().
138 
139   Input Parameter:
140 .  ctx - the matrix free context
141 
142    Notes: does not free the ctx, that is handled by the calling routine
143 
144 */
145 static PetscErrorCode MatMFFDDestroy_WP(MatMFFD ctx)
146 {
147   PetscErrorCode ierr;
148 
149   PetscFunctionBegin;
150   ierr = PetscFree(ctx->hctx);CHKERRQ(ierr);
151   PetscFunctionReturn(0);
152 }
153 
154 PetscErrorCode  MatMFFDWPSetComputeNormU_P(Mat mat,PetscBool flag)
155 {
156   MatMFFD    ctx   = (MatMFFD)mat->data;
157   MatMFFD_WP *hctx = (MatMFFD_WP*)ctx->hctx;
158 
159   PetscFunctionBegin;
160   hctx->computenormU = flag;
161   PetscFunctionReturn(0);
162 }
163 
164 /*@
165     MatMFFDWPSetComputeNormU - Sets whether it computes the ||U|| used by the WP
166              PETSc routine for computing h. With any Krylov solver this need only
167              be computed during the first iteration and kept for later.
168 
169   Input Parameters:
170 +   A - the matrix created with MatCreateSNESMF()
171 -   flag - PETSC_TRUE causes it to compute ||U||, PETSC_FALSE uses the previous value
172 
173   Options Database Key:
174 .   -mat_mffd_compute_normu <true,false> - true by default, false can save calculations but you
175               must be sure that ||U|| has not changed in the mean time.
176 
177   Level: advanced
178 
179   Notes:
180    See the manual page for MATMFFD_WP for a complete description of the
181    algorithm used to compute h.
182 
183 .seealso: MatMFFDSetFunctionError(), MatCreateSNESMF()
184 
185 @*/
186 PetscErrorCode  MatMFFDWPSetComputeNormU(Mat A,PetscBool flag)
187 {
188   PetscErrorCode ierr;
189 
190   PetscFunctionBegin;
191   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
192   ierr = PetscTryMethod(A,"MatMFFDWPSetComputeNormU_C",(Mat,PetscBool),(A,flag));CHKERRQ(ierr);
193   PetscFunctionReturn(0);
194 }
195 
196 /*
197      MatCreateMFFD_WP - Standard PETSc code for
198    computing h with matrix-free finite differences.
199 
200    Input Parameter:
201 .  ctx - the matrix free context created by MatCreateMFFD()
202 
203 */
204 PETSC_EXTERN PetscErrorCode MatCreateMFFD_WP(MatMFFD ctx)
205 {
206   PetscErrorCode ierr;
207   MatMFFD_WP     *hctx;
208 
209   PetscFunctionBegin;
210   /* allocate my own private data structure */
211   ierr               = PetscNewLog(ctx,&hctx);CHKERRQ(ierr);
212   ctx->hctx          = (void*)hctx;
213   hctx->computenormU = PETSC_FALSE;
214 
215   /* set the functions I am providing */
216   ctx->ops->compute        = MatMFFDCompute_WP;
217   ctx->ops->destroy        = MatMFFDDestroy_WP;
218   ctx->ops->view           = MatMFFDView_WP;
219   ctx->ops->setfromoptions = MatMFFDSetFromOptions_WP;
220 
221   ierr = PetscObjectComposeFunction((PetscObject)ctx->mat,"MatMFFDWPSetComputeNormU_C",MatMFFDWPSetComputeNormU_P);CHKERRQ(ierr);
222   PetscFunctionReturn(0);
223 }
224 
225 
226 
227