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: }