Actual source code: iguess.c
  1: #include <petsc/private/kspimpl.h>
  3: PetscFunctionList KSPGuessList = NULL;
  4: static PetscBool  KSPGuessRegisterAllCalled;
  6: /*@C
  7:   KSPGuessRegister -  Registers a method for initial guess computation in Krylov subspace solver package.
  9:   Not Collective, No Fortran Support
 11:   Input Parameters:
 12: + sname    - name of a new user-defined solver
 13: - function - routine to create method context
 15:   Example Usage:
 16: .vb
 17:    KSPGuessRegister("my_initial_guess", MyInitialGuessCreate);
 18: .ve
 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`
 27:   Level: developer
 29:   Note:
 30:   `KSPGuessRegister()` may be called multiple times to add several user-defined solvers.
 32: .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessRegisterAll()`
 33: @*/
 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: }
 42: /*@C
 43:   KSPGuessRegisterAll - Registers all `KSPGuess` implementations in the `KSP` package.
 45:   Not Collective
 47:   Level: developer
 49: .seealso: [](ch_ksp), `KSPGuess`, `KSPRegisterAll()`, `KSPInitializePackage()`
 50: @*/
 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: }
 61: /*@
 62:   KSPGuessSetFromOptions - Sets the options for a `KSPGuess` from the options database
 64:   Collective
 66:   Input Parameter:
 67: . guess - `KSPGuess` object
 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)
 80:   Level: developer
 82: .seealso: [](ch_ksp), `KSPGuess`, `KSPGetGuess()`, `KSPGuessSetType()`, `KSPGuessType`
 83: @*/
 84: PetscErrorCode KSPGuessSetFromOptions(KSPGuess guess)
 85: {
 86:   PetscFunctionBegin;
 88:   PetscTryTypeMethod(guess, setfromoptions);
 89:   PetscFunctionReturn(PETSC_SUCCESS);
 90: }
 92: /*@
 93:   KSPGuessSetTolerance - Sets the relative tolerance used in either eigenvalue (POD) or singular value (Fischer type 3) calculations.
 95:   Collective
 97:   Input Parameters:
 98: + guess - `KSPGuess` object
 99: - tol   - the tolerance
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
105:   Level: developer
107:   Note:
108:   Ignored by the first and second Fischer guess types
110: .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessType`, `KSPGuessSetFromOptions()`
111: @*/
112: PetscErrorCode KSPGuessSetTolerance(KSPGuess guess, PetscReal tol)
113: {
114:   PetscFunctionBegin;
116:   PetscTryTypeMethod(guess, settolerance, tol);
117:   PetscFunctionReturn(PETSC_SUCCESS);
118: }
120: /*@
121:   KSPGuessDestroy - Destroys `KSPGuess` context.
123:   Collective
125:   Input Parameter:
126: . guess - initial guess object
128:   Level: developer
130: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`, `KSPGuessType`
131: @*/
132: PetscErrorCode KSPGuessDestroy(KSPGuess *guess)
133: {
134:   PetscFunctionBegin;
135:   if (!*guess) PetscFunctionReturn(PETSC_SUCCESS);
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: }
147: /*@
148:   KSPGuessView - View the `KSPGuess` object
150:   Logically Collective
152:   Input Parameters:
153: + guess - the initial guess object for the Krylov method
154: - view  - the viewer object
156:   Options Database Key:
157: . -ksp_guess_view viewer - view the `KSPGuess` object
159:   Level: developer
161: .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPGuessType`, `KSPGuessRegister()`, `KSPGuessCreate()`, `PetscViewer`
162: @*/
163: PetscErrorCode KSPGuessView(KSPGuess guess, PetscViewer view)
164: {
165:   PetscBool ascii;
167:   PetscFunctionBegin;
169:   if (!view) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)guess), &view));
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: }
182: /*@
183:   KSPGuessCreate - Creates a `KSPGuess` context.
185:   Collective
187:   Input Parameter:
188: . comm - MPI communicator
190:   Output Parameter:
191: . guess - location to put the `KSPGuess` context
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)
204:   Level: developer
206:   Note:
207:   These are generally created automatically by using the option `-ksp_guess_type type` and controlled from the options database
209:   There are two families of methods `KSPGUESSFISCHER`, developed by Paul Fischer and `KSPGUESSPOD`
211: .seealso: [](ch_ksp), `KSPSolve()`, `KSPGuessDestroy()`, `KSPGuess`, `KSPGuessType`, `KSP`
212: @*/
213: PetscErrorCode KSPGuessCreate(MPI_Comm comm, KSPGuess *guess)
214: {
215:   KSPGuess tguess;
217:   PetscFunctionBegin;
218:   PetscAssertPointer(guess, 2);
219:   PetscCall(KSPInitializePackage());
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: }
227: /*@
228:   KSPGuessSetType - Sets the type of a `KSPGuess`. Each `KSPGuessType` provides a different algorithm for computing the initial guess.
230:   Logically Collective
232:   Input Parameters:
233: + guess - the initial guess object for the Krylov method
234: - type  - a known `KSPGuessType`
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
239:   Level: developer
241: .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPGuessType`, `KSPGuessRegister()`, `KSPGuessCreate()`, `KSPGUESSFISCHER`, `KSPGUESSPOD`
242: @*/
243: PetscErrorCode KSPGuessSetType(KSPGuess guess, KSPGuessType type)
244: {
245:   PetscBool match;
246:   PetscErrorCode (*r)(KSPGuess);
248:   PetscFunctionBegin;
250:   PetscAssertPointer(type, 2);
252:   PetscCall(PetscObjectTypeCompare((PetscObject)guess, type, &match));
253:   if (match) PetscFunctionReturn(PETSC_SUCCESS);
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;
260:   PetscCall(PetscMemzero(guess->ops, sizeof(struct _KSPGuessOps)));
261:   PetscCall(PetscObjectChangeTypeName((PetscObject)guess, type));
262:   PetscCall((*r)(guess));
263:   PetscFunctionReturn(PETSC_SUCCESS);
264: }
266: /*@
267:   KSPGuessGetType - Gets the `KSPGuessType` as a string from the `KSPGuess` object.
269:   Not Collective
271:   Input Parameter:
272: . guess - the initial guess context
274:   Output Parameter:
275: . type - type of `KSPGuess` method
277:   Level: developer
279: .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessSetType()`
280: @*/
281: PetscErrorCode KSPGuessGetType(KSPGuess guess, KSPGuessType *type)
282: {
283:   PetscFunctionBegin;
285:   PetscAssertPointer(type, 2);
286:   *type = ((PetscObject)guess)->type_name;
287:   PetscFunctionReturn(PETSC_SUCCESS);
288: }
290: /*@
291:   KSPGuessUpdate - Updates the guess object with the current solution and rhs vector
293:   Collective
295:   Input Parameters:
296: + guess - the initial guess context
297: . rhs   - the corresponding rhs
298: - sol   - the computed solution
300:   Level: developer
302: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
303: @*/
304: PetscErrorCode KSPGuessUpdate(KSPGuess guess, Vec rhs, Vec sol)
305: {
306:   PetscFunctionBegin;
310:   PetscTryTypeMethod(guess, update, rhs, sol);
311:   PetscFunctionReturn(PETSC_SUCCESS);
312: }
314: /*@
315:   KSPGuessFormGuess - Form the initial guess
317:   Collective
319:   Input Parameters:
320: + guess - the initial guess context
321: . rhs   - the current right-hand side vector
322: - sol   - the initial guess vector
324:   Level: developer
326: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
327: @*/
328: PetscErrorCode KSPGuessFormGuess(KSPGuess guess, Vec rhs, Vec sol)
329: {
330:   PetscFunctionBegin;
334:   PetscTryTypeMethod(guess, formguess, rhs, sol);
335:   PetscFunctionReturn(PETSC_SUCCESS);
336: }
338: /*@
339:   KSPGuessSetUp - Setup the initial guess object
341:   Collective
343:   Input Parameter:
344: . guess - the initial guess context
346:   Level: developer
348: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
349: @*/
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;
358:   PetscFunctionBegin;
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: }