xref: /petsc/src/ksp/ksp/interface/iguess.c (revision 76d6960897ba55d8238485170da43545084300c6)
1 #include <petsc/private/kspimpl.h> /*I "petscksp.h"  I*/
2 
3 PetscFunctionList KSPGuessList = NULL;
4 static PetscBool  KSPGuessRegisterAllCalled;
5 
6 /*@C
7   KSPGuessRegister -  Registers a method for initial guess computation in Krylov subspace solver package.
8 
9   Not Collective, No Fortran Support
10 
11   Input Parameters:
12 + sname    - name of a new user-defined solver
13 - function - routine to create method context
14 
15   Example Usage:
16 .vb
17    KSPGuessRegister("my_initial_guess", MyInitialGuessCreate);
18 .ve
19 
20   Then, it can be chosen with the procedural interface via
21 .vb
22   KSPGetGuess(ksp, &guess);
23   KSPGuessSetType(guess, "my_initial_guess");
24 .ve
25   or at runtime via the option `-ksp_guess_type my_initial_guess`
26 
27   Level: developer
28 
29   Note:
30   `KSPGuessRegister()` may be called multiple times to add several user-defined solvers.
31 
32 .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessRegisterAll()`
33 @*/
KSPGuessRegister(const char sname[],PetscErrorCode (* function)(KSPGuess))34 PetscErrorCode KSPGuessRegister(const char sname[], PetscErrorCode (*function)(KSPGuess))
35 {
36   PetscFunctionBegin;
37   PetscCall(KSPInitializePackage());
38   PetscCall(PetscFunctionListAdd(&KSPGuessList, sname, function));
39   PetscFunctionReturn(PETSC_SUCCESS);
40 }
41 
42 /*@C
43   KSPGuessRegisterAll - Registers all `KSPGuess` implementations in the `KSP` package.
44 
45   Not Collective
46 
47   Level: developer
48 
49 .seealso: [](ch_ksp), `KSPGuess`, `KSPRegisterAll()`, `KSPInitializePackage()`
50 @*/
KSPGuessRegisterAll(void)51 PetscErrorCode KSPGuessRegisterAll(void)
52 {
53   PetscFunctionBegin;
54   if (KSPGuessRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
55   KSPGuessRegisterAllCalled = PETSC_TRUE;
56   PetscCall(KSPGuessRegister(KSPGUESSFISCHER, KSPGuessCreate_Fischer));
57   PetscCall(KSPGuessRegister(KSPGUESSPOD, KSPGuessCreate_POD));
58   PetscFunctionReturn(PETSC_SUCCESS);
59 }
60 
61 /*@
62   KSPGuessSetFromOptions - Sets the options for a `KSPGuess` from the options database
63 
64   Collective
65 
66   Input Parameter:
67 . guess - `KSPGuess` object
68 
69   Options Database Keys:
70 + -ksp_guess_type <method>       - Turns on generation of initial guesses and sets the method; use -help for a list of available methods
71 . -ksp_guess_view <viewer>       - view the `KSPGuess` object
72 . -ksp_guess_fischer_model <a,b> - set details for the Fischer models
73 . -ksp_guess_fischer_monitor     - monitor the Fischer models
74 . -ksp_guess_fischer_tol <tol>   - set the tolerance for the Fischer models
75 . -ksp_guess_pod_size <size>     - Number of snapshots
76 . -ksp_guess_pod_monitor true    - monitor the pod initial guess processing
77 . -ksp_guess_pod_tol <tol>       - Tolerance to retain eigenvectors
78 - -ksp_guess_pod_Ainner true     - Use the operator as inner product (must be SPD)
79 
80   Level: developer
81 
82 .seealso: [](ch_ksp), `KSPGuess`, `KSPGetGuess()`, `KSPGuessSetType()`, `KSPGuessType`
83 @*/
KSPGuessSetFromOptions(KSPGuess guess)84 PetscErrorCode KSPGuessSetFromOptions(KSPGuess guess)
85 {
86   PetscFunctionBegin;
87   PetscValidHeaderSpecific(guess, KSPGUESS_CLASSID, 1);
88   PetscTryTypeMethod(guess, setfromoptions);
89   PetscFunctionReturn(PETSC_SUCCESS);
90 }
91 
92 /*@
93   KSPGuessSetTolerance - Sets the relative tolerance used in either eigenvalue (POD) or singular value (Fischer type 3) calculations.
94 
95   Collective
96 
97   Input Parameters:
98 + guess - `KSPGuess` object
99 - tol   - the tolerance
100 
101   Options Database Key:
102 + -ksp_guess_fischer_tol <tol> - set the tolerance for the Fischer models
103 - -ksp_guess_pod_tol <tol>     - set the tolerance for the Pod models
104 
105   Level: developer
106 
107   Note:
108   Ignored by the first and second Fischer guess types
109 
110 .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessType`, `KSPGuessSetFromOptions()`
111 @*/
KSPGuessSetTolerance(KSPGuess guess,PetscReal tol)112 PetscErrorCode KSPGuessSetTolerance(KSPGuess guess, PetscReal tol)
113 {
114   PetscFunctionBegin;
115   PetscValidHeaderSpecific(guess, KSPGUESS_CLASSID, 1);
116   PetscTryTypeMethod(guess, settolerance, tol);
117   PetscFunctionReturn(PETSC_SUCCESS);
118 }
119 
120 /*@
121   KSPGuessDestroy - Destroys `KSPGuess` context.
122 
123   Collective
124 
125   Input Parameter:
126 . guess - initial guess object
127 
128   Level: developer
129 
130 .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`, `KSPGuessType`
131 @*/
KSPGuessDestroy(KSPGuess * guess)132 PetscErrorCode KSPGuessDestroy(KSPGuess *guess)
133 {
134   PetscFunctionBegin;
135   if (!*guess) PetscFunctionReturn(PETSC_SUCCESS);
136   PetscValidHeaderSpecific(*guess, KSPGUESS_CLASSID, 1);
137   if (--((PetscObject)*guess)->refct > 0) {
138     *guess = NULL;
139     PetscFunctionReturn(PETSC_SUCCESS);
140   }
141   PetscTryTypeMethod(*guess, destroy);
142   PetscCall(MatDestroy(&(*guess)->A));
143   PetscCall(PetscHeaderDestroy(guess));
144   PetscFunctionReturn(PETSC_SUCCESS);
145 }
146 
147 /*@
148   KSPGuessView - View the `KSPGuess` object
149 
150   Logically Collective
151 
152   Input Parameters:
153 + guess - the initial guess object for the Krylov method
154 - view  - the viewer object
155 
156   Options Database Key:
157 . -ksp_guess_view viewer - view the `KSPGuess` object
158 
159   Level: developer
160 
161 .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPGuessType`, `KSPGuessRegister()`, `KSPGuessCreate()`, `PetscViewer`
162 @*/
KSPGuessView(KSPGuess guess,PetscViewer view)163 PetscErrorCode KSPGuessView(KSPGuess guess, PetscViewer view)
164 {
165   PetscBool ascii;
166 
167   PetscFunctionBegin;
168   PetscValidHeaderSpecific(guess, KSPGUESS_CLASSID, 1);
169   if (!view) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)guess), &view));
170   PetscValidHeaderSpecific(view, PETSC_VIEWER_CLASSID, 2);
171   PetscCheckSameComm(guess, 1, view, 2);
172   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &ascii));
173   if (ascii) {
174     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)guess, view));
175     PetscCall(PetscViewerASCIIPushTab(view));
176     PetscTryTypeMethod(guess, view, view);
177     PetscCall(PetscViewerASCIIPopTab(view));
178   }
179   PetscFunctionReturn(PETSC_SUCCESS);
180 }
181 
182 /*@
183   KSPGuessCreate - Creates a `KSPGuess` context.
184 
185   Collective
186 
187   Input Parameter:
188 . comm - MPI communicator
189 
190   Output Parameter:
191 . guess - location to put the `KSPGuess` context
192 
193   Options Database Keys:
194 + -ksp_guess_type  <method>      - Turns on generation of initial guesses and sets the method; use -help for a list of available methods
195 . -ksp_guess_view <viewer>       - view the `KSPGuess` object
196 . -ksp_guess_fischer_model <a,b> - set details for the Fischer models
197 . -ksp_guess_fischer_monitor     - monitor the fischer models
198 . -ksp_guess_fischer_tol <tol>   - set the tolerance for the Fischer models
199 . -ksp_guess_pod_size <size>     - Number of snapshots
200 . -ksp_guess_pod_monitor true    - monitor the pod initial guess processing
201 . -ksp_guess_pod_tol <tol>       - Tolerance to retain eigenvectors
202 - -ksp_guess_pod_Ainner true     - Use the operator as inner product (must be SPD)
203 
204   Level: developer
205 
206   Note:
207   These are generally created automatically by using the option `-ksp_guess_type type` and controlled from the options database
208 
209   There are two families of methods `KSPGUESSFISCHER`, developed by Paul Fischer and `KSPGUESSPOD`
210 
211 .seealso: [](ch_ksp), `KSPSolve()`, `KSPGuessDestroy()`, `KSPGuess`, `KSPGuessType`, `KSP`
212 @*/
KSPGuessCreate(MPI_Comm comm,KSPGuess * guess)213 PetscErrorCode KSPGuessCreate(MPI_Comm comm, KSPGuess *guess)
214 {
215   KSPGuess tguess;
216 
217   PetscFunctionBegin;
218   PetscAssertPointer(guess, 2);
219   PetscCall(KSPInitializePackage());
220 
221   PetscCall(PetscHeaderCreate(tguess, KSPGUESS_CLASSID, "KSPGuess", "Initial guess for Krylov Method", "KSPGuess", comm, KSPGuessDestroy, KSPGuessView));
222   tguess->omatstate = -1;
223   *guess            = tguess;
224   PetscFunctionReturn(PETSC_SUCCESS);
225 }
226 
227 /*@
228   KSPGuessSetType - Sets the type of a `KSPGuess`. Each `KSPGuessType` provides a different algorithm for computing the initial guess.
229 
230   Logically Collective
231 
232   Input Parameters:
233 + guess - the initial guess object for the Krylov method
234 - type  - a known `KSPGuessType`
235 
236   Options Database Key:
237 . -ksp_guess_type  <method> - Turns on generation of initial guesses and sets the method; see `KSPGuessType` for a list of available types
238 
239   Level: developer
240 
241 .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPGuessType`, `KSPGuessRegister()`, `KSPGuessCreate()`, `KSPGUESSFISCHER`, `KSPGUESSPOD`
242 @*/
KSPGuessSetType(KSPGuess guess,KSPGuessType type)243 PetscErrorCode KSPGuessSetType(KSPGuess guess, KSPGuessType type)
244 {
245   PetscBool match;
246   PetscErrorCode (*r)(KSPGuess);
247 
248   PetscFunctionBegin;
249   PetscValidHeaderSpecific(guess, KSPGUESS_CLASSID, 1);
250   PetscAssertPointer(type, 2);
251 
252   PetscCall(PetscObjectTypeCompare((PetscObject)guess, type, &match));
253   if (match) PetscFunctionReturn(PETSC_SUCCESS);
254 
255   PetscCall(PetscFunctionListFind(KSPGuessList, type, &r));
256   PetscCheck(r, PetscObjectComm((PetscObject)guess), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested KSPGuess type %s", type);
257   PetscTryTypeMethod(guess, destroy);
258   guess->ops->destroy = NULL;
259 
260   PetscCall(PetscMemzero(guess->ops, sizeof(struct _KSPGuessOps)));
261   PetscCall(PetscObjectChangeTypeName((PetscObject)guess, type));
262   PetscCall((*r)(guess));
263   PetscFunctionReturn(PETSC_SUCCESS);
264 }
265 
266 /*@
267   KSPGuessGetType - Gets the `KSPGuessType` as a string from the `KSPGuess` object.
268 
269   Not Collective
270 
271   Input Parameter:
272 . guess - the initial guess context
273 
274   Output Parameter:
275 . type - type of `KSPGuess` method
276 
277   Level: developer
278 
279 .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessSetType()`
280 @*/
KSPGuessGetType(KSPGuess guess,KSPGuessType * type)281 PetscErrorCode KSPGuessGetType(KSPGuess guess, KSPGuessType *type)
282 {
283   PetscFunctionBegin;
284   PetscValidHeaderSpecific(guess, KSPGUESS_CLASSID, 1);
285   PetscAssertPointer(type, 2);
286   *type = ((PetscObject)guess)->type_name;
287   PetscFunctionReturn(PETSC_SUCCESS);
288 }
289 
290 /*@
291   KSPGuessUpdate - Updates the guess object with the current solution and rhs vector
292 
293   Collective
294 
295   Input Parameters:
296 + guess - the initial guess context
297 . rhs   - the corresponding rhs
298 - sol   - the computed solution
299 
300   Level: developer
301 
302 .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
303 @*/
KSPGuessUpdate(KSPGuess guess,Vec rhs,Vec sol)304 PetscErrorCode KSPGuessUpdate(KSPGuess guess, Vec rhs, Vec sol)
305 {
306   PetscFunctionBegin;
307   PetscValidHeaderSpecific(guess, KSPGUESS_CLASSID, 1);
308   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
309   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
310   PetscTryTypeMethod(guess, update, rhs, sol);
311   PetscFunctionReturn(PETSC_SUCCESS);
312 }
313 
314 /*@
315   KSPGuessFormGuess - Form the initial guess
316 
317   Collective
318 
319   Input Parameters:
320 + guess - the initial guess context
321 . rhs   - the current right-hand side vector
322 - sol   - the initial guess vector
323 
324   Level: developer
325 
326 .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
327 @*/
KSPGuessFormGuess(KSPGuess guess,Vec rhs,Vec sol)328 PetscErrorCode KSPGuessFormGuess(KSPGuess guess, Vec rhs, Vec sol)
329 {
330   PetscFunctionBegin;
331   PetscValidHeaderSpecific(guess, KSPGUESS_CLASSID, 1);
332   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
333   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
334   PetscTryTypeMethod(guess, formguess, rhs, sol);
335   PetscFunctionReturn(PETSC_SUCCESS);
336 }
337 
338 /*@
339   KSPGuessSetUp - Setup the initial guess object
340 
341   Collective
342 
343   Input Parameter:
344 . guess - the initial guess context
345 
346   Level: developer
347 
348 .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
349 @*/
KSPGuessSetUp(KSPGuess guess)350 PetscErrorCode KSPGuessSetUp(KSPGuess guess)
351 {
352   PetscObjectState matstate;
353   PetscInt         oM = 0, oN = 0, M, N;
354   Mat              omat = NULL;
355   PC               pc;
356   PetscBool        reuse;
357 
358   PetscFunctionBegin;
359   PetscValidHeaderSpecific(guess, KSPGUESS_CLASSID, 1);
360   if (guess->A) {
361     omat = guess->A;
362     PetscCall(MatGetSize(guess->A, &oM, &oN));
363   }
364   PetscCall(KSPGetOperators(guess->ksp, &guess->A, NULL));
365   PetscCall(KSPGetPC(guess->ksp, &pc));
366   PetscCall(PCGetReusePreconditioner(pc, &reuse));
367   PetscCall(PetscObjectReference((PetscObject)guess->A));
368   PetscCall(MatGetSize(guess->A, &M, &N));
369   PetscCall(PetscObjectStateGet((PetscObject)guess->A, &matstate));
370   if (M != oM || N != oN) {
371     PetscCall(PetscInfo(guess, "Resetting KSPGuess since matrix sizes have changed (%" PetscInt_FMT " != %" PetscInt_FMT ", %" PetscInt_FMT " != %" PetscInt_FMT ")\n", oM, M, oN, N));
372   } else if (!reuse && (omat != guess->A || guess->omatstate != matstate)) {
373     PetscCall(PetscInfo(guess, "Resetting KSPGuess since %s has changed\n", omat != guess->A ? "matrix" : "matrix state"));
374     PetscTryTypeMethod(guess, reset);
375   } else if (reuse) {
376     PetscCall(PetscInfo(guess, "Not resettting KSPGuess since reuse preconditioner has been specified\n"));
377   } else {
378     PetscCall(PetscInfo(guess, "KSPGuess status unchanged\n"));
379   }
380   PetscTryTypeMethod(guess, setup);
381   guess->omatstate = matstate;
382   PetscCall(MatDestroy(&omat));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385