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