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