Actual source code: mffddef.c


  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.

  7:   To make your own: clone this file and modify for your needs.

  9:   Mandatory functions:
 10:   -------------------
 11:       MatMFFDCompute_  - for a given point and direction computes h

 13:       MatCreateMFFD _ - fills in the MatMFFD data structure
 14:                            for this particular implementation

 16:    Optional functions:
 17:    -------------------
 18:       MatMFFDView_ - prints information about the parameters being used.
 19:                        This is called when SNESView() or -snes_view is used.

 21:       MatMFFDSetFromOptions_ - checks the options database for options that
 22:                                apply to this method.

 24:       MatMFFDDestroy_ - frees any space allocated by the routines above

 26: */

 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>

 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;

 48: /*
 49:    MatMFFDCompute_DS - Standard PETSc code for computing the
 50:    differencing parameter (h) for use with matrix-free finite differences.

 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

 57:    Output Parameter:
 58: .  h - the scale computed

 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;

 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));

 81:     if (nrm == 0.0) {
 82:       *zeroa = PETSC_TRUE;
 83:       PetscFunctionReturn(PETSC_SUCCESS);
 84:     }
 85:     *zeroa = PETSC_FALSE;

 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(PETSC_SUCCESS);
 99: }

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.

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;

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) PetscCall(PetscViewerASCIIPrintf(viewer, "    umin=%g (minimum iterate parameter)\n", (double)hctx->umin));
124:   PetscFunctionReturn(PETSC_SUCCESS);
125: }

127: /*
128:    MatMFFDSetFromOptions_DS - Looks in the options database for
129:    any options appropriate for this method.

131:    Input Parameter:
132: .  ctx - the matrix free context

134: */
135: static PetscErrorCode MatMFFDSetFromOptions_DS(MatMFFD ctx, PetscOptionItems *PetscOptionsObject)
136: {
137:   MatMFFD_DS *hctx = (MatMFFD_DS *)ctx->hctx;

139:   PetscFunctionBegin;
140:   PetscOptionsHeadBegin(PetscOptionsObject, "Finite difference matrix free parameters");
141:   PetscCall(PetscOptionsReal("-mat_mffd_umin", "umin", "MatMFFDDSSetUmin", hctx->umin, &hctx->umin, NULL));
142:   PetscOptionsHeadEnd();
143:   PetscFunctionReturn(PETSC_SUCCESS);
144: }

146: /*
147:    MatMFFDDestroy_DS - Frees the space allocated by
148:    MatCreateMFFD_DS().

150:    Input Parameter:
151: .  ctx - the matrix free context

153:    Note:
154:    Does not free the ctx, that is handled by the calling routine
155: */
156: static PetscErrorCode MatMFFDDestroy_DS(MatMFFD ctx)
157: {
158:   PetscFunctionBegin;
159:   PetscCall(PetscFree(ctx->hctx));
160:   PetscFunctionReturn(PETSC_SUCCESS);
161: }

163: /*
164:    The following two routines use the PetscObjectCompose() and PetscObjectQuery()
165:    mechanism to allow the user to change the Umin parameter used in this method.
166: */
167: PetscErrorCode MatMFFDDSSetUmin_DS(Mat mat, PetscReal umin)
168: {
169:   MatMFFD     ctx = NULL;
170:   MatMFFD_DS *hctx;

172:   PetscFunctionBegin;
173:   PetscCall(MatShellGetContext(mat, &ctx));
174:   PetscCheck(ctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MatMFFDDSSetUmin() attached to non-shell matrix");
175:   hctx       = (MatMFFD_DS *)ctx->hctx;
176:   hctx->umin = umin;
177:   PetscFunctionReturn(PETSC_SUCCESS);
178: }

180: /*@
181:     MatMFFDDSSetUmin - Sets the "umin" parameter used by the
182:     PETSc routine for computing the differencing parameter, h, which is used
183:     for matrix-free Jacobian-vector products for a `MATMFFD` matrix.

185:    Input Parameters:
186: +  A - the `MATMFFD` matrix
187: -  umin - the parameter

189:    Level: advanced

191:    Note:
192:    See the manual page for `MatCreateSNESMF()` for a complete description of the
193:    algorithm used to compute h.

195: .seealso: `MATMFFD`, `MatMFFDSetFunctionError()`, `MatCreateSNESMF()`
196: @*/
197: PetscErrorCode MatMFFDDSSetUmin(Mat A, PetscReal umin)
198: {
199:   PetscFunctionBegin;
201:   PetscTryMethod(A, "MatMFFDDSSetUmin_C", (Mat, PetscReal), (A, umin));
202:   PetscFunctionReturn(PETSC_SUCCESS);
203: }

205: /*MC
206:      MATMFFD_DS - algorithm for compute the "h" used in the finite difference matrix-free matrix vector product, `MatMult()`.

208:    Options Database Keys:
209: .  -mat_mffd_umin <umin> - see `MatMFFDDSSetUmin()`

211:    Level: intermediate

213:    Notes:
214:     Requires 2 norms and 1 inner product, but they are computed together
215:        so only one parallel collective operation is needed. See `MATMFFD_WP` for a method
216:        (with `KSPGMRES`) that requires NO collective operations.

218:    Formula used:
219:      F'(u)*a = [F(u+h*a) - F(u)]/h where
220:      h = error_rel*u'a/||a||^2                        if  |u'a| > umin*||a||_{1}
221:        = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2   otherwise
222:  where
223:      error_rel = square root of relative error in function evaluation
224:      umin = minimum iterate parameter

226:   References:
227: .  * -  Dennis and Schnabel, "Numerical Methods for Unconstrained Optimization and Nonlinear Equations"

229: .seealso: `MATMFFD`, `MATMFFD_WP`, `MatCreateMFFD()`, `MatCreateSNESMF()`, `MATMFFD_WP`, `MatMFFDDSSetUmin()`
230: M*/
231: PETSC_EXTERN PetscErrorCode MatCreateMFFD_DS(MatMFFD ctx)
232: {
233:   MatMFFD_DS *hctx;

235:   PetscFunctionBegin;
236:   /* allocate my own private data structure */
237:   PetscCall(PetscNew(&hctx));
238:   ctx->hctx = (void *)hctx;
239:   /* set a default for my parameter */
240:   hctx->umin = 1.e-6;

242:   /* set the functions I am providing */
243:   ctx->ops->compute        = MatMFFDCompute_DS;
244:   ctx->ops->destroy        = MatMFFDDestroy_DS;
245:   ctx->ops->view           = MatMFFDView_DS;
246:   ctx->ops->setfromoptions = MatMFFDSetFromOptions_DS;

248:   PetscCall(PetscObjectComposeFunction((PetscObject)ctx->mat, "MatMFFDDSSetUmin_C", MatMFFDDSSetUmin_DS));
249:   PetscFunctionReturn(PETSC_SUCCESS);
250: }