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:   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: /*@C
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:   *guess = NULL;
220:   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: /*@C
228:   KSPGuessSetType - Sets the type of a `KSPGuess`

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; use -help for a list of available methods

239:   Level: developer

241: .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPGuessType`, `KSPGuessRegister()`, `KSPGuessCreate()`
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: /*@C
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: }