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

 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:   KSPSetGuessType(ksp, "my_initial_guess")
 23: .ve
 24:   or at runtime via the option `-ksp_guess_type my_initial_guess`

 26:   Level: developer

 28:   Note:
 29:   `KSPGuessRegister()` may be called multiple times to add several user-defined solvers.

 31: .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessRegisterAll()`
 32: @*/
 33: PetscErrorCode KSPGuessRegister(const char sname[], PetscErrorCode (*function)(KSPGuess))
 34: {
 35:   PetscFunctionBegin;
 36:   PetscCall(KSPInitializePackage());
 37:   PetscCall(PetscFunctionListAdd(&KSPGuessList, sname, function));
 38:   PetscFunctionReturn(PETSC_SUCCESS);
 39: }

 41: /*@C
 42:   KSPGuessRegisterAll - Registers all `KSPGuess` implementations in the `KSP` package.

 44:   Not Collective

 46:   Level: developer

 48: .seealso: [](ch_ksp), `KSPGuess`, `KSPRegisterAll()`, `KSPInitializePackage()`
 49: @*/
 50: PetscErrorCode KSPGuessRegisterAll(void)
 51: {
 52:   PetscFunctionBegin;
 53:   if (KSPGuessRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
 54:   KSPGuessRegisterAllCalled = PETSC_TRUE;
 55:   PetscCall(KSPGuessRegister(KSPGUESSFISCHER, KSPGuessCreate_Fischer));
 56:   PetscCall(KSPGuessRegister(KSPGUESSPOD, KSPGuessCreate_POD));
 57:   PetscFunctionReturn(PETSC_SUCCESS);
 58: }

 60: /*@
 61:   KSPGuessSetFromOptions - Sets the options for a `KSPGuess` from the options database

 63:   Collective

 65:   Input Parameter:
 66: . guess - `KSPGuess` object

 68:   Options Database Keys:
 69: + -ksp_guess_type  <method>      - Turns on generation of initial guesses and sets the method; use -help for a list of available methods
 70: . -ksp_guess_view <viewer>       - view the `KSPGuess` object
 71: . -ksp_guess_fischer_model <a,b> - set details for the Fischer models
 72: . -ksp_guess_fischer_monitor     - monitor the Fischer models
 73: . -ksp_guess_fischer_tol <tol>   - set the tolerance for the Fischer models
 74: . -ksp_guess_pod_size <size>     - Number of snapshots
 75: . -ksp_guess_pod_monitor true    - monitor the pod initial guess processing
 76: . -ksp_guess_pod_tol <tol>       - Tolerance to retain eigenvectors
 77: - -ksp_guess_pod_Ainner true     - Use the operator as inner product (must be SPD)

 79:   Level: developer

 81: .seealso: [](ch_ksp), `KSPGuess`, `KSPGetGuess()`, `KSPSetGuessType()`, `KSPGuessType`
 82: @*/
 83: PetscErrorCode KSPGuessSetFromOptions(KSPGuess guess)
 84: {
 85:   PetscFunctionBegin;
 87:   PetscTryTypeMethod(guess, setfromoptions);
 88:   PetscFunctionReturn(PETSC_SUCCESS);
 89: }

 91: /*@
 92:   KSPGuessSetTolerance - Sets the relative tolerance used in either eigenvalue (POD) or singular value (Fischer type 3) calculations.

 94:   Collective

 96:   Input Parameters:
 97: + guess - `KSPGuess` object
 98: - tol   - the tolerance

100:   Options Database Key:
101: + -ksp_guess_fischer_tol <tol> - set the tolerance for the Fischer models
102: - -ksp_guess_pod_tol <tol>     - set the tolerance for the Pod models

104:   Level: developer

106:   Note:
107:   Ignored by the first and second Fischer guess types

109: .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessType`, `KSPGuessSetFromOptions()`
110: @*/
111: PetscErrorCode KSPGuessSetTolerance(KSPGuess guess, PetscReal tol)
112: {
113:   PetscFunctionBegin;
115:   PetscTryTypeMethod(guess, settolerance, tol);
116:   PetscFunctionReturn(PETSC_SUCCESS);
117: }

119: /*@
120:   KSPGuessDestroy - Destroys `KSPGuess` context.

122:   Collective

124:   Input Parameter:
125: . guess - initial guess object

127:   Level: developer

129: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`, `KSPGuessType`
130: @*/
131: PetscErrorCode KSPGuessDestroy(KSPGuess *guess)
132: {
133:   PetscFunctionBegin;
134:   if (!*guess) PetscFunctionReturn(PETSC_SUCCESS);
136:   if (--((PetscObject)(*guess))->refct > 0) {
137:     *guess = NULL;
138:     PetscFunctionReturn(PETSC_SUCCESS);
139:   }
140:   PetscTryTypeMethod((*guess), destroy);
141:   PetscCall(MatDestroy(&(*guess)->A));
142:   PetscCall(PetscHeaderDestroy(guess));
143:   PetscFunctionReturn(PETSC_SUCCESS);
144: }

146: /*@C
147:   KSPGuessView - View the `KSPGuess` object

149:   Logically Collective

151:   Input Parameters:
152: + guess - the initial guess object for the Krylov method
153: - view  - the viewer object

155:   Options Database Key:
156: . -ksp_guess_view viewer - view the `KSPGuess` object

158:   Level: developer

160: .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPGuessType`, `KSPGuessRegister()`, `KSPGuessCreate()`, `PetscViewer`
161: @*/
162: PetscErrorCode KSPGuessView(KSPGuess guess, PetscViewer view)
163: {
164:   PetscBool ascii;

166:   PetscFunctionBegin;
168:   if (!view) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)guess), &view));
170:   PetscCheckSameComm(guess, 1, view, 2);
171:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &ascii));
172:   if (ascii) {
173:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)guess, view));
174:     PetscCall(PetscViewerASCIIPushTab(view));
175:     PetscTryTypeMethod(guess, view, view);
176:     PetscCall(PetscViewerASCIIPopTab(view));
177:   }
178:   PetscFunctionReturn(PETSC_SUCCESS);
179: }

181: /*@
182:   KSPGuessCreate - Creates a `KSPGuess` context.

184:   Collective

186:   Input Parameter:
187: . comm - MPI communicator

189:   Output Parameter:
190: . guess - location to put the `KSPGuess` context

192:   Options Database Keys:
193: + -ksp_guess_type  <method>      - Turns on generation of initial guesses and sets the method; use -help for a list of available methods
194: . -ksp_guess_view <viewer>       - view the `KSPGuess` object
195: . -ksp_guess_fischer_model <a,b> - set details for the Fischer models
196: . -ksp_guess_fischer_monitor     - monitor the fischer models
197: . -ksp_guess_fischer_tol <tol>   - set the tolerance for the Fischer models
198: . -ksp_guess_pod_size <size>     - Number of snapshots
199: . -ksp_guess_pod_monitor true    - monitor the pod initial guess processing
200: . -ksp_guess_pod_tol <tol>       - Tolerance to retain eigenvectors
201: - -ksp_guess_pod_Ainner true     - Use the operator as inner product (must be SPD)

203:   Level: developer

205:   Note:
206:   These are generally created automatically by using the option `-ksp_guess_type type` and controlled from the options database

208:   There are two families of methods `KSPGUESSFISCHER`, developed by Paul Fischer and `KSPGUESSPOD`

210: .seealso: [](ch_ksp), `KSPSolve()`, `KSPGuessDestroy()`, `KSPGuess`, `KSPGuessType`, `KSP`
211: @*/
212: PetscErrorCode KSPGuessCreate(MPI_Comm comm, KSPGuess *guess)
213: {
214:   KSPGuess tguess;

216:   PetscFunctionBegin;
217:   PetscAssertPointer(guess, 2);
218:   *guess = NULL;
219:   PetscCall(KSPInitializePackage());
220:   PetscCall(PetscHeaderCreate(tguess, KSPGUESS_CLASSID, "KSPGuess", "Initial guess for Krylov Method", "KSPGuess", comm, KSPGuessDestroy, KSPGuessView));
221:   tguess->omatstate = -1;
222:   *guess            = tguess;
223:   PetscFunctionReturn(PETSC_SUCCESS);
224: }

226: /*@C
227:   KSPGuessSetType - Sets the type of a `KSPGuess`

229:   Logically Collective

231:   Input Parameters:
232: + guess - the initial guess object for the Krylov method
233: - type  - a known `KSPGuessType`

235:   Options Database Key:
236: . -ksp_guess_type  <method> - Turns on generation of initial guesses and sets the method; use -help for a list of available methods

238:   Level: developer

240: .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPGuessType`, `KSPGuessRegister()`, `KSPGuessCreate()`
241: @*/
242: PetscErrorCode KSPGuessSetType(KSPGuess guess, KSPGuessType type)
243: {
244:   PetscBool match;
245:   PetscErrorCode (*r)(KSPGuess);

247:   PetscFunctionBegin;
249:   PetscAssertPointer(type, 2);

251:   PetscCall(PetscObjectTypeCompare((PetscObject)guess, type, &match));
252:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

254:   PetscCall(PetscFunctionListFind(KSPGuessList, type, &r));
255:   PetscCheck(r, PetscObjectComm((PetscObject)guess), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested KSPGuess type %s", type);
256:   PetscTryTypeMethod(guess, destroy);
257:   guess->ops->destroy = NULL;

259:   PetscCall(PetscMemzero(guess->ops, sizeof(struct _KSPGuessOps)));
260:   PetscCall(PetscObjectChangeTypeName((PetscObject)guess, type));
261:   PetscCall((*r)(guess));
262:   PetscFunctionReturn(PETSC_SUCCESS);
263: }

265: /*@C
266:   KSPGuessGetType - Gets the `KSPGuessType` as a string from the `KSPGuess` object.

268:   Not Collective

270:   Input Parameter:
271: . guess - the initial guess context

273:   Output Parameter:
274: . type - type of `KSPGuess` method

276:   Level: developer

278: .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessSetType()`
279: @*/
280: PetscErrorCode KSPGuessGetType(KSPGuess guess, KSPGuessType *type)
281: {
282:   PetscFunctionBegin;
284:   PetscAssertPointer(type, 2);
285:   *type = ((PetscObject)guess)->type_name;
286:   PetscFunctionReturn(PETSC_SUCCESS);
287: }

289: /*@
290:   KSPGuessUpdate - Updates the guess object with the current solution and rhs vector

292:   Collective

294:   Input Parameters:
295: + guess - the initial guess context
296: . rhs   - the corresponding rhs
297: - sol   - the computed solution

299:   Level: developer

301: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
302: @*/
303: PetscErrorCode KSPGuessUpdate(KSPGuess guess, Vec rhs, Vec sol)
304: {
305:   PetscFunctionBegin;
309:   PetscTryTypeMethod(guess, update, rhs, sol);
310:   PetscFunctionReturn(PETSC_SUCCESS);
311: }

313: /*@
314:   KSPGuessFormGuess - Form the initial guess

316:   Collective

318:   Input Parameters:
319: + guess - the initial guess context
320: . rhs   - the current right hand side vector
321: - sol   - the initial guess vector

323:   Level: developer

325: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
326: @*/
327: PetscErrorCode KSPGuessFormGuess(KSPGuess guess, Vec rhs, Vec sol)
328: {
329:   PetscFunctionBegin;
333:   PetscTryTypeMethod(guess, formguess, rhs, sol);
334:   PetscFunctionReturn(PETSC_SUCCESS);
335: }

337: /*@
338:   KSPGuessSetUp - Setup the initial guess object

340:   Collective

342:   Input Parameter:
343: . guess - the initial guess context

345:   Level: developer

347: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
348: @*/
349: PetscErrorCode KSPGuessSetUp(KSPGuess guess)
350: {
351:   PetscObjectState matstate;
352:   PetscInt         oM = 0, oN = 0, M, N;
353:   Mat              omat = NULL;
354:   PC               pc;
355:   PetscBool        reuse;

357:   PetscFunctionBegin;
359:   if (guess->A) {
360:     omat = guess->A;
361:     PetscCall(MatGetSize(guess->A, &oM, &oN));
362:   }
363:   PetscCall(KSPGetOperators(guess->ksp, &guess->A, NULL));
364:   PetscCall(KSPGetPC(guess->ksp, &pc));
365:   PetscCall(PCGetReusePreconditioner(pc, &reuse));
366:   PetscCall(PetscObjectReference((PetscObject)guess->A));
367:   PetscCall(MatGetSize(guess->A, &M, &N));
368:   PetscCall(PetscObjectStateGet((PetscObject)guess->A, &matstate));
369:   if (M != oM || N != oN) {
370:     PetscCall(PetscInfo(guess, "Resetting KSPGuess since matrix sizes have changed (%" PetscInt_FMT " != %" PetscInt_FMT ", %" PetscInt_FMT " != %" PetscInt_FMT ")\n", oM, M, oN, N));
371:   } else if (!reuse && (omat != guess->A || guess->omatstate != matstate)) {
372:     PetscCall(PetscInfo(guess, "Resetting KSPGuess since %s has changed\n", omat != guess->A ? "matrix" : "matrix state"));
373:     PetscTryTypeMethod(guess, reset);
374:   } else if (reuse) {
375:     PetscCall(PetscInfo(guess, "Not resettting KSPGuess since reuse preconditioner has been specified\n"));
376:   } else {
377:     PetscCall(PetscInfo(guess, "KSPGuess status unchanged\n"));
378:   }
379:   PetscTryTypeMethod(guess, setup);
380:   guess->omatstate = matstate;
381:   PetscCall(MatDestroy(&omat));
382:   PetscFunctionReturn(PETSC_SUCCESS);
383: }