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