xref: /petsc/src/mat/impls/mffd/mffddef.c (revision 89669be4d29968dc8d4c19ce1b69194a6a561ea4)
1 
2 /*
3   Implements the DS PETSc approach for computing the h
4   parameter used with the finite difference based matrix-free
5   Jacobian-vector products.
6 
7   To make your own: clone this file and modify for your needs.
8 
9   Mandatory functions:
10   -------------------
11       MatMFFDCompute_  - for a given point and direction computes h
12 
13       MatCreateMFFD _ - fills in the MatMFFD data structure
14                            for this particular implementation
15 
16    Optional functions:
17    -------------------
18       MatMFFDView_ - prints information about the parameters being used.
19                        This is called when SNESView() or -snes_view is used.
20 
21       MatMFFDSetFromOptions_ - checks the options database for options that
22                                apply to this method.
23 
24       MatMFFDDestroy_ - frees any space allocated by the routines above
25 
26 */
27 
28 /*
29     This include file defines the data structure  MatMFFD that
30    includes information about the computation of h. It is shared by
31    all implementations that people provide
32 */
33 #include <petsc/private/matimpl.h>
34 #include <../src/mat/impls/mffd/mffdimpl.h>   /*I  "petscmat.h"   I*/
35 
36 /*
37       The  method has one parameter that is used to
38    "cutoff" very small values. This is stored in a data structure
39    that is only visible to this file. If your method has no parameters
40    it can omit this, if it has several simply reorganize the data structure.
41    The data structure is "hung-off" the MatMFFD data structure in
42    the void *hctx; field.
43 */
44 typedef struct {
45   PetscReal umin;          /* minimum allowable u'a value relative to |u|_1 */
46 } MatMFFD_DS;
47 
48 /*
49    MatMFFDCompute_DS - Standard PETSc code for computing the
50    differencing parameter (h) for use 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_DS(MatMFFD ctx,Vec U,Vec a,PetscScalar *h,PetscBool  *zeroa)
62 {
63   MatMFFD_DS     *hctx = (MatMFFD_DS*)ctx->hctx;
64   PetscReal      nrm,sum,umin = hctx->umin;
65   PetscScalar    dot;
66 
67   PetscFunctionBegin;
68   if (!(ctx->count % ctx->recomputeperiod)) {
69     /*
70      This algorithm requires 2 norms and 1 inner product. Rather than
71      use directly the VecNorm() and VecDot() routines (and thus have
72      three separate collective operations, we use the VecxxxBegin/End() routines
73     */
74     PetscCall(VecDotBegin(U,a,&dot));
75     PetscCall(VecNormBegin(a,NORM_1,&sum));
76     PetscCall(VecNormBegin(a,NORM_2,&nrm));
77     PetscCall(VecDotEnd(U,a,&dot));
78     PetscCall(VecNormEnd(a,NORM_1,&sum));
79     PetscCall(VecNormEnd(a,NORM_2,&nrm));
80 
81     if (nrm == 0.0) {
82       *zeroa = PETSC_TRUE;
83       PetscFunctionReturn(0);
84     }
85     *zeroa = PETSC_FALSE;
86 
87     /*
88       Safeguard for step sizes that are "too small"
89     */
90     if (PetscAbsScalar(dot) < umin*sum && PetscRealPart(dot) >= 0.0) dot = umin*sum;
91     else if (PetscAbsScalar(dot) < 0.0 && PetscRealPart(dot) > -umin*sum) dot = -umin*sum;
92     *h = ctx->error_rel*dot/(nrm*nrm);
93     PetscCheck(!PetscIsInfOrNanScalar(*h),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Differencing parameter is not a number sum = %g dot = %g norm = %g",(double)sum,(double)PetscRealPart(dot),(double)nrm);
94   } else {
95     *h = ctx->currenth;
96   }
97   ctx->count++;
98   PetscFunctionReturn(0);
99 }
100 
101 /*
102    MatMFFDView_DS - Prints information about this particular
103    method for computing h. Note that this does not print the general
104    information about the matrix-free method, as such info is printed
105    by the calling routine.
106 
107    Input Parameters:
108 +  ctx - the matrix free context
109 -  viewer - the PETSc viewer
110 */
111 static PetscErrorCode MatMFFDView_DS(MatMFFD ctx,PetscViewer viewer)
112 {
113   MatMFFD_DS     *hctx = (MatMFFD_DS*)ctx->hctx;
114   PetscBool      iascii;
115 
116   PetscFunctionBegin;
117   /*
118      Currently this only handles the ascii file viewers, others
119      could be added, but for this type of object other viewers
120      make less sense
121   */
122   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
123   if (iascii) {
124     PetscCall(PetscViewerASCIIPrintf(viewer,"    umin=%g (minimum iterate parameter)\n",(double)hctx->umin));
125   }
126   PetscFunctionReturn(0);
127 }
128 
129 /*
130    MatMFFDSetFromOptions_DS - Looks in the options database for
131    any options appropriate for this method.
132 
133    Input Parameter:
134 .  ctx - the matrix free context
135 
136 */
137 static PetscErrorCode MatMFFDSetFromOptions_DS(PetscOptionItems *PetscOptionsObject,MatMFFD ctx)
138 {
139   MatMFFD_DS     *hctx = (MatMFFD_DS*)ctx->hctx;
140 
141   PetscFunctionBegin;
142   PetscOptionsHeadBegin(PetscOptionsObject,"Finite difference matrix free parameters");
143   PetscCall(PetscOptionsReal("-mat_mffd_umin","umin","MatMFFDDSSetUmin",hctx->umin,&hctx->umin,NULL));
144   PetscOptionsHeadEnd();
145   PetscFunctionReturn(0);
146 }
147 
148 /*
149    MatMFFDDestroy_DS - Frees the space allocated by
150    MatCreateMFFD_DS().
151 
152    Input Parameter:
153 .  ctx - the matrix free context
154 
155    Notes:
156    Does not free the ctx, that is handled by the calling routine
157 */
158 static PetscErrorCode MatMFFDDestroy_DS(MatMFFD ctx)
159 {
160   PetscFunctionBegin;
161   PetscCall(PetscFree(ctx->hctx));
162   PetscFunctionReturn(0);
163 }
164 
165 /*
166    The following two routines use the PetscObjectCompose() and PetscObjectQuery()
167    mechanism to allow the user to change the Umin parameter used in this method.
168 */
169 PetscErrorCode MatMFFDDSSetUmin_DS(Mat mat,PetscReal umin)
170 {
171   MatMFFD        ctx=NULL;
172   MatMFFD_DS     *hctx;
173 
174   PetscFunctionBegin;
175   PetscCall(MatShellGetContext(mat,&ctx));
176   PetscCheck(ctx,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatMFFDDSSetUmin() attached to non-shell matrix");
177   hctx       = (MatMFFD_DS*)ctx->hctx;
178   hctx->umin = umin;
179   PetscFunctionReturn(0);
180 }
181 
182 /*@
183     MatMFFDDSSetUmin - Sets the "umin" parameter used by the
184     PETSc routine for computing the differencing parameter, h, which is used
185     for matrix-free Jacobian-vector products.
186 
187    Input Parameters:
188 +  A - the matrix created with MatCreateSNESMF()
189 -  umin - the parameter
190 
191    Level: advanced
192 
193    Notes:
194    See the manual page for MatCreateSNESMF() for a complete description of the
195    algorithm used to compute h.
196 
197 .seealso: `MatMFFDSetFunctionError()`, `MatCreateSNESMF()`
198 
199 @*/
200 PetscErrorCode  MatMFFDDSSetUmin(Mat A,PetscReal umin)
201 {
202   PetscFunctionBegin;
203   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
204   PetscTryMethod(A,"MatMFFDDSSetUmin_C",(Mat,PetscReal),(A,umin));
205   PetscFunctionReturn(0);
206 }
207 
208 /*MC
209      MATMFFD_DS - the code for compute the "h" used in the finite difference
210             matrix-free matrix vector product.  This code
211         implements the strategy in Dennis and Schnabel, "Numerical Methods for Unconstrained
212         Optimization and Nonlinear Equations".
213 
214    Options Database Keys:
215 .  -mat_mffd_umin <umin> - see MatMFFDDSSetUmin()
216 
217    Level: intermediate
218 
219    Notes:
220     Requires 2 norms and 1 inner product, but they are computed together
221        so only one parallel collective operation is needed. See MATMFFD_WP for a method
222        (with GMRES) that requires NO collective operations.
223 
224    Formula used:
225      F'(u)*a = [F(u+h*a) - F(u)]/h where
226      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
227        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
228  where
229      error_rel = square root of relative error in function evaluation
230      umin = minimum iterate parameter
231 
232 .seealso: `MATMFFD`, `MatCreateMFFD()`, `MatCreateSNESMF()`, `MATMFFD_WP`, `MatMFFDDSSetUmin()`
233 
234 M*/
235 PETSC_EXTERN PetscErrorCode MatCreateMFFD_DS(MatMFFD ctx)
236 {
237   MatMFFD_DS     *hctx;
238 
239   PetscFunctionBegin;
240   /* allocate my own private data structure */
241   PetscCall(PetscNewLog(ctx,&hctx));
242   ctx->hctx = (void*)hctx;
243   /* set a default for my parameter */
244   hctx->umin = 1.e-6;
245 
246   /* set the functions I am providing */
247   ctx->ops->compute        = MatMFFDCompute_DS;
248   ctx->ops->destroy        = MatMFFDDestroy_DS;
249   ctx->ops->view           = MatMFFDView_DS;
250   ctx->ops->setfromoptions = MatMFFDSetFromOptions_DS;
251 
252   PetscCall(PetscObjectComposeFunction((PetscObject)ctx->mat,"MatMFFDDSSetUmin_C",MatMFFDDSSetUmin_DS));
253   PetscFunctionReturn(0);
254 }
255