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