Actual source code: iguess.c

  1: #include <petsc/private/kspimpl.h>

  3: PetscFunctionList KSPGuessList = NULL;
  4: static PetscBool  KSPGuessRegisterAllCalled;

  6: /*@
  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: /*@
 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 (fischer|pod)           - turns on generation of initial guesses and sets the method; see `KSPGuessType`
 71: . -ksp_guess_fischer_model model,size     - set details for the Fischer models
 72: . -ksp_guess_fischer_monitor (true|false) - 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 POD snapshots
 75: . -ksp_guess_pod_monitor (true|false)     - monitor the POD initial guess processing
 76: . -ksp_guess_pod_tol tol                  - tolerance to retain eigenvectors
 77: - -ksp_guess_pod_Ainner (true|false)      - use the operator as the inner product (must be SPD)

 79:   Level: developer

 81: .seealso: [](ch_ksp), `KSPGuess`, `KSPGetGuess()`, `KSPGuessSetType()`, `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 Keys:
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: /*@
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:   Level: developer

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

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

178: /*@
179:   KSPGuessCreate - Creates a `KSPGuess` context.

181:   Collective

183:   Input Parameter:
184: . comm - MPI communicator

186:   Output Parameter:
187: . guess - location to put the `KSPGuess` context

189:   Level: developer

191:   Notes:
192:   These are generally created automatically by using the option `-ksp_guess_type (fischer|pod)` and controlled from the options database.
193:   See `KSPGuessSetFromOptions()` for the `KSPGuess` options database keys

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

197: .seealso: [](ch_ksp), `KSPSolve()`, `KSPGuessDestroy()`, `KSPGuess`, `KSPGuessType`, `KSP`
198: @*/
199: PetscErrorCode KSPGuessCreate(MPI_Comm comm, KSPGuess *guess)
200: {
201:   KSPGuess tguess;

203:   PetscFunctionBegin;
204:   PetscAssertPointer(guess, 2);
205:   PetscCall(KSPInitializePackage());

207:   PetscCall(PetscHeaderCreate(tguess, KSPGUESS_CLASSID, "KSPGuess", "Initial guess for Krylov Method", "KSPGuess", comm, KSPGuessDestroy, KSPGuessView));
208:   PetscCall(MatStateInvalidate(tguess->omatstate));
209:   *guess = tguess;
210:   PetscFunctionReturn(PETSC_SUCCESS);
211: }

213: /*@
214:   KSPGuessSetType - Sets the type of a `KSPGuess`. Each `KSPGuessType` provides a different algorithm for computing the initial guess.

216:   Logically Collective

218:   Input Parameters:
219: + guess - the initial guess object for the Krylov method
220: - type  - a known `KSPGuessType`

222:   Options Database Key:
223: . -ksp_guess_type (fischer|pod) - Turns on generation of initial guesses and sets the method; see `KSPGuessType`

225:   Level: developer

227: .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPGuessType`, `KSPGuessRegister()`, `KSPGuessCreate()`, `KSPGUESSFISCHER`, `KSPGUESSPOD`
228: @*/
229: PetscErrorCode KSPGuessSetType(KSPGuess guess, KSPGuessType type)
230: {
231:   PetscBool match;
232:   PetscErrorCode (*r)(KSPGuess);

234:   PetscFunctionBegin;
236:   PetscAssertPointer(type, 2);

238:   PetscCall(PetscObjectTypeCompare((PetscObject)guess, type, &match));
239:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

241:   PetscCall(PetscFunctionListFind(KSPGuessList, type, &r));
242:   PetscCheck(r, PetscObjectComm((PetscObject)guess), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested KSPGuess type %s", type);
243:   PetscTryTypeMethod(guess, destroy);
244:   guess->ops->destroy = NULL;

246:   PetscCall(PetscMemzero(guess->ops, sizeof(struct _KSPGuessOps)));
247:   PetscCall(PetscObjectChangeTypeName((PetscObject)guess, type));
248:   PetscCall((*r)(guess));
249:   PetscFunctionReturn(PETSC_SUCCESS);
250: }

252: /*@
253:   KSPGuessGetType - Gets the `KSPGuessType` as a string from the `KSPGuess` object.

255:   Not Collective

257:   Input Parameter:
258: . guess - the initial guess context

260:   Output Parameter:
261: . type - type of `KSPGuess` method

263:   Level: developer

265: .seealso: [](ch_ksp), `KSPGuess`, `KSPGuessSetType()`
266: @*/
267: PetscErrorCode KSPGuessGetType(KSPGuess guess, KSPGuessType *type)
268: {
269:   PetscFunctionBegin;
271:   PetscAssertPointer(type, 2);
272:   *type = ((PetscObject)guess)->type_name;
273:   PetscFunctionReturn(PETSC_SUCCESS);
274: }

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

279:   Collective

281:   Input Parameters:
282: + guess - the initial guess context
283: . rhs   - the corresponding rhs
284: - sol   - the computed solution

286:   Level: developer

288: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
289: @*/
290: PetscErrorCode KSPGuessUpdate(KSPGuess guess, Vec rhs, Vec sol)
291: {
292:   PetscFunctionBegin;
296:   PetscTryTypeMethod(guess, update, rhs, sol);
297:   PetscFunctionReturn(PETSC_SUCCESS);
298: }

300: /*@
301:   KSPGuessFormGuess - Form the initial guess

303:   Collective

305:   Input Parameters:
306: + guess - the initial guess context
307: . rhs   - the current right-hand side vector
308: - sol   - the initial guess vector

310:   Level: developer

312: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
313: @*/
314: PetscErrorCode KSPGuessFormGuess(KSPGuess guess, Vec rhs, Vec sol)
315: {
316:   PetscFunctionBegin;
320:   PetscTryTypeMethod(guess, formguess, rhs, sol);
321:   PetscFunctionReturn(PETSC_SUCCESS);
322: }

324: /*@
325:   KSPGuessSetUp - Setup the initial guess object

327:   Collective

329:   Input Parameter:
330: . guess - the initial guess context

332:   Level: developer

334: .seealso: [](ch_ksp), `KSPGuessCreate()`, `KSPGuess`
335: @*/
336: PetscErrorCode KSPGuessSetUp(KSPGuess guess)
337: {
338:   PetscInt  oM = 0, oN = 0, M, N;
339:   Mat       omat = NULL;
340:   PC        pc;
341:   PetscBool reuse, same;
342:   MatState  matstate;

344:   PetscFunctionBegin;
346:   if (guess->A) {
347:     omat = guess->A;
348:     PetscCall(MatGetSize(guess->A, &oM, &oN));
349:   }
350:   PetscCall(KSPGetOperators(guess->ksp, &guess->A, NULL));
351:   PetscCall(KSPGetPC(guess->ksp, &pc));
352:   PetscCall(PCGetReusePreconditioner(pc, &reuse));
353:   PetscCall(PetscObjectReference((PetscObject)guess->A));
354:   PetscCall(MatGetSize(guess->A, &M, &N));
355:   PetscCall(MatGetState(guess->A, &matstate));
356:   PetscCall(MatStateCompare(matstate, guess->omatstate, &same));
357:   if (M != oM || N != oN) {
358:     PetscCall(PetscInfo(guess, "Resetting KSPGuess since matrix sizes have changed (%" PetscInt_FMT " != %" PetscInt_FMT ", %" PetscInt_FMT " != %" PetscInt_FMT ")\n", oM, M, oN, N));
359:   } else if (!reuse && !same) {
360:     PetscCall(PetscInfo(guess, "Resetting KSPGuess since %s has changed\n", matstate.id != guess->omatstate.id ? "matrix" : "matrix state"));
361:     PetscTryTypeMethod(guess, reset);
362:   } else if (reuse) {
363:     PetscCall(PetscInfo(guess, "Not resettting KSPGuess since reuse preconditioner has been specified\n"));
364:   } else {
365:     PetscCall(PetscInfo(guess, "KSPGuess status unchanged\n"));
366:   }
367:   PetscTryTypeMethod(guess, setup);
368:   guess->omatstate = matstate;
369:   PetscCall(MatDestroy(&omat));
370:   PetscFunctionReturn(PETSC_SUCCESS);
371: }