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

 25:   Level: developer

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

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

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

 43:   Not Collective

 45:   Level: developer

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

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

 62:   Collective

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

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

 78:   Level: developer

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

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

 93:   Collective

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

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

103:   Level: developer

105:   Notes:
106:   Ignored by the first and second Fischer guess types

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

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

121:   Collective

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

126:   Level: developer

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

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

148:   Logically Collective

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

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

157:   Level: developer

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

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

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

183:   Collective

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

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

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

202:   Level: developer

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

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

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

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

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

228:   Logically Collective

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

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

237:   Level: developer

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

246:   PetscFunctionBegin;
248:   PetscAssertPointer(type, 2);

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

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

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

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

267:   Not Collective

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

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

275:   Level: developer

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

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

291:   Collective

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

298:   Level: developer

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

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

315:   Collective

317:   Input Parameters:
318: + guess - the initial guess context
319: . rhs   - the current rhs vector
320: - sol   - the initial guess vector

322:   Level: developer

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

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

339:   Collective

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

344:   Level: developer

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

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